[ Java & CORBAページへ戻る ]

CORBAのリモートオペレーション呼び出しの途中でフックを行い、なんらかの処理を挟み込みたいことがあります。例えば、CORBAのリモートオペレーション呼び出しのログを取りたいときなどです。そのときにCORBAの実装系に依存しない標準APIとしてPortable Interceptorが用意されています。


インターセプタ概要

インターセプタは、CORBAオペレーションを呼び出す側(クライアント)とCORBAオペレーションを受け取り実行する側(サーバ)とに分かれます。

ClientRequestInterceptor TCP/IP ServerRequestInterceptor
クライアント
オブジェクト
receive_request_service_contexts サーバ
オブジェクト
send_request receive_request
send_poll
receive_reply send_reply
receive_exception (←) send_exception
receive_other send_other

例えば、クライアントオブジェクトがリモートオブジェクトへオペレーションを要求するときは、まずクライアント側のインターセプタが持つsend_requestメソッドが起動されます。そして、サーバ側ではサーバントに渡る前にサーバ側のインターセプタが持つreceive_requestメソッドが起動されます。
それから、サーバントの対応するメソッドが起動されます。サーバントのメソッドが正常にreturnされると、サーバ側のインターセプタが持つsend_replyが起動されます。そして、クライアント側でインターセプタが持つreceive_replyメソッドが起動されます。

インターセプタの実装

クライアント側のインターセプタ

クライアント側インターセプタは、org.omg.PortableInterceptor.ClientInterceptorインタフェースを実装します。また、org.omg.CORBA.LocalObjectを継承します。

クライアント側インターセプタ実装例 ClientInterceptor.java
package count;

import org.omg.CORBA.LocalObject;
import org.omg.PortableInterceptor.ForwardRequest;
import org.omg.PortableInterceptor.ClientRequestInfo;
import org.omg.PortableInterceptor.ClientRequestInterceptor;

public class ClientInterceptor extends LocalObject
    implements ClientRequestInterceptor
{
    public ClientInterceptor() {}
    public void send_request(ClientRequestInfo info)
        throws ForwardRequest
    {
        printRequestInfo("send_request ", info);
    }
    public void send_poll(ClientRequestInfo info) {}
    public void receive_reply(ClientRequestInfo info) {
        printRequestInfo("receive_reply", info);
    }
    public void receive_exception(ClientRequestInfo info)
        throws ForwardRequest
    {}

    public void receive_other(ClientRequestInfo info)
        throws ForwardRequest
    {}

    public String name() {
        return "ClientInterceptor";
    }

    public void destroy() {}

    private void printRequestInfo(String methodName,
                                  ClientRequestInfo info)
    {
        System.out.println("ClientInterceptor#" + methodName + ": " +
                      "send_request: operation=" + info.operation() +
                      ", request_id=" + info.request_id()
        );
    }
}// ClientInterceptor

サーバ側のインターセプタ

クライアント側インターセプタは、org.omg.PortableInterceptor.ClientInterceptorインタフェースを実装します。また、org.omg.CORBA.LocalObjectを継承します。

サーバ側インターセプタ実装例 ServerInterceptor.java
package count;

import org.omg.CORBA.LocalObject;
import org.omg.PortableInterceptor.ForwardRequest;
import org.omg.PortableInterceptor.ServerRequestInfo;
import org.omg.PortableInterceptor.ServerRequestInterceptor;

public class ServerInterceptor extends LocalObject
    implements ServerRequestInterceptor
{
    public ServerInterceptor() {}
    public void receive_request_service_contexts(ServerRequestInfo info)
        throws ForwardRequest
    {}
    public void receive_request(ServerRequestInfo info)
        throws ForwardRequest
    {
        printRequestInfo("receive_request ", info);
    }
    public void send_reply(ServerRequestInfo info) {
        printRequestInfo("send_reply      ", info);
    }
    public void send_exception(ServerRequestInfo info)
        throws ForwardRequest 
    {}

    public void send_other(ServerRequestInfo info)
        throws ForwardRequest
    {}

    public String name() {
        return "ServerInterceptor";
    }

    public void destroy() {
    }

    private void printRequestInfo(String methodName,
                                  ServerRequestInfo info)
    {
        System.out.println("ServerInterceptor#" + methodName + ": " +
                      "send_request: operation=" + info.operation() +
                      ", request_id=" + info.request_id()
        );
    }
}// ServerInterceptor

インターセプタの初期化とORBへの設定

インターセプタは、インターセプタ初期化クラスによってORBに登録されます。これは、org.omg.PortableInterceptor.ORBInitializerインタフェースを実装します。また、org.omg.CORBA.LocalObjectを継承します。2つのメソッドpre_initjとpost_initを持っており、どちらかのメソッドの実装においてインターセプタを初期化しORBに登録します。これは呼ばれるタイミングが違います。

インターセプタの初期化クラス
package count;

import org.omg.PortableInterceptor.ORBInitInfo;
import org.omg.PortableInterceptor.ORBInitializer;
import org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName;
import org.omg.CORBA.LocalObject;

public class InterceptorInitializer extends LocalObject
    implements ORBInitializer
{
    ClientInterceptor clientInterceptor = new ClientInterceptor();
    ServerInterceptor serverInterceptor = new ServerInterceptor();

    public void pre_init(ORBInitInfo info) {
        System.out.println("count.InterceptorInitializer#pre_init: called");
        try {
            info.add_client_request_interceptor(clientInterceptor);
            info.add_server_request_interceptor(serverInterceptor);
        } catch (DuplicateName e) {
            System.out.println("DuplicateName in InterceptorInitializer#pre_init");
        }
    }

    public void post_init(ORBInitInfo info) {
        System.out.println("count.InterceptorInitializer#post_init: called");
    }
    
}// InterceptorInitializer

JavaVMのシステムプロパティでインターセプタ初期化クラスを指定

このインターセプタ初期化クラスは、プログラム中でコーディングすることもできますが、システムプロパティに記述することもできます。

OpenORB 1.4.0
D:\develop\ex1>java -Dorg.omg.PortableInterceptor.ORBInitializerClass.count.Inter
ceptorInitializer -cp $CLASSPATH:classes count.Client -ORBInitRef NameService=cor
baloc:iiop:1.2@xxx.xxx.xxx.xxx:1234/NameService
  :

プロパティ名: org.omg.PortableInterceptor.ORBInitializerClass.インターセプタ初期化クラスのFQCN


This page is written by Toru TAKAHASHI.(torutk@02.246.ne.jp)