1. 概要

2つのJVMが通信する必要がある場合、JavaRMIはそれを実現するための1つのオプションです。 この記事では、JavaRMIテクノロジーを紹介する簡単な例をブートストラップします。

2. サーバーの作成

RMIサーバーを作成するには、次の2つの手順が必要です。

  1. クライアント/サーバーコントラクトを定義するインターフェイスを作成します。
  2. そのインターフェースの実装を作成します。

2.1. 契約の定義

まず、リモートオブジェクトのインターフェイスを作成しましょう。 このインターフェースは、java.rmi.Remoteマーカーインターフェースを拡張します。

さらに、インターフェースで宣言された各メソッドは、java.rmi。RemoteExceptionをスローします。

public interface MessengerService extends Remote {
    String sendMessage(String clientMessage) throws RemoteException;
}

ただし、Javaタイプが java.io.Serializabl e を実装している限り、RMIはメソッドシグネチャの完全なJava仕様をサポートしていることに注意してください。

今後のセクションで、クライアントとサーバーの両方がこのインターフェイスをどのように使用するかを説明します。

サーバーの場合、リモートオブジェクトと呼ばれることが多い実装を作成します。

クライアントの場合、RMIライブラリはスタブと呼ばれる実装を動的に作成します。

2.2. 実装

さらに、リモートオブジェクトと呼ばれるリモートインターフェイスを実装しましょう。

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句を省略していることに注意してください。

リモートオブジェクトがRemoteExceptionをスローすることはまれです。これは、この例外は通常、クライアントへの通信エラーを発生させるためにRMIライブラリ用に予約されているためです。

それを除外すると、実装をRMIに依存しないという利点もあります。

また、リモートオブジェクトで定義されているがインターフェイスでは定義されていない追加のメソッドは、クライアントには表示されません。

3. サービスの登録

リモート実装を作成したら、リモートオブジェクトをRMIレジストリにバインドする必要があります。

3.1. スタブの作成

まず、リモートオブジェクトのスタブを作成する必要があります。

MessengerService server = new MessengerServiceImpl();
MessengerService stub = (MessengerService) UnicastRemoteObject
  .exportObject((MessengerService) server, 0);

静的UnicastRemoteObject.exportObjectメソッドを使用して、スタブ実装を作成します。 スタブは、基盤となるRMIプロトコルを介してサーバーと通信する魔法を実行します。

exportObject の最初の引数は、リモートサーバーオブジェクトです。

2番目の引数は、exportObjectがリモートオブジェクトをレジストリにエクスポートするために使用するポートです。

ゼロの値を指定することは、 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の概要と、JavaRMIがクライアントサーバーアプリケーションの基盤となる方法について説明しました。 RMIのユニークな機能のいくつかに関する追加の投稿をお楽しみに!

このチュートリアルのソースコードは、GitHubにあります。