S-JIS[2008-12-01/2008-12-11] 変更履歴

JBossASのRMI

JBossASでRMIを扱う方法。


インターフェースの作成

まず、インターフェースを作る。
このインターフェースを経由してクライアントからメソッドを呼び出すことになる。

RmiSample.java

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」を付ける必要がある。


インターフェースの実装

次に、インターフェースを実装したクラスを作る。
このクラスのインスタンスが実際に呼ばれることになる。

RmiSampleImpl.java

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する必要がある。


JNDIへの(クラスの)登録

(実行時に)実装クラスのインスタンスを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()は、そのサーブレットが初めてインスタンス化するときに一度だけ呼ばれる。
(そのサーブレットにブラウザーからアクセスしないとインスタンス化されないけどね)


JNDIからの(クラスの)取得

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);

JNDIへの(唯一のインスタンスの)登録

毎回同一のインスタンスへアクセスする為には、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]


JBossASへ戻る / RMIへ戻る / WebLogicのRMIへ行く / Java目次へ行く
メールの送信先:ひしだま