1概要

このチュートリアルでは、http://cxf.apache.org/[Apache CXF]フレームワークをSpring ** と一緒に構成および使用することに焦点を当てています – JavaまたはXML構成のいずれか。

Apache CXFに関するシリーズの第2弾です。

最初のもの

は、JAX-WS標準APIの実装としてのCXFの基本に焦点を当てていました。


2 Mavenの依存関係

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

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>3.1.6</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http</artifactId>
    <version>3.1.6</version>
</dependency>

Apache CXFアーティファクトの最新バージョンについては、https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.apache.cxf%22[apache-cxf]を参照してください。

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

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.1.RELEASE</version>
</dependency>

Spring成果物の最新版はhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.springframework%22[here]にあります。

最後に、従来の

web.xml

デプロイメント記述子の代わりにJava Servlet 3.0+ APIを使用してプログラムでアプリケーションを設定するので、以下のアーティファクトが必要になります。

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
</dependency>


こちら

Servlet 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

ファイルに次のサーブレット定義を含める必要があります。

<servlet>
    <servlet-name>cxf</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
    <servlet-mapping>
    <servlet-name>cxf</servlet-name>
    <url-pattern>/services/** </url-pattern>
</servlet-mapping>


3.3.

ServiceConfiguration

クラス

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

@Configuration
public class ServiceConfiguration {
   //Bean definitions
}

最初に必要なBeanは

SpringBus

です。これは、Apache CXFがSpring Frameworkと連携するための拡張機能を提供します。

@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 BaeldungImpl());
    endpoint.publish("http://localhost:8080/services/baeldung");
    return endpoint;
}


BaeldungImpl

クラスは、Webサービスインタフェースを実装するために使用されます。

その定義は次の小節で述べる。

あるいは、サーバーエンドポイントをXML設定ファイルで宣言することもできます。具体的には、以下の

cxf-servlet.xml

ファイルは、サブセクション3.1で定義されている

web.xml

デプロイメント記述子と連携し、まったく同じエンドポイントを記述しています。

<jaxws:endpoint
  id="baeldung"
  implementor="com.baeldung.cxf.spring.BaeldungImpl"
  address="http://localhost:8080/services/baeldung"/>

XML構成ファイルは、デプロイメント記述子に定義されているサーブレット名、つまり

cxf

に基づいて命名されています。


3.4. 型の定義

次に – これは前のサブセクションですでに述べた

implementor

の定義です:

@WebService(endpointInterface = "com.baeldung.cxf.spring.Baeldung")
public class BaeldungImpl implements Baeldung {
    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メタデータに含める

Baeldung

エンドポイントインタフェースの実装を提供します。

@WebService
public interface Baeldung {
    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は、

Baeldung

Webサービスのプロキシを表します。 JAX-WSプロキシを作成するためのファクトリである

JaxWsProxyFactoryBean

Beanの

create

メソッドの呼び出しによって作成されます。


JaxWsProxyFactoryBean

オブジェクトは、次のメソッドで作成および設定されています。

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

ファクトリの

serviceClass

プロパティはWebサービスインタフェースを示し、

address

プロパティはプロキシがリモート呼び出しを行うためのURLアドレスを示します。

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

<bean id="client" factory-bean="clientFactory" factory-method="create"/>
<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
    <property name="serviceClass" value="com.baeldung.cxf.spring.Baeldung"/>
    <property name="address" value="http://localhost:8080/services/baeldung"/>
</bean>


5テストケース

このセクションでは、Apache CXFによるSpringのサポートを説明するためのテストケースについて説明します。テストケースは

StudentTest

という名前のクラスで定義されています。

まず、前述の

ServiceConfiguration

設定クラスからSpringアプリケーションコンテキストをロードし、それを

context

フィールドにキャッシュする必要があります。

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

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

private Baeldung baeldungProxy = (Baeldung) context.getBean("client");

この

Baeldung

プロキシは、後述のテストケースで使用されます。

最初のテストケースでは、

hello

メソッドがプロキシ上でローカルに呼び出されたときの応答が、エンドポイント

implementor

がリモートWebサービスから返すものとまったく同じであることを証明します。

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

2番目のテストケースでは、生徒はプロキシ上の

register

メソッドをローカルに呼び出すことによってBaeldungコースに登録し、それがWebサービスを呼び出します。その後、そのリモートサービスは学生番号を計算し、それを発信者に返します。次のコードスニペットは、私たちが期待することを確認します。

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

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


6. 統合テスト

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

packaging

プロパティを宣言することで実現できます。

<packaging>war</packaging>

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

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
</plugin>

このプラグインはコンパイルされたソースコードをWARファイルにパッケージ化します。 Javaコードを使用してサーブレットコンテキストを設定するので、従来の

web.xml

デプロイメント記述子は存在する必要はありません。その結果、プラグインの実行時に失敗しないように、

failOnMissingWebXml

プロパティを

false

に設定する必要があります。


https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.apache.maven.plugins%22%20AND%20a%3A%22maven-war-plugin%22

[このリンクはMaven WARプラグインの最新版のためのものです。

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

以下のプラグインをMaven POMファイルに含める必要があります。詳細については、リンク:/apache-cxf-with-spring[この統合テストチュートリアル]をチェックしてください。

これがMaven Surefireプラグインです。

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19.1</version>
    <configuration>
        <excludes>
            <exclude>StudentTest.java</exclude>
        </excludes>
    </configuration>
</plugin>

このプラグインの最新バージョンはhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.apache.maven.plugins%22%20AND%20a%3A%22maven-にあります。 surefire-plugin%22[ここ]。


id



integration



profile

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

<profiles>
   <profile>
      <id>integration</id>
      <build>
         <plugins>
            ...
         </plugins>
      </build>
   </profile>
</profiles>

Maven Cargoプラグインは

integration

プロファイルに含まれています。

<plugin>
    <groupId>org.codehaus.cargo</groupId>
    <artifactId>cargo-maven2-plugin</artifactId>
    <version>1.5.0</version>
    <configuration>
        <container>
            <containerId>jetty9x</containerId>
            <type>embedded</type>
        </container>
        <configuration>
            <properties>
                <cargo.hostname>localhost</cargo.hostname>
                <cargo.servlet.port>8080</cargo.servlet.port>
            </properties>
        </configuration>
    </configuration>
    <executions>
        <execution>
            <id>start-server</id>
            <phase>pre-integration-test</phase>
            <goals>
                <goal>start</goal>
            </goals>
        </execution>
        <execution>
            <id>stop-server</id>
            <phase>post-integration-test</phase>
            <goals>
                <goal>stop</goal>
            </goals>
        </execution>
    </executions>
</plugin>


cargo.hostname

および

cargo.servlet.port

構成プロパティーは、わかりやすくするために含まれているだけです。これらの設定プロパティはデフォルト値と同じであるため、アプリケーションに影響を与えずに除外することができます。このプラグインはサーバーを起動し、接続を待ち、最後にサーバーを停止してシステムリソースを解放します。


このリンク

Maven Cargoプラグインの最新バージョンをチェックすることができます。

Maven Surefireプラグインは、

integration

プロファイル内で再度宣言され、メインの

build

セクションの設定をオーバーライドし、前のセクションで説明したテストケースを実行します。

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19.1</version>
    <executions>
        <execution>
            <phase>integration-test</phase>
            <goals>
                <goal>test</goal>
            </goals>
            <configuration>
                <excludes>
                    <exclude>none</exclude>
                </excludes>
            </configuration>
        </execution>
    </executions>
</plugin>

これで、プロセス全体をコマンド

mvn -Pintegration clean install

で実行できます。


7. 結論

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

これらすべての例とコードスニペットの実装はhttps://github.com/eugenp/tutorials/tree/master/apache-cxf/cxf-spring[リンクされたGitHubプロジェクト]にあります。