EJB
昨日と今日は今更ながらEJBの講習でした。
そのときにEJBクライアントで気になる記述が。
前にSJC-BCを取得するために勉強した際にも
同じことが気になってたんよね。
何かというと、
InitialContext ctx = new InitialContext(); Object obj = ctx.lookup("java:comp/env/ejb/HogeHome"); HogeHome home = (HogeHome)PortableRemoteObject.narrow(obj,HogeHome.class);
この3行目の PortableRemoteObject.narrow()なんだけど。
InitialContext ctx = new InitialContext(); HogeHome home = (HogeHome)ctx.lookup("java:comp/env/ejb/HogeHome");
こんな感じでObjectをそのままHogeHomeにキャストできるのに、
なんでわざわざPortableRemoteObject.narrow()なんて使うの?
ググっても一般的にみんなそうやってるみたいだし。
いろいろ調べてみて、自分なりに出した答えは以下のとおり。
間違ってたらツッコミよろしくです。
まずEJBクライアントは、RMI/JRMPまたはRMI/IIOPでEJBを利用可能。
で、RMI/JRMPでEJBを呼び出した場合は、Javaネイティブな通信を
行うために、取得したObjectをそのままキャスト可能。
Java間だから問題ないと。
一方、RMI/IIOPでEJBを呼び出した場合は、Java以外との通信が
可能なプロトコルを使用するため、正しいJavaのクラス型で
取得することができない(もしくはできない可能性がある)ため、
PortableRemoteObject.narrow()で型変換を行う必要があると。
javax.rmi.PortableRemoteObject.narrow(Object obj, Class class) は
obj を 任意の class に cast するものです。CORBA 実装は一般的に
メソッド呼び出しの際本当のサーバーの型を返す替わりにシグニチャ
を返します。narrow() は引数で与えられたクラス型を解決するために
必要な場合はサーバーに対してRPC を行ないます。解決できなかった場合、
ClassCastException を throw します。
通常の Java の cast ではこの状況に対応できません。
EJB 1.1 の仕様で object の cast は常にこれを使用するよう定められました。
ということで、RMI/JRMPで必ず通信するということであれば
そのままキャストできるけど、RMI/IIOPで通信する可能性が
あるのであればPortableRemoteObject.narrow()を使う必要があると。
こんな感じの解釈でいいのかな。
RMI/JRMPの場合でもPortableRemoteObject.narrow()で
取得しても問題ないので、安全にいくなら
必ずPortableRemoteObject.narrow()を使用することかも。