SpringによるApache CXFの手引き

SpringでのApache CXFのガイド

1. 概要

このチュートリアルでは、JavaまたはXML構成のいずれかを使用した構成とusing the Apache CXF framework together with Springに焦点を当てます。

これは、ApacheCXFに関するシリーズの2番目です。 the first oneは、JAX-WS標準APIの実装としてのCXFの基本に焦点を当てています。

2. Mavenの依存関係

前のチュートリアルと同様に、次の2つの依存関係を含める必要があります。


    org.apache.cxf
    cxf-rt-frontend-jaxws
    3.1.6


    org.apache.cxf
    cxf-rt-transports-http
    3.1.6

Apache CXFアーティファクトの最新バージョンについては、apache-cxfを確認してください。

さらに、Springをサポートするには次の依存関係が必要です。


    org.springframework
    spring-context
    4.3.1.RELEASE


    org.springframework
    spring-webmvc
    4.3.1.RELEASE

Springアーティファクトの最新バージョンはhereにあります。

最後に、従来のweb.xmlデプロイメント記述子の代わりにJavaサーブレット3.0+ APIを使用してアプリケーションをプログラムで構成するため、以下のアーティファクトが必要になります。


    javax.servlet
    javax.servlet-api
    3.1.0

Thisは、サーブレットAPIの最新バージョンを見つけることができる場所です。

3. サーバー側のコンポーネント

次に、Webサービスエンドポイントを公開するためにサーバー側に存在する必要があるコンポーネントを見てみましょう。

3.1. WebApplicationInitilizerインターフェース

WebApplicationInitializerインターフェースは、アプリケーションのServletContextインターフェースをプログラムで構成するために実装されています。 クラスパスに存在する場合、そのonStartupメソッドはサーブレットコンテナによって自動的に呼び出され、その後、ServletContextがインスタンス化されて初期化されます。

WebApplicationInitializerインターフェイスを実装するためのクラスの定義方法は次のとおりです。

public class AppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext container) {
        // Method implementation
    }
}

onStartup()メソッドは、以下に示すコードスニペットを使用して実装されます。

最初に、構成メタデータを含むクラスを登録するために、Springアプリケーションコンテキストが作成および構成されます。

AnnotationConfigWebApplicationContext context
  = new AnnotationConfigWebApplicationContext();
context.register(ServiceConfiguration.class);

ServiceConfigurationクラスには、Bean定義を提供するために@Configurationアノテーションが付けられています。 このクラスについては、次のサブセクションで説明します。

次のスニペットは、Springアプリケーションコンテキストがサーブレットコンテキストに追加される方法を示しています。

container.addListener(new ContextLoaderListener(context));

Apache CXFによって定義されるCXFServletクラスは、着信要求を処理するために生成および登録されます。

ServletRegistration.Dynamic dispatcher
  = container.addServlet("dispatcher", new CXFServlet());

アプリケーションコンテキストは、構成ファイルで定義されたSpring要素をロードします。 この場合、サーブレットの名前はcxfであるため、コンテキストはデフォルトでcxf-servlet.xmlという名前のファイル内のこれらの要素を検索します。

最後に、CXFサーブレットは相対URLにマッピングされます。

dispatcher.addMapping("/services");

3.2. 古き良きweb.xml

または、WebApplicationInitilizerインターフェイスではなく(やや古風な)デプロイメント記述子を使用する場合は、対応するweb.xmlファイルに次のサーブレット定義を含める必要があります。


    cxf
    org.apache.cxf.transport.servlet.CXFServlet
    1

    
    cxf
    /services/*

3.3. ServiceConfigurationクラス

次に、サービス構成を見てみましょう。最初に、WebサービスエンドポイントのBean定義を囲む基本的なスケルトンです。

@Configuration
public class ServiceConfiguration {
    // Bean definitions
}

最初に必要なBeanはSpringBusです。これは、ApacheCXFがSpringFrameworkと連携するための拡張機能を提供します。

@Bean
public SpringBus springBus() {
    return new SpringBus();
}

EnpointImpl Beanも、SpringBus BeanとWebサービスimplementorを使用して作成する必要があります。 このBeanは、指定されたHTTPアドレスでエンドポイントを公開するために使用されます。

@Bean
public Endpoint endpoint() {
    EndpointImpl endpoint = new EndpointImpl(springBus(), new exampleImpl());
    endpoint.publish("http://localhost:8080/services/example");
    return endpoint;
}

exampleImplクラスは、Webサービスインターフェイスを実装するために使用されます。 その定義は次のサブセクションで与えられます。

また、XML構成ファイルでサーバーエンドポイントを宣言することもできます。 具体的には、以下のcxf-servlet.xmlファイルは、サブセクション3.1で定義されたweb.xmlデプロイメント記述子で機能し、まったく同じエンドポイントを記述します。

XML構成ファイルの名前は、デプロイメント記述子で定義されているサーブレット名(cxf)にちなんで付けられていることに注意してください。

3.4. タイプ定義

次へ–これは、前のサブセクションですでに説明したimplementorの定義です。

@WebService(endpointInterface = "com.example.cxf.spring.example")
public class exampleImpl implements example {
    private int counter;

    public String hello(String name) {
        return "Hello " + name + "!";
    }

    public String register(Student student) {
        counter++;
        return student.getName() + " is registered student number " + counter;
    }
}

このクラスは、Apache CXFが公開されたWSDLメタデータに含めるexampleエンドポイントインターフェイスの実装を提供します。

@WebService
public interface example {
    String hello(String name);
    String register(Student student);
}

エンドポイントインターフェイスとimplementorの両方が、次のように定義されているStudentクラスを利用します。

public class Student {
    private String name;

    // constructors, getters and setters
}

4. クライアント側のBean

Spring Frameworkを利用するために、@Configurationアノテーション付きクラスでBeanを宣言します。

@Configuration
public class ClientConfiguration {
    // Bean definitions
}

clientという名前のBeanが定義されています。

@Bean(name = "client")
public Object generateProxy() {
    return proxyFactoryBean().create();
}

client Beanは、exampleWebサービスのプロキシーを表します。 これは、JAX-WSプロキシを作成するためのファクトリであるJaxWsProxyFactoryBean Beanでのcreateメソッドの呼び出しによって作成されます。

JaxWsProxyFactoryBeanオブジェクトは、次の方法で作成および構成されます。

@Bean
public JaxWsProxyFactoryBean proxyFactoryBean() {
    JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();
    proxyFactory.setServiceClass(example.class);
    proxyFactory.setAddress("http://localhost:8080/services/example");
    return proxyFactory;
}

ファクトリのserviceClassプロパティはWebサービスインターフェイスを示し、addressプロパティはプロキシがリモート呼び出しを行うためのURLアドレスを示します。

また、クライアント側のSpring Beanの場合、XML構成ファイルに戻る場合があります。 次の要素は、上記でプログラムで構成したばかりのBeanと同じBeanを宣言します。



    
    

5. テストケース

このセクションでは、SpringのApache CXFサポートを説明するために使用されるテストケースについて説明します。 テストケースは、StudentTestという名前のクラスで定義されています。

まず、前述のServiceConfiguration構成クラスからSpringアプリケーションコンテキストをロードし、それをcontextフィールドにキャッシュする必要があります。

private ApplicationContext context
  = new AnnotationConfigApplicationContext(ClientConfiguration.class);

次に、サービスエンドポイントインターフェイスのプロキシが宣言され、アプリケーションコンテキストからロードされます。

private example exampleProxy = (example) context.getBean("client");

このexampleプロキシは、以下で説明するテストケースで使用されます。

最初のテストケースでは、helloメソッドがプロキシでローカルに呼び出された場合、応答がエンドポイントimplementorがリモートWebサービスから返すものとまったく同じであることを証明します。

@Test
public void whenUsingHelloMethod_thenCorrect() {
    String response = exampleProxy.hello("John Doe");
    assertEquals("Hello John Doe!", response);
}

2番目のテストケースでは、学生はプロキシでregisterメソッドをローカルに呼び出して、たとえばコースを登録します。プロキシはWebサービスを呼び出します。 そのリモートサービスは、学生番号を計算し、呼び出し元に返します。 次のコードスニペットは、期待どおりのものを確認します。

@Test
public void whenUsingRegisterMethod_thenCorrect() {
    Student student1 = new Student("Adam");
    Student student2 = new Student("Eve");
    String student1Response = exampleProxy.register(student1);
    String student2Response = exampleProxy.register(student2);

    assertEquals("Adam is registered student number 1", student1Response);
    assertEquals("Eve is registered student number 2", student2Response);
}

6. 統合テスト

サーバー上のWebアプリケーションとしてデプロイするには、このチュートリアルのコードスニペットを最初にWARファイルにパッケージ化する必要があります。 これは、POMファイルでpackagingプロパティを宣言することで実現できます。

war

パッケージングジョブは、Maven WARプラグインによって実装されます。


    maven-war-plugin
    2.6
    
        false
    

このプラグインは、コンパイルされたソースコードをWARファイルにパッケージ化します。 Javaコードを使用してサーブレットコンテキストを構成するため、従来のweb.xmlのデプロイメント記述子が存在する必要はありません。 その結果、プラグインの実行時の失敗を回避するために、failOnMissingWebXmlプロパティをfalseに設定する必要があります。

Maven WARプラグインの最新バージョンのthis linkを追跡できます。

Webサービスの操作を説明するために、統合テストを作成します。 このテストでは、最初にWARファイルを生成し、組み込みサーバーを起動してから、クライアントにWebサービスを呼び出しさせ、後続の応答を検証して、最後にサーバーを停止します。

次のプラグインをMaven POMファイルに含める必要があります。 詳細については、this Integration Testing tutorialを確認してください。

Maven Surefireプラグインは次のとおりです。


    maven-surefire-plugin
    2.19.1
    
        
            StudentTest.java
        
    

このプラグインの最新バージョンはhereにあります。

統合テストを容易にするために、integrationidを持つprofileセクションが宣言されています。


   
      integration
      
         
            ...
         
      
   

Maven Cargoプラグインはintegrationプロファイルに含まれています。


    org.codehaus.cargo
    cargo-maven2-plugin
    1.5.0
    
        
            jetty9x
            embedded
        
        
            
                localhost
                8080
            
        
    
    
        
            start-server
            pre-integration-test
            
                start
            
        
        
            stop-server
            post-integration-test
            
                stop
            
        
    

cargo.hostnameおよびcargo.servlet.portの構成プロパティは、わかりやすくするために含まれているだけであることに注意してください。 これらの構成プロパティはデフォルト値と同じであるため、アプリケーションに影響を与えずに省略できます。 このプラグインはサーバーを起動し、接続を待機し、最後にサーバーを停止してシステムリソースを解放します。

This linkを使用すると、MavenCargoプラグインの最新バージョンを確認できます。

Maven Surefireプラグインは、integrationプロファイル内で再度宣言され、メインのbuildセクションの構成をオーバーライドし、前のセクションで説明したテストケースを実行します。


    maven-surefire-plugin
    2.19.1
    
        
            integration-test
            
                test
            
            
                
                    none
                
            
        
    

これで、プロセス全体を次のコマンドで実行できます:mvn -Pintegration clean install

7. 結論

このチュートリアルでは、SpringのApache CXFサポートについて説明しました。 特に、Spring構成ファイルを使用してWebサービスを公開する方法、および別の構成ファイルで宣言されたApache CXFプロキシファクトリによって作成されたプロキシを介してクライアントがそのサービスと対話する方法を示しました。

これらすべての例とコードスニペットの実装は、the linked GitHub projectにあります。