DeltaSpikeのI18nタイプセーフメッセージを試してみる
DeltaSpikeのドキュメントを見ているとI18nという章があり、タイプセーフメッセージについて記載されていますが、今回はこれを少し試したいと思います。
DeltaSpikeではメッセージを扱うインターフェースを定義し、特定のメッセージを取得するメソッドをインターフェースに定義し、適切なアノテーションを付与することでメッセージの取得を行うことができるようです。文章で説明してもよくわからないと思うので、ドキュメントにある最も簡単なメッセージ出力例を少しアレンジしたもので紹介します。
@MessageBundle public interface HogeMessage { @MessageTemplate("hoge hoge") public String hogeHoge(); }
@MessageBundleはおまじないのようなものだと思ってください。ここで重要なのは必要なのはインターフェースのみで実装は必要ありません。メッセージを取得する側に当該メッセージバンドルインターフェースをDIし、hogeHogeというメソッドを呼び出すと@MessageTemplateで定義したメッセージ(hoge hoge)が取得できます。
実際メッセージは*.propertiesファイルに定義し読み込むことが一般的だと思いますが、DeltaSpikeでこれを行うにはまず@MessageBundleを付与したクラスと同名のプロパティファイルを同じパッケージ階層に作成します。
例えばHogeMessage.java(.class)のパッケージがorg.example.msgならばHogeMessage.propertiesファイルもorg.example.msgパッケージ配下に配置します。メッセージファイルに以下のようなメッセージが存在する場合、
hello_hoge=Hello hoge!!
当該メッセージを取得するためのメソッドに付与する@MessageTemplateにはキー名を"{"、"}"で囲った値を定義します。
@MessageTemplate("{hello_hoge}")
では、もう一歩進んでメッセージファイルのメッセージにプレースホルダを定義し、任意の値をバインドするにはどうするかというと、これはデフォルトではできないようです。DeltaSpikeにDefaultMessageInterpolatorというクラスがありますが、このクラスは受け取ったメッセージテキストをただ返却しているだけです。標準で{0}とかにバインドしてくれてもいいような気もしますが、泣き言いっても無いものは無いのでMessageInterpolatorインターフェースを実装して自分で組み込むしかないようです。
【MessageInterpolatorインターフェース実装例】
import org.apache.deltaspike.core.api.message.MessageInterpolator; public class MyMessageInterpolator implements MessageInterpolator { @Override public String interpolate(String messageText, Object[] arguments) { final MessageFormat format = new MessageFormat(messageText); return format.format(arguments); } }
メッセージファイルには次のようなメッセージを作成します。
hello=Hello {0} !
自作したMessageInterpolatorを利用するにはどうするかというと@MessageContextConfigアノテーションでMessageInterpolatorクラスを定義するだけです。
@MessageBundle @MessageContextConfig(messageInterpolator = MyMessageInterpolator.class) public interface ApplicationMessage { @MessageTemplate("{hello}") public String sayHello(String name); }
ここで、sayHelloというメソッドの引数にnameを設定しています。ApplicationMessage#sayHelloメソッド呼び出し側でsayHelloメソッドのnameに設定された値がメッセージファイルのプレースホルダ{0]にバインドされる訳です。
【呼び出し側】
@Inject private ApplicationMessage applicationMessage; ... public void hello() { String message = applicationMessage.sayHello("hoge"); }
なお、@MessageContextConfigではMessageInterpolator以外に、MessageResolverとLocaleResolverも独自クラスを組み込めるようになっています。
この辺は時間がありなおかつ気が向いたら紹介したいと思います。