6 WebLogic RMIの実装方法
java.rmi.Remote
インタフェースについて説明します(ただし、このインタフェースにはメソッドは含まれません)。この「タグ付け」インタフェースを拡張し(リモート・クラスを識別するタグとして機能するように)、リモート・オブジェクトの構造を作成するメソッド・スタブを使って、使用するリモート・インタフェースを作成します。次に、リモート・クラスを使ってリモート・インタフェースを実装します。この実装はレジストリ内の名前にバインドされ、クライアントやサーバーはそこからオブジェクトをルックアップしてリモートで使用できます。 すでにRMIクラスを記述している場合は、リモート・インタフェースとそれを拡張するクラスでimport文を変えるだけでWebLogic RMIをインストールできます。クライアント・アプリケーションにリモート呼出しを追加するには、レジストリ内でオブジェクトを名前でルックアップします。Weblogic RMI例外はjava.rmi
例外と同じ機能を備えているので、既存のインタフェースと実装で例外の処理方法を変える必要がありません。
この章には次の項が含まれます:
リモートで呼び出すことができるクラスの作成
RMIクラスを記述してWebLogic RMIに含めて、リモート・インタフェースとリモート・インタフェースを拡張するクラスでimport文を変えることができます。WebLogic RMIは柔軟なランタイムを持つコードを生成し、インタフェースを実装するクラスから独立した動的なバイトコードを作成します。
独自のWebLogic RMIクラスを簡単なステップで記述できます。
ステップ1. リモート・インタフェースの作成
リモートで呼び出せるすべてのクラスは、リモート・インタフェースを実装します。次のガイドラインに従って、リモート・インタフェースを作成します。
-
リモート・インタフェースは、java.rmi.Remoteインタフェースを拡張する必要がありますが、これにはメソッド・シグネチャは含まれません。インタフェースを実装する各リモート・クラスで実装されるメソッド・シグネチャを含めます。
-
リモート・インタフェースはパブリックでなければなりません。パブリックでない場合、クライアントはリモート・インタフェースを実装するリモート・オブジェクトをロードしようとするとエラーを受け取ります。
-
インタフェース内の各メソッドがそのthrowsブロックで
java.rmi.RemoteException
を宣言する必要はありません。アプリケーションがスローする例外は、アプリケーション固有の例外である可能性があり、RuntimeException
.WebLogic RMI subclassesjava.rmi.RemoteException
を拡張する場合があります。したがって、すでにRMIクラスがある場合、例外処理を変更する必要はありません。 -
リモート・インタフェースにはコードがあまり記述されていない場合もあります。必要なのは、リモート・クラスで実装するメソッドのメソッド・シグネチャだけです。
以下の例に、メソッド・シグネチャ
sayHello()
を持つリモート・インタフェースを示します。WebLogic RMIは、柔軟性の高い実行時のコード生成をサポートします。つまり、WebLogic RMIは、型さえ正しければ、そのほかはインタフェースを実装するクラスに依存しない動的プロキシと動的に生成されるバイトコードもサポートします。クラスが単一のリモート・インタフェースを実装する場合、コンパイラが生成したプロキシとバイトコードは、リモート・インタフェースと同じ名前になります。クラスが複数のリモート・インタフェースを実装する場合、コンパイルから生じたプロキシとバイトコードの名前は、コンパイラが使用する名前マングリングによって決まります。
例6-1 Hello.javaリモート・インタフェース
package examples.rmi.hello; import java.rmi.RemoteException; /** * This interface is the remote interface. * * Copyright (c) 1999,2012, Oracle and/or its affiliates. All Rights Reserved. */ public interface Hello extends java.rmi.Remote { String sayHello() throws RemoteException; }
ステップ2. リモート・インタフェースの実装
リモートで呼び出すクラスを作成します。このクラスは、ステップ1で記述したリモート・インタフェースを実装する必要があります。これは、インタフェースに含まれるメソッド・シグネチャを実装することを意味します。WebLogic RMIで行われるコード生成はすべて、このクラス・ファイルに依存します。
-
クラスは、複数のリモート・インタフェースを実装できます。また、クラスにはリモート・インタフェースにないメソッドも定義できますが、このようなメソッドはリモートで呼び出せません。
-
例6-2では、
HelloImpl
を作成するクラスを実装し、それをレジストリ内の一意の名前HelloServer
にバインドします。メソッドsayHello()
により、挨拶が表示されます。 -
main()
メソッドは、リモート・オブジェクトのインスタンスを作成し、それを名前(オブジェクトの実装を指し示すURL)にバインドすることによってWebLogic JNDIツリーに登録します。リモートでオブジェクトを使用するためにプロキシを取得しようとするクライアントは、オブジェクトを名前でルックアップできます。
WebLogic RMIでは、アプリケーションにセキュリティを統合するためにセキュリティ・マネージャを設定する必要はありません。セキュリティは、WebLogicのSSLとACLのサポートによって処理されます。
例6-2 HelloImpl.javaリモート・インタフェースの実装
package examples.rmi.hello; import javax.naming.*; import java.rmi.RemoteException; /** * Copyright (c) 1999,2012, Oracle and/or its affiliates. All Rights Reserved. */ public class HelloImpl implements Hello{ private String name; /** * Constructs a HelloImpl with the specified string. * * @param s String message */ public HelloImpl(String s) throws RemoteException { super(); name = s; } /** * Returns a string. * * @return String message * @exception java.rmi.RemoteException */ public String sayHello() throws java.rmi.RemoteException { return "Hello World!"; } /** * Allows the WebLogic Server to instantiate this implementation * and bind it in the registry. */ public static void main(String args[]) throws Exception { try { HelloImpl obj = new HelloImpl("HelloServer"); Context ctx = new InitialContext(); ctx.bind("HelloServer", obj); System.out.println("HelloImpl created and bound in the registry " + "to the name HelloServer"); } catch (Exception e) { System.err.println("HelloImpl.main: an exception occurred:"); System.err.println(e.getMessage()); throw e; } } }
ステップ3: リモート・メソッドを呼び出すクライアントの作成
一般に、初期コンテキストを作成すると、リモート・オブジェクトの参照を取得する単一行のコードのみが取得されます。これは、Naming.lookup()
メソッドで行います。次の項では、クライアント作成に関するその他の情報について説明します。
クライアント・タイムアウトの設定
初期コンテキストを構成しながら、クライアント側のタイムアウトを設定できます。
-
リクエストが接続レスポンスを待機する時間を設定するには、
weblogic.jndi.connectTimeout
を使用します。 -
接続の確立後に、リモート・サーバーからのレスポンスをリクエストが待機する時間を設定するには、
weblogic.jndi.responseReadTimeout
を使用します。 -
「リクエスト・タイムアウト」を参照してください。
たとえば:
. . . // Get an InitialContext Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory"); env.put(Context.PROVIDER_URL, url); env.put("weblogic.jndi.connectTimeout", new Long(15000)); env.put("weblogic.jndi.responseReadTimeout", new Long(15000)); return new InitialContext(env); . . .
HelloClient.javaクライアントの例
次に、例6-2で作成したオブジェクトを使用する短いWebLogicクライアント・アプリケーションを示します。
例6-3 HelloClient.javaクライアントの例
package examples.rmi.hello;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* This client uses the remote HelloServer methods.
*
* @author Copyright (c) 1999,2012, Oracle and/or its affiliates. All Rights Reserved.
*/
public class HelloClient
{
// Defines the JNDI context factory.
public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";
int port;
String host;
private static void usage() {
System.err.println("Usage: java examples.rmi.hello.HelloClient " +
"<hostname> <port number>");
}
public HelloClient() {}
public static void main(String[] argv) throws Exception {
if (argv.length < 2) {
usage();
return;
}
String host = argv[0];
int port = 0;
try {
port = Integer.parseInt(argv[1]);
}
catch (NumberFormatException nfe) {
usage();
throw nfe;
}
try {
InitialContext ic = getInitialContext("t3://" + host + ":" + port);
Hello obj = (Hello) ic.lookup("HelloServer");
System.out.println("Successfully connected to HelloServer on " +
host + " at port " +
port + ": " + obj.sayHello() );
}
catch (Exception ex) {
System.err.println("An exception occurred: "+ex.getMessage());
throw ex;
}
}
private static InitialContext getInitialContext(String url)
throws NamingException
{
Hashtable<String,String> env = new Hashtable<String,String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
env.put(Context.PROVIDER_URL, url);
return new InitialContext(env);
}
}
ステップ4. Javaクラスのコンパイル
javac
または他のJavaコンパイラを使用して.java
ファイルをコンパイルし、リモート・インタフェースとそれを実装するクラス用の.class
ファイルを作成します。
例6-4に、WebLogic Server examplesServerに構成されるserverclasses
ディレクトリとclientclasses
ディレクトリに対して、.java
ファイルをコンパイルしたり.class
ファイルをインストールする場合にWebLogic Serverのサンプル環境で使用できるAntスクリプトを示します。
例6-4 Javaクラスをコンパイルするbuild.xmlファイルの例
<?xml version="1.0" encoding="ISO-8859-1"?> <project name="rmi.hello" default="all" basedir="."> <property environment="env"/> <property file="../../../examples.properties"/> <property name="build.compiler" value="${compiler}"/> <!-- set global properties for this build --> <property name="source" value="${basedir}"/> <target name="all" depends="build"/> <target name="build" depends="compile.server, compile.client"/> <!-- Compile server classes into the serverclasses directory --> <target name="compile.server"> <javac srcdir="${source}" destdir="${server.classes.dir}" includes="Hello.java, HelloImpl.java" classpath="${ex.classpath};${server.classes.dir}" deprecation="${deprecation}" debug="${debug}" debugLevel="${debugLevel}" /> </target> <!-- Compile client classes into the clientclasses directory --> <target name="compile.client"> <javac srcdir="${source}" destdir="${client.classes.dir}" includes="HelloClient.java" classpath="${ex.classpath};${server.classes.dir}" deprecation="${deprecation}" debug="${debug}" debugLevel="${debugLevel}" /> </target> </project>
RMI Helloサンプル・コードの実行
次の手順を使用して、WebLogic RMI Helloサンプルを実行します。
起動クラスの構成
exampleServerのインスタンスを起動します。起動クラスを次の情報で作成します。
-
名前:
MyHello
-
クラス名:
examples.rmi.hello.HelloImpl
-
ターゲット: examplesServer
Oracle WebLogic Server管理コンソール・オンライン・ヘルプの起動クラスの構成を参照してください。
ノート:
このサンプルでは、ビルド・スクリプトは、起動クラスがサーバーのクラスパスの場所にあるかどうかを確認します。
examplesServerの再起動
examplesServerを再起動します。サーバーが起動したら、サーバー・ログで次の内容を確認する必要があります。
HelloImpl created and bound in the registry to the name HelloServer
サーバーが実行すると、JNDIを表示してHelloServer
が登録されていることを確認できます。Oracle WebLogic Server管理コンソール・オンライン・ヘルプのJNDIツリーでのオブジェクトの表示を参照してください。