Chonaso's Commentary

InternetやIT技術などについて知ったこと、試したこと、考えたことを書いていきます。

Doma勉強会 in 東京に行ってきました #doma_tokyo #eventdots

DomaJava のDBアクセスフレームワークです。(Welcome to Doma — Doma 2.0 ドキュメントより)

私が仕切る案件では基本的にDomaを使っています。 部門的にはSeasar2+S2JDBCがスタンダードでしたが、Seasar2が公式アップデートはぼちぼち終了になるので、 今後の案件はおそらくSpring+Domaという組み合わせになるでしょう。

ちなみに私がDomaを選んだ理由は以下の通りです。

  • JavaコードとSQLを完全分離できる
  • SQLを知らないと使えない(強く意識させる)
  • 2Way SQLが使える
  • 特定のフレームワークにロックしない
  • 多くのRDBに対応している

また、実際に使っていてよいと感じた点が以下の通りです。

  • 静的チェックが強力
  • SQLJavaコードの行き来が簡単
  • ドメインクラス機能が超便利

では本編。主に感想です。

Domaの紹介

http://backpaper0.github.io/ghosts/doma-intro.html

  • Domaの機能の紹介ですが、Domaは結構ハイペースでバージョンアップを続けていてフォローしきれていない機能(Embeddableなど)があったので、改めて勉強になりました。
  • EntityListenerでDIってよさげですね。たぶん今度使います。
  • どこかで発表があったかもしれませんが、doma-genなどの細かい(深い)話も聞いてみたいなぁ、と個人的に思いました。

ドメインクラスの話

http://backpaper0.github.io/ghosts/doma-domainclass.html

  • Domaという名前の由来でもあるドメインクラスの話。
  • ドメインって意味が広すぎてつらい、っていう意見ももっともですが、仕方ないですね。
  • 私の身の回りではDomaのおかげで「Enum値をgetValueして比較する」みたいな悲しいコードが無くなりました。
  • 「どこまでドメインクラス化するか」問題は皆共通の悩みだったようです。設計書にドメイン一覧とか書く案件だったら全部クラス化してもいい気がしますね。

とあるDoma2の使い方

http://gakuzzzz.github.io/slides/doma_practice/

  • 関数型ゴリゴリなDoma2の使い方。Java8 Stream APIを理解していない人は見ても仕方ないスライドです。逆に理解している人にとっては非常に面白い教材ですね。
  • というかDoma 2 素案 · GitHubで見かけたやり取りに対するアンサーだなぁ、と思ったら発表者はコメント付けた方でした。
  • IN句、NOT IN句にNULL入れた時の挙動って調べたこともなかったなぁ。

Domaの開発で大切にしている10のこと - Qiita

http://qiita.com/nakamura-to/items/099cf72f5465d0323521

  • Doma開発者の中村さんの発表。Domaの開発ポリシーについてです。
  • さりげなくJPA以外のCriteriaフレームワークにフォローを入れつつも、どの程度Criteriaを使うか、に対する一つのアンサーとも言えます。
  • 個人的には概ね同意というか、S2DAOからS2JDBCに移ることに納得のいかなかった人々へのノアの方舟といった感じです。
  • 逆に全体的に同意しかねる!っていう人は他のフレームワークに移った方がいいかもしれない、そんな内容です。(この辺りは唯一の正解は無い話ですね)
  • 実は私もツイートを拾ってもらって、Domaに反映されたことがあります。(たまたまリリース候補と合致してただけかもしれません) https://twitter.com/chonaso/status/683506363553583104

(LT)Doma2とMVC1.0でJava EE Webアプリを作ろう! // Speaker Deck

https://speakerdeck.com/masatoshitada/doma2tomvc1-dot-0dejava-ee-webapuriwozuo-rou

  • SpringBoot with Doma2対抗のPayara Micro with Doma2。
  • Domaとは全然関係ないですが、JerseyMVCじゃなくMVCでもいいかもね、ってちょっと思いました。

(LT)Doma2 with Kotlin

http://www.slideshare.net/yyyank/doma2-with-kotlin

  • Kotlinって正直ほとんど言語仕様をフォローしていないんですが、KotlinがサポートしてるのってJava6なんですね...
  • Kotlin関係ないですが、Domaって手軽にJDBCを使うツールとしても使えるんだなぁと認識させられました。

その他質問など

  • Q:せっかくなのでちょっと気になってた件。

    A:データソースごとにパッケージ分けた方がいいです。

  • あの場では特に聞かなかったですが、ドメイン使いだすとありがちな「DAOメソッドをオーバーロードしたい」問題って私だけですかね?

まとめ

  • Domaを好んで使う人たちの集まりだけあって「Doma最高!」連呼の若干宗教じみた雰囲気を感じました。
  • 今回発表されたスライドではないですが、これも面白いです。

Domaで複数データベースを扱う

きちんと探せばサンプルありそうな気がするんですが、こんな感じで解決しました、という一例として残しておきます。


Domaを使い始めて2年以上経ってるはずなんですが、振り返ると複数データソースは初めてでした。

daoやentityのパッケージングはどうしたものかなぁ、という課題を残しつつもとりあえず2つのデータベースを同時に扱えるようにConfigクラスやbuild.gradleを2つ準備してDoma-genまで上手く行ったのでアプリ起動!

と思ったらエラー。

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.seasar.doma.jdbc.Config] is defined: expected single matching bean but found 2: HogeDatabaseConfig,FooDatabaseConfig

まだSpringは慣れてないけど、DI候補が2つあるからDIできないぞ、と怒られているというのは何となくわかりました。

問題の箇所はDAOから生成されたクラス(XxxDaoImpl)内のコンストラクタで、ConfigをDIしようとしている部分です。

    /**
     * @param config the config
     */
    @org.springframework.beans.factory.annotation.Autowired()
    public HogeDaoImpl(org.seasar.doma.jdbc.Config config) {
        super(config);
    }

DBが一つなら型インジェクションが普通に決まるので問題無く動くのですが、 エラーメッセージにあるHogeDatabaseConfigとFooDatabaseConfigはそれぞれorg.seasar.doma.jdbc.Configを実装したクラスなので確かにこれは動かないですね。

ってことで、それぞれのConfigクラスに名前を付けて、 DAO側では@Qualifierでその名前を指定するようにしました。

その結果、自動生成部分はこのようになりました。

    @org.springframework.beans.factory.annotation.Autowired()
    public HogeDaoImpl(@org.springframework.beans.factory.annotation.Qualifier("HogeDatabaseConfig") org.seasar.doma.jdbc.Config config) {
        super(config);
    }

これできちんと動いたので、doma-genのdao.ftlも修正しておしまい。


追記

確かに!

ということで修正しました。

S2DBCPのコネクションプール状態の取得

今さらSeasar2関連です。 HikariCPのデバッグログではコネクションプールの状況を逐一ログに出してくれるのですが、 S2DBCPはそういう機能が見つからなかったので作ってみました。

SAStrutsのアクションとして実装しています。

一つのアプリで複数のプールを使うこともありますので、全部出すようにしています。

Zabbix アクションが発動しない時にチェックする項目

自分用メモ。徐々に追記していきます。

  • アクションが発動しない(メールが飛ばない、など)

    • アイテム
      • 正しく取得できているか
        • 有効/無効
        • 実行間隔
        • 種別は正しいか(数値、文字列、ログ...)
    • トリガー
      • イベントが発生しているか
      • (ログの場合) ステータスが正常状態か or 「障害イベントを連続して生成」にチェックがついているか
    • アクションの条件
      • 有効/無効
      • トリガー(深刻度)
      • アイテム(アプリケーション)
    • ユーザ
      • メディア(深刻度)
      • ユーザグループ
        • 有効/無効
        • 権限
          • ホストグループ
          • テンプレートグループ

これらの掛け合わせなので、どれかが間違ってるとアクションは発動しません。

Zabbix難しいよ、って言う人はこの辺の理解でつまづいているように見えます。

理解できてもなかなかサクッと発動してくれなかったりするんですよね。何かいいテスト・デバッグ方法はないものでしょうか。

Bootstrapのbtnとdisabled

BootstrapのCSSを適用するとbutton以外のタグでもボタン化することが可能です。 さらにdisabledなどの状態も含めたCSSがセットになっているのでデザインにこだわらないWebアプリを開発する際には非常に重宝します。

これにAngularJSのng-clickやng-disabledなどを組み合わせることでお手軽にUIパーツが組めるのですが、どのタグにボタンを適用するかをその場のフィーリングで決めていたら軽く痛い目に遭いました。

具体的にはAタグをボタン化していたものについて、ng-disabledが効かずクリックできてしまうというものです。

ng-disabledが効かないというのは半分間違っていて、見た目上はdisabledなのですがクリック出来る状態で、見ただけじゃ気付かない罠でした。(マウスオーバーでカーソルも禁止マークになります)

サンプル http://plnkr.co/edit/sDYTmQFBUdc9VcxSw0BZ?p=preview

class="btn"はdivやspanでも使えますが、やっぱりクリックが発動します。

BeanValidatorをJava8 Streamで書く

コードレビューしてて思ったのが、BeanValidatorの処理ってJava8ならもうちょっとスマートに書けるのではないか、ということ。

どうせみんなコピペしてるんでしょ?と思ったので書いてみました。

ちょこっとスッキリしました。

後で自分がコピペして使う用として残しておきます。

どうせこの形で使うことがほとんどでしょうから、staticなメソッドになっててもいいような…。

AngularJS & Jerseyでファイルアップロード&JSONでパラメータ連携

Jerseyでのファイルアップロードって、よく見かけるサンプルではファイルもパラメータもmultipart/form-dataで一緒くたにされてしまいますが、実際にはパラメータ内に配列やオブジェクトが含まれていることが多いので、やっぱりいつも通りJSON経由で一撃でバインドしたいですよね。

続きを読む