JBossASでRMIを扱う方法。
|
|
まず、インターフェースを作る。
このインターフェースを経由してクライアントからメソッドを呼び出すことになる。
package jp.hishidama.rmi; import java.rmi.Remote; import java.rmi.RemoteException; public interface RmiSample extends Remote { public String getMessage() throws RemoteException; }
JBossのRMIでは、各メソッドに「throws RemoteException」を付ける必要がある。
次に、インターフェースを実装したクラスを作る。
このクラスのインスタンスが実際に呼ばれることになる。
package jp.hishidama.rmi;
import java.io.Serializable;
public class RmiSampleImpl implements RmiSample, Serializable {
private static final long serialVersionUID = 960582942208877131L;
private java.util.Date date = new java.util.Date();
public String getMessage() {
String home = System.getProperty("jboss.home.dir");
return "RmiSampleImplメッセージ: " + this + " / " + home + " / " + date;
}
}
JBossのRMIでは、Serializableをimplementsする必要がある。
(実行時に)実装クラスのインスタンスをJBossのJNDIへ登録(バインド)する。
以下の例では、RmiSampleNameという名前を付けてバインドしている。
public static void main(String[] args) throws NamingException { InitialContext ctx = initContext(); Object obj = new RmiSampleImpl(); ctx.rebind("RmiSampleName", obj); }
public class RmiServlet extends HttpServlet { @Override public void init() throws ServletException { try { InitialContext ctx = new InitialContext(); Object obj = new RmiSampleImpl(); ctx.rebind("RmiSampleName", obj); } catch (NamingException e) { throw new ServletException(e); } } 〜 }
サーブレットのinit()は、そのサーブレットが初めてインスタンス化するときに一度だけ呼ばれる。
(そのサーブレットにブラウザーからアクセスしないとインスタンス化されないけどね)
JBossのJNDIの機能を利用して、リモートオブジェクト…JNDIに登録されているインスタンスを取得する。
public static void main(String[] args) throws NamingException { InitialContext ctx = initContext(); RmiSample rs = (RmiSample) ctx.lookup("RmiSampleName"); String msg = rs.getMessage(); System.out.println(msg); }
インターフェース経由で呼び出すことで、インスタンスのメソッドが呼ばれる。
しかしこの登録の仕方だと、lookup()の度に毎回インスタンスが作られるようだ。
(WebLogicでは、これと同様のやり方で同一のインスタンスへのアクセスとなるのだが。)
つまり、リモートオブジェクトへのアクセスでなく、lookup()を実行しているVM内にインスタンスが作られて、そのメソッドが呼ばれることになる。
毎回新しいインスタンスが返されるとは言ってもコンストラクターは呼ばれないし、clone()が使われているわけでも無さげ。けっこう不思議。
bind()の際に別のクラス(無名クラスとか)にして登録すると、そのクラスのインスタンスがちゃんと取れる。
Object obj = new RmiSampleImpl() { public String getMessage() { return "別物"; } }; ctx.rebind("RmiSampleName", obj);
毎回同一のインスタンスへアクセスする為には、UnicastRemoteObjectを使ってエクスポートして登録(バインド)する。
public static void main(String[] args) throws NamingException { InitialContext ctx = initContext(); RmiSampleImpl rs = new RmiSampleImpl(); Object obj = UnicastRemoteObject.exportObject(rs, 0); ctx.rebind("RmiSampleName", obj); }
オブジェクトの取得側のコーディングは全く同じままで、リモートにある同一のインスタンスへアクセスできるようになる。
なお、JBossAS4.2.3では、rmicによるスタブ・スケルトンの作成は不要。(JDK1.5以降だから)[2008-12-11]