RMIのサンプルコード その1

RMIの簡単なサンプルコードを書いた時のメモです。

使用したJ2SEのバージョン:1.4.2_08

1.D:\RMI_HELLO\examples\rmiフォルダを作成し、以後プログラムはこのフォルダ以下に保存します。

2.以下のようなクライアントから呼び出せるメソッドを定義したリモートインターフェイスを作成します。

Hello.java

package examples.rmi;

import java.rmi.Remote;
import java.rmi.RemoteException;

/**
 * 
 * リモートインターフェイスは以下二つの条件を満たさなくてはいけません。
 * 
 * 1.java.rmi.Remoteを継承します。
 * 
 * 2.定義したメソッドはRemoteExceptionをスローするようにします。
 * 
 */
public interface Hello extends Remote {
	
	public String sayHello(String name) throws RemoteException;
}

3.サーバー側に設置するプログラムを作成します。

HelloImpl.java

package examples.rmi;

import java.rmi.RemoteException;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.server.UnicastRemoteObject;
import java.net.MalformedURLException;

/**
 * 
 * サーバー側のプログラムは以下四つの条件を満たす必要があります。
 * 
 * 1.Helloインターフェイスを実装する。
 * 
 * 2.java.rmi.server.UnicastRemoteObjectを継承する。
 * 
 * 3.RemoteExceptionをスローするためにコンストラクタを用意する。
 * 
 * 4.Helloインターフェイスで用意したメソッドを実装する。
 * 
 */
public class HelloImpl extends UnicastRemoteObject implements Hello {
	
	protected HelloImpl() throws RemoteException {
		super();
	}
	
	public String sayHello(String name) throws RemoteException {
		
		return name + "さん、こんにちは";
	}
	
	public static void main(String[] args) {
		
		if (System.getSecurityManager() == null) {
			// セキュリティマネージャーの設定
			System.setSecurityManager(new RMISecurityManager());
		}
		
		try {
			// インスタンスを生成
			HelloImpl hello = new HelloImpl();
			
			// rmi://localhost/HelloServerというURIを生成します。
			StringBuffer url = new StringBuffer();
			url.append("rmi://");
			// プログラム実行時にlocalhostという文字列を引数で渡してargs[0]の値をlocalhostとする。
			url.append(args[0]);
			url.append("/HelloServer");
			
			// rmiregistryに生成したオブジェクトであるhelloをrmi://localhost/HelloServerという名前で登録します。
			Naming.rebind(new String(url), hello);
			
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}
}

4.クライアント側プログラムの作成

HelloClient.java

package examples.rmi;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

/**
 * 
 * @author kota
 * 
 */
public class HelloClient {
	public static void main(String[] args) {
		
		// rmi://localhost/HelloServerという文字列を生成します。
		StringBuffer url = new StringBuffer();
		url.append("rmi://");
		url.append(args[0]);// プログラム実行時にlocalhostという文字列を引数で渡してargs[0]の値をlocalhostとする。
		url.append("/HelloServer");
		
		try {
			// rmiregistryからrmi://localhost/HelloServerという名前のオブジェクトを探してHelloにキャストします。
			Hello obj = (Hello) Naming.lookup(new String(url));
			
			// プログラム実行時、第二引数に指定した文字列をsayHelloメソッドに渡してsayHelloメソッドを実行します。
			System.out.println(obj.sayHello(args[1]));
		} catch (MalformedURLException e) {
			
			e.printStackTrace();
		} catch (RemoteException e) {
			
			e.printStackTrace();
		} catch (NotBoundException e) {
			
			e.printStackTrace();
		}
		
	}
	
}

5.Hello.java、HelloImpl.java及びHelloClient.javaコンパイルします。

6.rmic examples.rmi.HelloImplと実行する事によって、以下の二つのクラスファイルが生成されます。

  • HelloImpl_Stub.class
  • HelloImpl_Skel.class

補足:J2SE5.0環境化でrmic examples.rmi.HelloImplと実行したところ、スタブクラスは生成されましたが、スケルトンクラスは生成されませんでした。

参考になるサイト:JavaTM RMI リリースノート

補足の追加:スケルトンクラスがなくてもプログラムは動きました。

7.コマンドプロンプトを起動し、クラスファイルが無いディレクトリーでstart rmiregistryコマンドを実行して下さい。

8.D:\RMI_HELLO\examples\rmi以下にpolicy.txtを作成します。

policy.txt

grant {
	permission java.security.AllPermission;
};

9.コマンドプロンプトを起動して以下のコマンドを実行します。以下のコマンドはD:\RMI_HELLO\examples\rmi\にスタブを置いたときの例です。

D:\RMI_HELLO\examples\rmi\の最後の\を必ず付けて下さい。

D:\RMI_HELLO>java -Djava.rmi.server.codebase=file:///D:\RMI_HELLO\examples\rmi\
-Djava.security.policy=.\examples\rmi\policy.txt examples.rmi.HelloImpl localhost

10.コマンドプロンプトを起動して以下のコマンドを実行します。

D:\RMI_HELLO>java -Djava.security.policy=policy.txt examples.rmi.HelloClient localhost tanaka

成功すれば、以下の結果が返ってきます。

tanakaさん、こんにちは

アプリケーション企画

蔵書管理アプリケーション:停滞中
毎月の携帯料金を管理するアプリケーション:企画中
個人的な日記をWEBアプリケーションで開発:企画中
超個人的なめざせ100万語!読書記録手帳のWebアプリ化:企画中
アンケート集計&抽選Webソフト:企画中

上記は全てJavaの勉強のために作っている(作ろうとしている)アプリです(^_^;)

マーカーインターフェイス

Serializableのようにメソッドもフィールドも持たないインターフェイスを、マーカーインターフェイスと呼ぶこともあるらしい。java.lang.Cloneableも同じようにマーカーインターフェイスらしい(メモ)

SubClass extends SuperClassの関係にあるクラスがあったとして、SuperClassがSerializableではなく、SubClassがSerializableの時は、SuperClassの分、この場合はSuperClassクラスのフィールドが直列化されないみたいです。しかも、コンパイルと実行が両方とも黙って通るみたいです(笑)