S2Remotingサンプル実装改造

前回までで、一先ず動作するものができましたが、これから少しずつ手を加えて行く。

また、S2が2.1.1にバージョンアップしたので、環境を更新しました。

気になっている点は以下の2点。

  1. Adaptorインタフェースとその実装
  2. 例外処理

1. Adaptorインタフェースとその実装の変更

Adaptorインタフェースとして、Remoteを継承したRmiAdaptorを作成したが、AdaptorインタフェースがRMIの実装に縛られるのはよろしくない気がする。

そこで、純粋にリモートメソッドの呼び出しだけを行うインタフェースを作る。

2. RemoteMethodInvokerインタフェース

package sample.seasar.remoting;

import java.rmi.Remote;

/**
 * @author murata
 */
public interface RemoteMethodInvoker extends Remote
{
  public Object invoke(String targetName, String methodName, Object[] args)
      throws Exception;
}

Connectorインタフェースの実装クラスはこのRemoteMethodInvokerのリモートオブジェクトを取得して、処理を実行するように変更する。

また、Adaptorインタフェースの実装クラスはこのRemoteMethodInvokerのリモートオブジェクトをrmiregistryに登録し、自身のinvokeメソッドを呼ばれるように変更する。

こんなイメージですね。

Interseptor > Connector > RemoteMethodInvoker > Adaptor
Interseptor < Connector < RemoteMethodInvoker < Adaptor

3. Connector

package sample.seasar.remoting;

/**
 * @author murata
 */
public interface Connector
{
  public Object invoke(String tagetName, String methodName, Object[] args)
      throws Exception;
}

4. ConnectorImpl

package sample.seasar.remoting.impl;

import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import sample.seasar.remoting.Connector;
import sample.seasar.remoting.RemoteMethodInvoker;

/**
 * @author murata
 */
public class RmiConnectorImpl implements Connector
{
  private RemoteMethodInvoker remoteInvoker;

  public void addURL(String url) throws Exception
  {
    if (null == System.getSecurityManager())
    {
      System.setSecurityManager(new RMISecurityManager());
    }

    this.remoteInvoker = (RemoteMethodInvoker) Naming.lookup(url
        + "/RemoteMethodInvoker");
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.seasar.remoting.Connector#invoke(java.lang.String,
   *      java.lang.String, java.lang.Object[])
   */
  public Object invoke(String targetName, String methodName, Object[] args)
      throws Exception
  {
    return this.remoteInvoker.invoke(targetName, methodName, args);
  }
}

5. Adaptor

AdaptorはRemoteMethodInvokerの導入により、RMIに依存しないインタフェースになります。最初に戻りましたね。

package sample.seasar.remoting;

/**
 * @author murata
 */
public interface Adaptor
{
  public void setup() throws Exception;

  public Object invoke(String tagetName, String methodName, Object[] args)
      throws Exception;
}

6. AdaptorImpl

Adaptorインタフェースの実装クラスでは、RemoteMethodInvokerの実装クラスを生成し、invokeメソッドを呼ばれるように自身の参照を渡すように変更する。
あとは、ポート番号を設定できるようにしてみる。

package sample.seasar.remoting.impl;

import java.rmi.Naming;
import java.rmi.RMISecurityManager;

import org.seasar.framework.beans.BeanDesc;
import org.seasar.framework.beans.factory.BeanDescFactory;
import org.seasar.framework.container.S2Container;

import sample.seasar.remoting.Adaptor;
import sample.seasar.remoting.RemoteMethodInvoker;

/**
 * @author murata
 */
public class RmiAdaptorImpl implements Adaptor
{
  private int port = 1099;

  private S2Container container;

  /**
   * @param port The port to set.
   */
  public void setPort(int port)
  {
    this.port = port;
  }

  /**
   * @param container
   *          The container to set.
   */
  public void setContainer(S2Container container)
  {
    this.container = container;
  }
  
  /*
   * (non-Javadoc)
   * 
   * @see sample.seasar.remoting.Adaptor#setup()
   */
  public void setup() throws Exception
  {
    if (null == System.getSecurityManager())
    {
      System.setSecurityManager(new RMISecurityManager());
    }

    RemoteMethodInvoker remoteInvoker = new RemoteMethodInvokerImpl(this);

    Naming.rebind("//localhost:" + this.port + "/RemoteMethodInvoker",
        remoteInvoker);
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.seasar.remoting.Adaptor#invoke(java.lang.String, java.lang.String,
   *      java.lang.Object[])
   */
  public Object invoke(String targetName, String methodName, Object[] args) throws Exception
  {
    Object targetObj = this.container.getComponent(targetName);

    BeanDesc beanDesc = BeanDescFactory.getBeanDesc(targetObj.getClass());

    return beanDesc.invoke(targetObj, methodName, args);
  }
}

7. RemoteMethodInvokerImpl

RemoteMethodInvokerインタフェースの実装クラスは、Adaptorの参照を持つようにし、Connectorから呼ばれたら、Adaptorのinvokeメソッドを呼ぶようにします。

package sample.seasar.remoting.impl;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import sample.seasar.remoting.Adaptor;
import sample.seasar.remoting.RemoteMethodInvoker;

/**
 * @author murata
 */
public class RemoteMethodInvokerImpl extends UnicastRemoteObject implements
    RemoteMethodInvoker
{
  private Adaptor adaptor;

  /**
   * @throws RemoteException
   */
  public RemoteMethodInvokerImpl(Adaptor adaptor) throws RemoteException
  {
    super();

    this.adaptor = adaptor;
  }

  /*
   * (non-Javadoc)
   * 
   * @see sample.seasar.remoting.RemoteMethodInvoker#invoke(java.lang.String,
   *      java.lang.String, java.lang.Object[])
   */
  public Object invoke(String targetName, String methodName, Object[] args)
      throws Exception
  {
    return this.adaptor.invoke(targetName, methodName, args);
  }
}