続・Wicket + Guice + warp-persist + JPA を試す
先日のエントリのやり方では Tomcat 上では動いても Glassfish では動かないことがわかりましたので、訂正します。
インジェクタの初期化を Wicket つまり、フィルタ(Wicket はフィルタとして動作している)で行ってはいけないようなので、リスナで初期化を行います。
package com.example.listener; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.servlet.GuiceServletContextListener; import com.wideplay.warp.persist.PersistenceService; import com.wideplay.warp.persist.UnitOfWork; import com.wideplay.warp.persist.jpa.JpaUnit; public class MyServletContextListener extends GuiceServletContextListener { @Override protected Injector getInjector() { // warp-persist の Guice モジュール生成 Module warpModule = PersistenceService.usingJpa().across(UnitOfWork.REQUEST).buildModule(); // Guice Injector を生成 return Guice.createInjector(warpModule, buildWebModule()); } private Module buildWebModule() { return new AbstractModule() { @Override public void configure() { // JPA の persistence.xml に記述している persistence-unit name を指定 bindConstant().annotatedWith(JpaUnit.class).to("persistence-unit name"); } }; } }
web.xml にリスナを追加します。
<listener> <listener-class>com.example.listener.MyServletContextListener</listener-class> </listener>
WicketApplication クラスの init メソッドは以下のようにします。
@Override protected void init() { super.init(); // サーブレットコンテキストからインジェクタを取得 Injector injector = (Injector) getServletContext().getAttribute("com.google.inject.Injector"); // Wicket にインジェクタを登録 addComponentInstantiationListener(new GuiceComponentInjector(this, injector)); }
Wicket + Guice + warp-persist + JPA を試す
Wicket と ActiveObjects の組み合わせが良いよ!という記事をかなり前に書きました。ところが、その「良さ」を発揮するための Databinder というプロダクトがなかなか Wicket 1.4.x に対応してくれない! んじゃあ、自分でやるぜ! と思って Databinder のソースを見てみたのですが、ちょっと厳しいところがありまして(Wicket 1.4 のジェネリクス対応のせい)Databinder の開発チームも同じところで悩んでいることがあとでわかりました。
ということで、Wicket と ActiveObjects の組み合わせが流行っているなんて言われる割に Databinder なしでみんなどうやってるんだろ? なんて思っていたところです。もしかして、DTO 的なものをわざわざ作っているのでしょうか? それとも Proxy を使ってる? 何にしてもいまいちスマートにならないんですよね、私の頭では。
となってくると、O/R マッパの再選考だ! となるわけです。そこで、今試しているのが JPA。半分食わず嫌いだったのですが、いままでよくつかってきた S2JDBC のエンティティがそのまま使えるし、この際やってみよう! となりました。S2JDBC を使わないのは、dicon の組み立てでハマりまくった経験が多く、さすがに疲れてきたからです。
で、そのまま JPA を使うのはおもしろくないので、warp-persist を使ってみました。バージョンは 2.0-20090214 です。これは何をするものかというと、
するものです。
使い方ですが、まず、WicketApplication クラスの init メソッドの例です。
@Override protected void init() { super.init(); // warp-persist の Guice モジュール生成 Module warpModule = PersistenceService.usingJpa().across(UnitOfWork.REQUEST).buildModule(); // Guice Injector を生成 Injector injector = Guice.createInjector(warpModule, buildWebModule()); // Wicket に登録 addComponentInstantiationListener(new GuiceComponentInjector(this, injector)); } protected Module buildWebModule() { return new AbstractModule() { public void configure() { // JPA の persistence.xml に記述している persistence-unit name を指定 bindConstant().annotatedWith(JpaUnit.class).to("persistence-unit name"); } }; }
次に DAO (S2JDBC 風にいえば Service)の作り方の例です。
package com.example.dao; import com.example.dao.impl.SomeEntityDaoImpl; import com.example.entity.SomeEntity; import com.google.inject.ImplementedBy; @ImplementedBy(SomeEntityDaoImpl.class) public interface SomeEntityDao { void someMethod(SomeEntity someEntity); }
package com.example.dao.impl; import javax.persistence.EntityManager; import com.example.dao.SomeEntityDao; import com.example.entity.SomeEntity; import com.google.inject.Inject; import com.google.inject.Provider; import com.wideplay.warp.persist.Transactional; @Transactional public class SomeEntityDaoImpl implements SomeEntityDao { @Inject private Provider<EntityManager> entityManagerProvider; @Override public void someMethod(SomeEntity someEntity) { EntityManager em = entityManagerProvicer.get(); // 処理 } }
最後に web.xml に以下の filter を追加
<filter> <filter-name>warpPersistFilter</filter-name> <filter-class>com.wideplay.warp.persist.PersistenceFilter</filter-class> </filter> <filter-mapping> <filter-name>warpPersistFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
以上です。JPA 自体の説明は今回は割愛します。
続・JInputでキーボードの状態を拾うプログラムをUbuntu上で動かしたら動かない
昨日のエントリのやり方では Ubuntu を再起動するともとにもどってしまうので、udev の設定をいじらないとダメだということが判明しました。
まず、デフォルトの設定ファイルを /etc にコピーします。
sudo cp 50-udev-default.rules /etc/udev/rules.d/
つぎのこの設定ファイルを修正します。
sudo vi /etc/udev/rules.d/50-udev-default.rules
24行目のあたりが以下のようになっていると思います。これは、デバイスのパーミッションを設定しているところで、なぜか所有者と所有グループ以外は読むことができなくなっています。
# input KERNEL=="mouse*|mice|event*", MODE="0640" KERNEL=="ts[0-9]*|uinput", MODE="0640" KERNEL=="js[0-9]*", MODE="0644"
これを↓こんな塩梅に修正します。
# input KERNEL=="mouse*|mice|event*", MODE="0644" KERNEL=="ts[0-9]*|uinput", MODE="0644" KERNEL=="js[0-9]*", MODE="0644"
これで再起動すれば今渡こそ解決。
JInputでキーボードの状態を拾うプログラムをUbuntu上で動かしたら動かない
なんでか調べてみたら、JInput が読み込もうとしている /dev/input/* が所有者(つまり root)しか読めないパーミッションになっていたからでした。
chmod go+r /dev/input/*
これで解決。
教育を通してわかった「Wicketの良さ」
ここのところJavaによるWebアプリケーションの経験が皆無な人にいろいろ教育してみてわかったのですが、教育の観点からするとWicketはとてもいいですね。
つまり、学習コストが低い。
故あってWicketとともにSlim3も学習対象にしているので、Slim3のような「薄い」フレームワークとの対比となるのですが、以下のような学習コストの低減にあたっての利点がありました。
- HTTP そのものの知識がほぼ不要。
- テンプレート(View層)の作成には HTML の知識だけでほぼことたりる。
- ページ間の値の引渡しについて特別に設計、考慮の必要がない。
ただし、Wicketはリソース食いな上にデフォルトのパスがカッコ悪いので、BtoCのWebサービスにはあまり向かないでしょう。逆に従来のC/S型の社内システムをWebベースでリプレースしたいときなどには威力を発揮すると思います。
Scala で何を書いているのか
JOGL 使ってゲームを作ってみています。さて、どれぐらいのパフォーマンスがでるのか。
Scala 用 IDE はどれがいい?
現在いろいろ試しているところです。
Scala IDE for Eclipse
Java の IDE として高いシェアを誇る Eclipse。私も一番慣れているのがこれ。Scala も Eclipse で扱えたら嬉しい。ということで使ってみた。
Scala Plugin for IntelliJ IDEA
最近 Community Edition もリリースされて、大手を振って使えるようになった IDE。Google の人も使ってるらしいので、使ってみた。
- IntelliJ IDEA 自体が英語。日本語のメッセージリソースを持っていないっぽい。
- 前出の2つに比べて Scala IDE としての完成度が高い。
- コードフォーマットはもちろんのこと、リファクタリングもできる。
- JDK のクラスライブラリをスタティックインポートして使うと「このインポートは使っていないから消せ」的な警告が出る。Scala で作ったものからは出ない。
- 入力補完の性能はまあまあ。インポートされていないクラスは入力補完できないっぽい(設定か?)
- キーバインドを「Eclipse 風」にしてもやっぱり細かく違う(実行とか)。
ということで使い物になるのは今のところ IDEA だけなんだけど、いかんせん英語が……。
Eclipse プラグインは次バージョンでだいぶ良くなると聞くけど、ほんとかなぁ。