Java RMI入門
1概要
2つのJVMが通信する必要がある場合、Java RMIはそのために必要な選択肢の1つです。この記事では、Java RMIテクノロジを紹介する簡単な例を紹介します。
2サーバーを作成する
RMIサーバーを作成するために必要な2つのステップがあります。
-
クライアント/サーバー契約を定義するインターフェースを作成します.
-
そのインターフェースの実装を作成します.
2.1. 契約の定義
まず最初に、リモートオブジェクト用のインターフェースを作成しましょう。このインタフェースは
java.rmi.Remote
markerインタフェースを拡張します。
さらに、インタフェースで宣言された各メソッドは
java.rmi.RemoteException
をスローします。
public interface MessengerService extends Remote {
String sendMessage(String clientMessage) throws RemoteException;
}
ただし、Java型が
java.io.Serializable
を実装している限り、RMIはメソッドシグネチャの完全なJava仕様をサポートしています。
今後のセクションで、クライアントとサーバーの両方がこのインターフェースをどのように使用するかを見ます。
サーバー用に、
Remote Object
と呼ばれることが多い実装を作成します。
クライアントの場合、RMIライブラリは
Stub
という実装を動的に作成します。
2.2. 実装
さらに、リモートオブジェクトを実装しましょう。これも
Remote Object
と呼ばれます。
public class MessengerServiceImpl implements MessengerService {
@Override
public String sendMessage(String clientMessage) {
return "Client Message".equals(clientMessage) ? "Server Message" : null;
}
public String unexposedMethod() {/** code ** /}
}
メソッド定義から
throws
RemoteException
句を省略したことに注意してください。
この例外は通常、RMIライブラリがクライアントへの通信エラーを発生させるために予約されているため、リモートオブジェクトが
RemoteException
をスローするのは珍しいことです。
それを省いても、私たちの実装をRMIにとらわれないでおくという利点があります。
また、リモートオブジェクトで定義されているがインタフェースでは定義されていない追加のメソッドは、クライアントからは見えません。
3サービスを登録する
リモート実装を作成したら、リモートオブジェクトをRMIレジストリにバインドする必要があります。
3.1. スタブを作成する
まず、リモートオブジェクトのスタブを作成する必要があります。
MessengerService server = new MessengerServiceImpl();
MessengerService stub = (MessengerService) UnicastRemoteObject
.exportObject((MessengerService) server, 0);
スタブ実装を作成するには、静的な
UnicastRemoteObject.exportObject
メソッドを使用します。スタブは、基盤となるRMIプロトコルを介してサーバーと通信するという魔法のようなものです。
exportObject
の最初の引数は、リモートサーバーオブジェクトです。
2番目の引数は、
exportObject
がリモートオブジェクトをレジストリにエクスポートするために使用するポートです。
値を0にすると、
exportObject
がどのポートを使用するかが気になりません。これは一般的なので動的に選択されます。
-
残念ながら、ポート番号のない
exportObject()
メソッドは推奨されていません。
3.2レジストリの作成
私達は私達のサーバーのローカルレジストリを立ち上げることも別のスタンドアロンサービスとして立ち上げることもできます。
簡単にするために、サーバーにローカルなものを作成します。
Registry registry = LocateRegistry.createRegistry(1099);
これにより、スタブがサーバーによってバインドされ、クライアントによって検出されるレジストリを作成します。
また、サーバーに対してローカルにレジストリを作成しているので、
createRegistry
メソッドを使用しました。
デフォルトでは、RMIレジストリはポート1099で実行されます。むしろ、
createRegistry
ファクトリメソッドで別のポートを指定することもできます。
しかし、スタンドアローンの場合は、
getRegistry
を呼び出し、ホスト名とポート番号をパラメータとして渡します。
3.3スタブをバインドする
そのため、スタブをレジストリにバインドしましょう。 RMIレジストリはJNDIなどのような命名機能です。ここでも同様のパターンに従って、スタブを一意のキーにバインドできます。
registry.rebind("MessengerService", stub);
その結果、リモートオブジェクトはレジストリを見つけることができるすべてのクライアントに利用可能になりました。
4クライアントを作成する
最後に、リモートメソッドを呼び出すクライアントを書きましょう。
これを行うには、まずRMIレジストリを見つけます。さらに、バインドされた一意のキーを使用してリモートオブジェクトスタブを検索します。
そして最後に、
sendMessage
メソッドを呼び出します。
Registry registry = LocateRegistry.getRegistry();
MessengerService server = (MessengerService) registry
.lookup("MessengerService");
String responseMessage = server.sendMessage("Client Message");
String expectedMessage = "Server Message";
assertEquals(expectedMessage, responseMessage);
ローカルマシンとデフォルトポート1099でRMIレジストリを実行しているので、
getRegistry
にパラメータを渡しません。
実際、レジストリが別のホストや別のポートにある場合は、これらのパラメータを指定できます。
レジストリを使用してスタブオブジェクトをルックアップしたら、リモートサーバーでメソッドを呼び出すことができます。
5結論
このチュートリアルでは、Java RMIについて簡単に紹介し、それがクライアント/サーバーアプリケーションの基盤となる方法について説明しました。 RMIのユニークな機能のいくつかについての追加の投稿をお楽しみに!
このチュートリアルのソースコードはhttps://github.com/eugenp/tutorials/tree/master/java-rmi[on GitHub]にあります。