行く記憶の流れは絶えずして

戻ってこないのでメモするところ

Dropwizardをデプロイ後、8時間後にDB接続エラー

デプロイしていよいよ起動、明くる日に様子を見るとページからログインできない。
ログインボタンを押してもレスポンスがない。
応答を見ると[500 Internal Server Error]。
バグ?ログを見てみると以下。

f:id:taketsuru:20150503013213p:plain


とか出ている。autoReconnect=trueにすると解決すると誘われている。

デフォルトでは最後の接続から8時間経つと切断されるらしい。

調べるとmysqlのpathの最後に?autoreconnect=trueで解決するとか。

しかし非推奨で、コネクションプーリングしなさいとのこと。
dropwizard特有のやり方とかあるんじゃないのとさらに調べる。

見つかる。例によって外人。

java - Broken Pipe exception in Dropwizard application - Stack Overflow

 

  1. 設定+αで解決した報告

    • checkConnectionWhileIdle: true
    • checkConnectionOnReturn: true
    • checkConnectionOnBorrow: true


    とソースのトランザクション境界で直ったらしい。(関係ない気がするけど)
    自分のやつはユーザー認証と掲示板読み書き程度、それぞれでAbstractDAOの継承クラスによるアクセスと@UnitOfWorkをつけているのでいいはず。

  2. コネクションプーリングしなさい

    1の投稿のすぐ下にある。Manageを使おうとのこと。
    ManagedPooledDataSource.javaとかいうド直球なソースが紹介されているけど、
    これとdropwizard-hibernateを絡ませなきゃいけない。すぐには手が出せそうにないので後回し。

今回は1の方法で、最後の接続から8時間後に接続して解決したのでひとまず良しとします。

puttyとsshの違い

VPSにはずーっとputtyでアクセスしてきましたが、

勉強も兼ねてssh(linuxクライアント)でもアクセスしてみました。

 

主な違いは鍵。

それぞれ特有の鍵をそれぞれで生成します。

サーバーに公開鍵、クライアントが秘密鍵を使用するのは基本。

linuxクライアントでは秘密鍵パーミッションを400にしないと怒られる。

 

  1. 鍵の生成、それぞれパスワードを指定

  2. サーバーに登録

    • どちらも拡張子pubのファイルを使用
    • cat ***.pub >> .ssh/authorized_keys
  3. アクセス

sshはコマンドなので一例を。

オプションをファイルに書いておく方法もあるらしいけど今回はパス。

  • ssh user@url -p 12345 -i ***.ppk

    • 普通のログイン用
    • urlのサーバーにuserでログイン
    • サーバーのsshポートは12345
    • 秘密鍵として***.ppkを使用
  • ssh user@url -p 12345 -N -f -L 23456:localhost:34567

    • トンネル用
    • urlのサーバーにuserでログイン
    • サーバーのsshポートは12345
    • ログイン後バックグラウンドへ(-f)
    • ログイン後何もしない(-N)
    • クライアントのポート23456にアクセスすると
      サーバーから見えるlocalhostのポート34567に転送する

一番下が一番ややこしい。

Dropwizardのassetsに/をmappingしたい

Dropwizardにおいて、静的なファイル(html, js, css…)はデフォルトでは

  • http://{ドメイン}/assets/* → "src/main/resources/assets/*"

となっています。

 

ですが、トップページなどはURL直接指定でアクセスできると格好良かったりします。

先記のデフォルトは一応AssetBundleを使用することで変更できますが

ルートにはできない仕様らしいです。

Asset bundles not able to be served from root path. · Issue #661 · dropwizard/dropwizard · GitHub

 

Google先生に聞くと外人がたくさん困ってましたが、

ログを一生懸命漁っていると解決した声を見つけました。

上記リンクの下のほうにあり、まとめると

  1. Application#initialize()において

    bootstrap.addBundle(new AssetsBundle("/assets/", "/"));
  2. Application#run()において

    environment.jersey().setUrlPattern("/services/*");

1つめでやりたいことやって(従来はだめでしたが)、

2つめでjerseyのマッピングをしています(ここでは"/services/"以下)。

Dropwizardのjerseyはルートがデフォルトなので、

2つめがないと静的ファイルをjerseyで解決しようとして404になります。

( 2つ目の項目ですが、公式ドキュメントにあるように、

設定ファイルにapplicationContextPathを設定してもうまく動作しませんでした。)

 

日本語が少なくて大変…

DropwizardにおけるHibernateでのテーブル名定義箇所

今回一番引っかかったところ。

 

Dropwizardに組み込まれているHibernateのテンプレートクラスは、

  1. 設定ファイルに接続情報を記載
  2. Pojoの定義
  3. AbstractDAOの継承
  4. HQLを@NamedQueryで宣言、呼び出し
  5. サービス登録

って感じでマッピングxmlをいちいち作成しなくて便利。

だが、テーブル名の定義が@Tableと@NamedQuery内の2箇所であり、

どっちを使ってるのかいまいち。

 

そこで実験してみました。

というより今回引っかかったのでついでにいろいろ試しただけです。

 

大文字小文字の区別をこんな感じでしてみました。

Dropwizardのバージョンは0.7.0です。

NoSQLテーブル名POJOクラス名@Table@NamedQuery結果
1 BBSDATA BBSData BBSData BBSData クエリ呼び出し時にNG
MySQLSyntaxErrorException: Table 'Schema.BBSData' doesn't exist
2 BBSDATA BBSData BBSData BBSDATA Dropwizard起動時にNG
QuerySyntaxException: BBSDATA is not mapped
3 BBSDATA BBSData BBSDATA BBSData OK
4 BBSDATA BBSData BBSDATA BBSDATA Dropwizard起動時にNG
QuerySyntaxException: BBSDATA is not mapped
5 BBSDATA BBSDATA BBSData BBSData Dropwizard起動時にNG
QuerySyntaxException: BBSData is not mapped
6 BBSDATA BBSDATA BBSData BBSDATA クエリ呼び出し時にNG
MySQLSyntaxErrorException: Table 'Schema.BBSData' doesn't exist
7 BBSDATA BBSDATA BBSDATA BBSData Dropwizard起動時にNG
QuerySyntaxException: BBSData is not mapped
8 BBSDATA BBSDATA BBSDATA BBSDATA OK

 

意外だったのがPOJOのクラス名をみている?こと。

 

考察してみる。

  • No1とNo3より、SQL問い合わせは@Tableを使用してるっぽい。
  • No2、4、5、7より、"not mapped"と叱られているのは@NamedQuery。
  • また、No2、4、5、7はPOJOクラス名≠@NamedQuery。
  • 成功しているNo3、No8POJOクラス名=@NamedQuery。

 

これらより、

@NamedQueryに出てくるPOJOクラス名を@Tableで置換しているのか?

と推測。

 

 

Dropwizard勉強中のTips②

考えてみれば当たり前なんだけど、Dropwizardはjerseyを使ってるから

調べるときもjersey(JAX-RS)で検索したほうがかかりやすい、と。

 

ただ、今使ってるのDropwizardは0.7。

0.8がすでに存在し、jerseyのバージョンが上がって結構変わるらしい。

HK2とか言う記述をチラッと見たけど、

とりあえず0.7で一通り完成させてから対応させるつもり。

 

  1. @Entityのあるpojoはスコープのどれかに@Idが必要.

    tableではなくviewにマッピングすると忘れがち。

    たまたまUniqueな値がいたからそれにしたけど、違うと何かあるのかな。

  2. @ContextでHttpSessionを扱いたい場合はHttpSession,SessionHandlerの登録が必要。

jQuery Mobile覚書(form周り)

  1. jQuery Mobileでformのpost送信したければformの属性にdata-ajax="false"を指定。

    一括指定する方法もあるらしいけど、今回はこっち。

    ( $.mobile.ajaxFormsEnabled = false をjQuery mobile.jsの読み込み前に実行:

    jQuery Mobile の Ajax を使用したページやフォーム遷移を無効にする - 暇人じゃない )

  2. 普通のformだと$.postの引数に$(form).serializeArray()を使っていたが、

    jQuery Mobileはformの構造を変えるので使えない

    <form><input></form>が<form><div><input></div></form>みたいに変化し、レイアウト用のdivが挟まる。

    その結果inputはformの直接の子ではなくなるので反応しなくなるっぽい。

MySQL覚書(foreign keyなど)

  1. foreign keyを使いたければInnoDB

    MySQL(5.1.73)でのデフォルトはMyISAMというものらしい。

    さくっと調べた結果、MyISAMのほうが機能で劣る代わりに速いと解釈しました。

  2. foreign keyで制約するテーブル(例:売り上げレコード)はInnoDBである必要が有るのは分かるけど、

    制約のために参照する側(例:店舗一覧)もInnoDBでなければならない。注意。

  3. SQLでUnsignedの整数のデータをhibernateマッピングしたい場合、

    そのデータを表現できる整数型(int(11) unsignedならlong)でOK。