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 は常にこれを使用するよう定められました。


http://java-house.jp/ml/archive/j-h-b/040193.html

ということで、RMI/JRMPで必ず通信するということであれば
そのままキャストできるけど、RMI/IIOPで通信する可能性が
あるのであればPortableRemoteObject.narrow()を使う必要があると。


こんな感じの解釈でいいのかな。
RMI/JRMPの場合でもPortableRemoteObject.narrow()で
取得しても問題ないので、安全にいくなら
必ずPortableRemoteObject.narrow()を使用することかも。