JBossは人気のオブジェクト/リレーショナルマッピングフレームワークであるHibernateのバージョン4をリリースした。Hibernate 4の特徴は、
- マルチテナントサポート
- "サービス"APIの導入
- 国際化をサポートし、メッセージコードが利用できるロギング(slf4jではなくJBoss Logging経由)
- OSGIサポートの準備
- 廃止予定コードの整理と削除
マルチテナントは大規模な企業アプリケーションで、共有空間にすべてのデータを保持するかわりに、クライアント/カスタマー(テナントとも呼ばれる)を仮想的に分離する機能だ。これは管理がしやすくなり監視やセキュリティも改善する、大規模サービスプロバイダに好都合な機能だ。クラウド基盤を提供する企業もマルチテナント機能の恩恵を受けられる。この機能を実行するにはいくつかのやり方がある。
- 各クライアント/テナント毎に異なるデータベース/スキーマを利用する
- すべてのクライアントで同じデータベース/スキーマを使うがすべてのテーブルにデータをフィルタするためのカラム(例えば、tenant_idのような)を追加する
Hibernateは4.0のリリースで前者の方法をサポートする。後者の方法のサポートは次バージョンで計画されている。
"サービス"APIの仕様が追加されたのも重要だ。このAPIを使えば組み込みの標準的なサービスを超えて様々にHibernateを拡張できる。Hibernateの内部にプラグインを追加する機能は以前からあったが、新しいバージョンからはこのサービスAPIを使って拡張するのが正式なやり方になる。InfoQはプロジェクトの指導者であるSteve Ebersole氏に新しい機能について話を聞いた。
InfoQ: "サービス"の概念について教えてください。Hibernateの拡張だけに使うべきでしょうか。それとも、アプリケーションの開発者も利用できますか。
まず、多くのアプリケーション開発者はアプリケーション開発のひとつのルーチンとしてHibernate拡張を開発できるということを理解するのが重要です。カスタムのイベントリスナやカスタム型などを開発するということはHibernate拡張を開発するということです。これは一般的なシナリオです。
サービスAPIをドメイン固有のCDIでライフサイクルや依存性、JMXの管理などの共通の振る舞いや必要な処理に対して統一した操作方法を提供すると考えてください。こう考えると、開発者はかなりたくさんのサービスを開発しています。例えば、JMSに書き込むイベントリスナです。リスナや他のカスタムの拡張はJMSのコネクションを利用するので、JMSはサービスと見なすことができます。
しかし、サービスというアイディアは融通無碍です。"アプリケーションコード"がサービスを探して直接利用すると考えることができるでしょうか。一般的には考えられません。しかし、だれもがそう考えないというわけではありません。JMSのユースケースの話に戻りますが、アプリケーションコードがJMSのコネクションを通信する必要がある場合があります。この場合、アプリケーションコードはJMSのコネクションをHibernateから探すことができます。こうすることで、サービスのライフサイクルの管理をHibernateに移譲できます。
InfoQ: どうしてOSGIが重要なのですか。Hibernateはどの程度OSGIをサポートしていますか。
面白い質問です。OSGIをサポートしようとしたとき、"OSGIサポート"や"OSGI対応"というのはどういう意味なのかと尋ねる人のほとんどは、これがどういうことか分からない人であり、得られた答えも様々でした。私の考えでは2つの意味があります。
まず、HibernateはOSGI環境をロードするモジュールクラスを使えるでしょうか。4.0以前のバージョンではこれをやろうとするのはかなり難儀です。4.0以前のバージョンでは従来のClassLoaderの設定を想定しているからです。4.0では標準サービスとしてClassLoaderServiceがあります。これはHibernateがどのようにクラスやリソースを見つけるのかを定義し、標準のJavaのServiceLoadersをどのように解決するのかを定義します。ClassLoaderServiceはHibernateがクラスパスを利用するためのAPIを定義します。さらに重要なのはクラスのロードの方法が選択できるということです。普通とは違うクラスをロードする環境では、HibernateがどのようにClassLoaderを使うかを定義する独自のロード方法が使えます。この仕組みはJBoss ASでしっかりとテストされています。JBoss ASでは、カスタムのClassLoaderServiceを使ってモジュールクラスのロードを行っています。Hibernateでも同じことができるのです。
第二にHibernateはインポート/エクスポートの観点から見た場合、どの程度、しっかりと"OSGIメタデータ"を定義できるでしょうか。現時点では、HibernateはOSGI固有のメタデータすべてを定義しません。誰かが提供してくれたら取り込むつもりです。念頭に置いておく必要があるのは、HibernateのチームにはOSGIの専門家がいないということです。これは、誰かOSGIのメタデータに詳しく興味がある方に対処してほしい課題です。この点について4.0で前進したことのひとつはパッケージを分割して、対象となる利用者をよりはっきりさせました。私の考えが間違っていなければ、対象となる利用者とは適切なエクスポートを簡単に記述できるようにしてくれる人です。
InfoQ: なぜロギングのフレームワークを変更したのですか。
Hibernate 4の開発を始めたとき、ログ出力で国際化サポートが必要だということは決まっていました。そのとき、私たちが知っていたかぎりでは、パラメータ化を含む国際化機能をサポートしていたのはJBoss Loggingだけでした。JBoss Loggingの国際化サポートはGNU gettextのような方式であり、Hibernateの開発チームはこの方式の方がJavaのResouceBundleを使った方式よりも望ましいという合意に至りました。JBoss Loggingは例外メッセージも他と同じ方式で国際化をサポートしますが、現時点ではHibernateはこの機能を使っていません。
加えて、JBoss LoggingはResourceBundleの国際化で使われるキーとは別の概念として、メッセージキーを組み込みサポートします。このキーは出力されるメッセージを決定する条件に紐づく不変のキーです。これはFAQやドキュメントを作成するのにとても便利です。確かに、SLF4JやJava Util Loggingなどを合わせて使えば同じようなことを実現できるかもしれません。しかし、私はこのようなキーをファーストクラスとしてサポートするのは必須だと思います。このようなロギングをたくさん使う大規模なプロジェクトの場合、キーがユニークで一貫性があるかどうか検証しなければならないからです。JBoss Loggingは検証の仕組みも提供します。
InfoQ: 今回の新しい機能はほとんど内部的なものだという指摘があります。Hibernateはユーザが見える変更が必要なくなるほど成熟したということでしょうか。Hibernateはメンテナンスモードになったのでしょうか。
いいえ、Hibernateは新しい機能追加が必要ないメンテナンスモードになってはいません。メンテナンスが必要かどうかで言えばもちろん必要です。皆が気付いているわけではありませんが、Hibernateは10歳です。たくさんの絆創膏が重なっています。私たちが到達したのは、新しい機能を計画し実装するときに絆創膏の上に絆創膏を貼ってはならない状態です。HibernateはYAGNIの原則から生まれました。特に規約/APIは時間をかけて明確にしていくという考えに従って開発されています。なので、これからもこのようなブラッシュアップは続いていきます。
これほど実績があり成功したJavaのOSSプロジェクトは少数だと思います。そして、そのようなプロジェクトは一度か二度は大規模なリファクタリングを行っています。
InfoQ: Hibernate 5はどうなりますか。現時点の開発ではどこを目指していますか。
5.0では主にO/RメタデータとしてXMLやアノテーションから生成されるモデルの再設計に注力するつもりです。このモデルのコードは当初Hibernateが必要としていた以上に大きくなりました。JPAの新しい要件や機能開発はシンプルで変更もなかったのですが、多くのプロジェクトがこのコードを利用し、私たちもコードが分裂するのを最小限にしたかったため、結局コードが大きくなってしまったのです。しかし、本来はもっと早く再設計を行うべきでした。
Hibernate 4はすでにMaven Centralにあるので、Javaアプリケーションに組み込んで使える。