Seasar DI Container with AOP

S2Axis2 サンプル

本ドキュメントはS2Axis2について記述しています。

目次

概要

S2Axis2Examplesは、S2Axis2の基本的な機能を一通り使用したサンプルです。インストールについてはセットアップを参照してください。

ソースはサーバ側とクライアント側に分かれており、クライアント側はJUnit (S2Unit) のテストケースとして作成されています。それぞれ、以下のソースフォルダにあります。

サーバ側
src/mainフォルダのorg.seasar.axis.examples パッケージ
クライアント側
src/testフォルダのorg.seasar.axis.examples パッケージ

クライアント側では、リモート呼び出しの設定を、以下のdiconファイルで共通化しています。

dicon(クライアント側)
  s2axis2-client.dicon
<components>
    <component name="ioRemoting"
               class="org.seasar.remoting.common.interceptor.RemotingInterceptor">
        <property name="connector">ioConnector</property>
    </component>
    <component name="ioConnector"
               class="org.seasar.remoting.axis2.connector.AxisInOutConnector">
        <property name="baseURL">baseURL</property>
    </component>

    <component name="oneWayRemoting"
               class="org.seasar.remoting.common.interceptor.RemotingInterceptor">
        <property name="connector">oneWayConnector</property>
    </component>
    <component name="oneWayConnector"
               class="org.seasar.remoting.axis2.connector.AxisOnewayConnector">
        <property name="baseURL">baseURL</property>
    </component>

    <component class="org.apache.axis2.description.AxisService" autoBinding="none"/>

    <component name="baseURL" class="java.net.URL" autoBinding="none">
        <arg>"http://localhost:8080/s2axis2-examples/services/"</arg>
    </component>
</components>

コンポーネントをWebサービスとして公開する

POJOのクラスをWebサービスとして公開することが可能です。

現在のバージョンでは、「同期型要求応答形式(Request/Response)」「一方向形式(Oneway)」をサポートしています。 一方向形式では、戻り値なし(void)でなければなりません。

同期型要求応答形式(Request/Response)

サービスとして公開するクラス
  src/main/java/org/seasar/remoting/axis2/examples/ex01/Echo.java
  src/main/java/org/seasar/remoting/axis2/examples/ex01/EchoImpl.java
public interface Echo {
    String echo(int id, String message);
}

public class EchoImpl implements Echo {
    public String echo(int id, String message) {
        return "[id = " + id + "] " + message;
    }
}
dicon(サービス側)
  src/main/resources/org/seasar/remoting/axis2/examples/ex01/deploy.dicon
<component name="Echo" class="org.seasar.remoting.axis2.examples.ex01.EchoImpl">
    <meta name="axis-service"/>
</component>
dicon(クライアント側)
  src/test/resources/org/seasar/remoting/axis2/examples/ex01/EchoTest.dicon
<include path="s2-axis-client.dicon"/>
<component class="org.seasar.remoting.axis2.examples.ex01.Echo">
    <aspect>ioRemoting</aspect>
</component>

一方向形式(Oneway)

サービスとして公開するクラス
  src/main/java/org/seasar/remoting/axis2/examples/ex01/Ping.java
  src/main/java/org/seasar/remoting/axis2/examples/ex01/PingImpl.java
public interface Ping {
    void ping(String message);
}

public class PingImpl implements Ping {
    public void ping(String message) {
        System.out.println(message);
    }
}

dicon(サービス側)
  src/main/resources/org/seasar/remoting/axis2/examples/ex01/deploy.dicon
<component name="Ping" class="org.seasar.remoting.axis2.examples.ex01.PingImpl">
    <meta name="axis-service"/>
</component>
dicon(クライアント側)
  src/test/resources/org/seasar/remoting/axis2/examples/ex01/PingTest.dicon
<include path="s2-axis-client.dicon"/>
<component class="org.seasar.remoting.axis2.examples.ex01.Ping">
    <aspect>oneWayRemoting</aspect>
</component>

特定のインタフェースを公開する

実装クラスを公開すると、不要なメソッドまで公開されてる場合があります(インタフェースを実装していない場合や複数のインタフェースを実装している場合など)。実装クラスHelloImplは二つのインタフェースを実装していますが、MessageSettableのメソッドsetMessage(String)はWebサービスとして公開しないものとします。
このような場合には、公開するJavaインタフェースを指定します(実装したインタフェースが一つだけの場合や、実装した複数のインタフェースのメソッドを全て公開する場合には明示的に指定する必要はありません)。

dicon(サービス側)
  src/main/resources/org/seasar/remoting/axis2/examples/ex02/deploy.dicon
<component name="Hello" class="org.seasar.remoting.axis2.examples.ex02.impl.HelloImpl">
    <meta name="axis-service">
        <component class="org.seasar.remoting.axis2.ServiceDef">
            <property name="serviceType">
                @org.seasar.remoting.axis2.examples.ex02.Hello@class
            </property>
        </component>
    </meta>
    <property name="message">"Hello"</property>
</component>

引数/戻り値としてBeanを使用する

このサンプルでは、サービスは引数および戻り値の型としてJavaBeansを使用しています。プリミティブ型(およびそのラッパクラス型)を使用している場合は、特に何も指定しなくても動作します。

サービスとして公開するクラス
  src/main/java/org/seasar/remoting/axis2/examples/ex03/BeanEcho.java
  src/main/java/org/seasar/remoting/axis2/examples/ex03/impl/BeanEchoImpl.java
public interface BeanEcho {
    EchoDto echo(EchoDto echoDto);
}

public class BeanEchoImpl implements BeanEcho {
    public BeanEchoImpl() {}
    public EchoDto echo(EchoDto echoDto) {
        return echoDto;
    }
}

public class EchoDto {
    private String  strParam    = "";
    private short   shortParam  = 1;
    private int     intParam    = 2;
    private long    longParam   = 3L;
    private float   floatParam  = 1.0f;
    private double  doubleParam = 1.1;
    private boolean boolParam   = true;
    
	// setter/getter
}

スコープを指定する

Axis2は、スコープを指定して、サービスのインスタンスを管理することができます。 S2Axis2では、S2コンテナがインスタンスを管理します。サービスをSessionスコープとして利用する場合には、以下のように指定します。

dicon(サービス側)
  src/main/resources/org/seasar/remoting/axis2/examples/ex04/deploy.dicon
<components>
    <component name="Counter"
        class="org.seasar.remoting.axis2.examples.ex04.impl.CounterImpl"
        instance="session">
        <meta name="axis-service"/>
    </component>
</components>

S2コンテナとAxis2におけるスコープの関連は、リファレンスを参照してください。

services.xmlを利用してサービスを公開する

Axis2で利用するservices.xmlを指定して、サービスをデプロイします。

dicon(サービス側)
  src/main/resources/org/seasar/remoting/axis2/examples/ex06/deploy.dicon
<components>
    <meta name="axis-deploy">
        "org/seasar/remoting/axis2/examples/ex05/services.xml"
    </meta>
</components>
services.xml(Axis2のサービス定義ファイル)
  src/main/resources/org/seasar/remoting/axis2/examples/ex05/services.xml
<service name="EchoBasedXml" scope="application">
    <description>Echo Service.</description>
    <messageReceivers>
        <messageReceiver mep="http://www.w3.org/ns/wsdl/in-out"
                         class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
        <messageReceiver mep="http://www.w3.org/ns/wsdl/in-only"
                         class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
    </messageReceivers>
    <parameter name="ServiceClass" locked="false">
        org.seasar.remoting.axis2.examples.ex01.EchoImpl
    </parameter>
    <operation name="echo">
        <actionMapping>urn:echo</actionMapping>
    </operation>
</service>

ここでは、「コンポーネントをWebサービスとして公開する」で利用したEchoと同じサービスを定義していますが、クライアントの処理は、変更する必要はありません。

また、services.xmlを指定してデプロイしたサービスのインスタンス管理に、S2およびS2Axis2は関与しません。 services.xmlで指定したサービスのインスタンスは、S2コンテナからは取得できない(他のコンポーネントにインジェクションできない)ことに注意してください。

独自のWSDLファイルを利用してサービスを公開する

エンドポイントのURLを変更したい場合など、独自のWSDLファイルを指定してサービスをデプロイすることが可能です。 独自のWSDLファイルを適用するにはServiceDefを利用します。 独自のWSDLファイルを適用するには、まず、利用するWSDLファイルをクラスパス直下のMETA-INFディレクトリ配下に配置します。 WSDLのファイル名は、適用するサービス名に一致するようにします。

例)WEB-INF/classes/META-INF/EchoFormCustomWSDL.wsdl

WSDLを配置したら、以下のように、公開するサービスのdicon定義ファイルでServiceDefにパラメータを指定してください。

dicon(サービス側)
  src/main/resources/org/seasar/remoting/axis2/examples/ex06/deploy.dicon
<component name="EchoFormCustomWSDL"
    class="org.seasar.remoting.axis2.examples.ex01.EchoImpl">
    <meta name="axis-service">
        <component class="org.seasar.remoting.axis2.ServiceDef">
            <initMethod name="addParameter">
                <arg>"useOriginalwsdl"</arg>
                <arg>"true"</arg>
            </initMethod>
            <initMethod name="addParameter">
                <arg>"modifyUserWSDLPortAddress"</arg>
                <arg>"false"</arg>
            </initMethod>
        </component>
    </meta>
</component>

ServiceDef#addParameterメソッドで、「useOriginalwsdl」を「true」と指定することで、独自のWSDLが適用されます。 「modifyUserWSDLPortAddress」は、エンドポイントのURLを変更したい場合に指定してください。デフォルトは「true」ですが、 「false」を指定すると、WSDLで指定した値がそのまま利用されるようになります。

サービスをデプロイ後、ブラウザで以下のようにURLを指定すると、WSDLを確認することができます。

http://localhost:8080/s2axis2-examples/services/EchoFormCustomWSDL?wsdl

クライアントで動的にオプションパラメータを変更する

処理に応じて接続先を変更したい場合など、クライアントの処理でオプションパラメータを指定することが可能です。 変更するにはS2AxisClientContextクラスを利用します。

dicon(サービス側)
public class EchoClient {

    private Echo service;
    
    public EchoClient(Echo echo) {
        this.service = echo;
    }

    public void execute() {
        int id = 1;
        String msg = "echo message";
        String result;
        
        // diconに設定されているURLで接続
         S2AxisClientContext.setEndpointURL(null);
        result = service.echo(id, msg);
        System.out.println(result);
        
        // このクラスで指定したURLで接続
         S2AxisClientContext.setEndpointURL("http://localhost:8081/Echo");
        result = service.echo(id, msg);
        System.out.println(result);
    }

    public static void main(String[] args) {
        SingletonS2ContainerFactory.setConfigPath("EchoTest.dicon");
        SingletonS2ContainerFactory.init();
        S2Container container = SingletonS2ContainerFactory.getContainer();
        Echo echo = (Echo)container.getComponent(Echo.class);

        EchoClient client = new EchoClient(echo);
        client.execute();
    }
}
				

Yahoo! WebサービスにRESTで接続する

S2Axis2で、Yahoo!のWebサービス用APIを利用してみます。Yahoo!のWebサービスに関する情報は、Yahoo!デベロッパーネットワークから得ることができます。 Yahoo!のWebサービスは、HTTP REST(Representational State Transfer)によってアクセスすることが可能です。

本サンプルでは、Web検索のAPIを利用します。サービスはYahoo!のWebサービスとなるため、S2Axis2のクライアントの機能のみ使用します。

YahooSearchDto.java(リクエストパラメータを保持するクラス)

まず、ウェブ検索WebサービスのAPIにしたがって、リクエストパラメータを保持するDTOクラスを作成します。 ここでは、必須パラメータである、appid および query のみ指定しています。

public class YahooSearchDto {
    private String appid;  // アプリケーションID
    private String query;  // 検索クエリー
	
    // setter/getter
}
YahooSearch.java(サービス呼び出しのインタフェース)

次に、サービスを呼び出すためのインタフェースを作成します。インタフェースのみを定義すれば、サービスを呼び出すことが可能です。

S2Axis2では、メソッドの名前に合わせてRESTの通信方式(Axis2 1.0 では、GET/POSTのみがサポートされています)を特定するため、メソッドの名前の付け方に注意してください。

getXxx
GET としてサービスを呼び出します。
postXXX
POST としてサービスを呼び出します。
public interface YahooSearch {
    String postSearch(YahooSearchDto dto);
    String getSearchResult(YahooSearchDto dto);
}
YahooSearchTest.dicon

コネクタにはorg.seasar.remoting.axis2.connector.RESTConnectorを指定し、接続先のURLには、ウェブ検索WebサービスのリクエストURLを指定してください。

上で作成したYahooSearchインタフェースに、RESTConnectorを設定したRemotingInterceptorをアスペクトとして指定します。

<component name="remoting" class="org.seasar.remoting.common.interceptor.RemotingInterceptor"/>

<component name="connector" class="org.seasar.remoting.axis2.connector.RESTConnector">
    <property name="baseURL">
        new java.net.URL("http://api.search.yahoo.co.jp/WebSearchService/V1/webSearch")
    </property>
</component>

<component class="org.seasar.remoting.axis2.examples.rest.YahooSearch">
    <aspect>remoting</aspect>
</component>

以上で、サービスを呼び出す準備が整いました。

クライアント

ウェブ検索Webサービスを呼び出します。ここでは、S2TestCaseとして作成しています。

public class YahooSearchTest extends S2TestCase {
    public void setUp() {
        include("YahooSearchTest.dicon");
    }

    public void testGet() {
        YahooSearch rest = (YahooSearch) getComponent(YahooSearch.class);
        YahooSearchDto dto = createDto();
        String result = rest.getSearchResult(dto);
        System.out.println(result);
    }

    private YahooSearchDto createDto() {
        YahooSearchDto dto = new YahooSearchDto();
        dto.setAppid("ApacheRestDemo");
        dto.setQuery("Axis2 REST");
        return dto;
    }
}