1概要

2つのJVMが通信する必要がある場合、Java RMIはそのために必要な選択肢の1つです。この記事では、Java RMIテクノロジを紹介する簡単な例を紹介します。


2サーバーを作成する

RMIサーバーを作成するために必要な2つのステップがあります。

  1. クライアント/サーバー契約を定義するインターフェースを作成します.

  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]にあります。