Apache-cxf-quick-guide

提供:Dev Guides
移動先:案内検索

Apache CXF-はじめに

今日の環境では、いくつかのオプションを使用してWebサービスアプリケーションを作成できます。 通信には、いくつかの標準プロトコルおよび広く受け入れられているプロトコルの1つ以上を使用できます。 たとえば、https://www.w3.org/TR/soap/[SOAP]、XML/HTTP、https://en.wikipedia.org/wiki/Representational_state_transfer [RESTful HTTP]、およびhttps://www.corba .org/[CORBA](Common Object Request Broker Architecture。昔は非常に人気がありましたが、現在はそれほど頻繁に使用されていません。

HTTP、https://en.wikipedia.org/wiki/Apache%20CXF_Message_Service [JMS]、https://en.wikipedia.org/wiki/Apache%20CXF_Business_Integration [JBI]などのさまざまなトランスポートを選択することもできます。 JAX-RSやhttps://en.wikipedia.org/wiki/Apache%20CXF_API_for_XML_Web_Services[JAXなどのフロントエンドAPIの選択-WS]。 Webサービス開発には非常に多くのオプションがあるため、上記のすべてのオプションを結合するオープンソースサービスフレームワークが必要であり、それがhttps://cxf.apache.org/[Apache CXF]の役割です。

このチュートリアルでは、上記の1つ以上のオプションを使用して、CXFを使用してWebサービスとサービスを使用するクライアントの両方を作成する方法を学習します。 このチュートリアルでは、サーバーとクライアントの両方のコード開発全体を説明します。 各アプリケーションは、各カテゴリのオプションの1つ(フロントエンド、トランスポート、プロトコル)のみを使用できるため、これら3つのすべての順列と組み合わせを考慮すると、アプリケーションの数は非常に多くなります。

このチュートリアルでは、次のプロジェクトの開発について詳しく説明します-

  • プレーンオールドApache CXFオブジェクト(POJO)を使用したCXF
  • JAX-WSを使用したCXF
  • WSDLを使用したCXF
  • JAX-RSを使用したCXF
  • JMSを使用したCXF

シンプルにするために、コマンドラインインターフェイスでmavenを使用しました。 Mavenプロジェクトの作成には、好みのIDEを使用できます。

次の章では、最初の章から始めましょう。

POJOを使用したApache CXF

この章では、ユーザーに挨拶メッセージを送信する単純なWebアプリケーションを開発する方法を学習します。 Webサービスプロジェクトは、https://www.w3.org/TR/2001/NOTE-wsdl-20010315 [WSDL]モデルを使用します。 CXFでは、Apache CXF APIを基盤となるWSDLにマッピングするためのシンプルなフロントエンドを提供することにより、このWSDLモデルを隠すことができます。

この最も単純なプロジェクトでは、Webサービスのインターフェイスがクライアントに直接公開され、クライアントはネイティブのApache CXF APIを使用してWebサービスを呼び出します。

最初に、Webサービスを作成します。 すべてのサービスには、クライアントに公開されるインターフェイスがあります。 このインターフェイスは、単純なApache CXFインターフェイスまたはWSDLドキュメントとして記述できます。 このApache CXF-Firstアプローチでは、Apache CXFインターフェイスを介してサービスを公開します。

Webサービスの開発

Web上で作成するサービスには、 greetings と呼ばれる単一のWebメソッドがあります。 このメソッドは、ユーザーの名前を送信する string 型の引数を取ります。 サービスは、受信したユーザー名をメッセージに含めて、グリーティングメッセージを発信者に送り返します。

Webサービスインタフェース

私たちのWebサービスのインターフェイスを公開するには、次のようにApache CXFインターフェイスを作成します-

//HelloWorld.java
package com.finddevguides.cxf.pojo;
public interface HelloWorld {
   String greetings(String text);
}

インターフェースには greetings というメソッドが1つだけあります。 サーバーはこのインターフェースを実装します。 簡単なアプリケーションでは、このインターフェイスはクライアントに直接公開されます。 通常、Webサービスアプリケーションでは、WSDLを使用してWebサービスインターフェイスを記述します。 この単純なアプリケーションでは、この直接インターフェースをクライアント開発者に提供します。 クライアントは、サーバーオブジェクトで greetings メッセージを呼び出します。 それでは、まずWebサービスを作成しましょう。

Webサービスの実装

*HelloWorld* インターフェースは、以下に示すように *HelloWorldImpl* Apache CXFクラスに実装されています-
//HelloWorldImpl.java
package com.finddevguides.cxf.pojo;
public class HelloWorldImpl implements HelloWorld {
   @Override
   public String greetings(String text) {
      return "Hi " + text;
   }
}
*greetings* メソッドは、 *string* タイプのパラメーターを受け取り、それをグリーティングメッセージに追加し、結果の文字列を呼び出し元に返します。

次に、 HelloWorld サービスをホストするサーバーアプリケーションを作成します。

サーバーの作成

サーバーアプリケーションは2つの部分で構成されています-

  • 最初の部分は、Webサービスのファクトリーを作成します。
  • 2番目の部分は、インスタンス化するための main メソッドを記述します。

サーバーは、CXFライブラリが提供する ServerFactoryBean クラスを使用して、 HelloWorld インターフェイスをリモートクライアントに公開します。 したがって、最初に ServerFactoryBean クラスをインスタンス化し、次にそのさまざまなプロパティを設定します-

ServerFactoryBean factory = new ServerFactoryBean();
*factory* オブジェクトで *setServiceClass* メソッドを呼び出して、サービスクラスを呼び出すように設定します-
factory.setServiceClass(HelloWorld.class);

ファクトリの setAddress メソッドを呼び出すことにより、サービスを呼び出すためのURLを設定します。 サービスはこのURLで公開されることに注意してください。

factory.setAddress("http://localhost:5000/Hello");

この場合、サービスは組み込みサーバーにデプロイされ、ポート5000をリッスンします。 任意のポート番号を選択できます。

ファクトリーを作成する前に、サービス実装クラスについてファクトリーに伝える必要があります。 これは、以下に示すように factory オブジェクトで setServiceBean メソッドを呼び出すことで実行されます-

factory.setServiceBean(new HelloWorldImpl());

サービスBeanは、サービス実装クラスのインスタンスに設定されます。 最後に、その create メソッドを呼び出してファクトリを作成します-

factory.create();

ここで、Webサービスを実行するファクトリを開発したので、次に main メソッドを記述して、それをインスタンス化し、しばらく実行し続けます。

今、次のように HelloServer クラスをインスタンス化する*メイン*メソッドを記述します-

public static void main(String[] args) throws Exception {
   new HelloServer();
   System.out.println("Listening on port 5000 ...");
}

インスタンス化されると、 HelloServer クラスは無期限に実行され続けます。 実稼働展開の場合、サーバーを永久に稼働させ続けることは間違いありません。 現在の状況では、次のように所定の時間後にサーバーを終了します-

Thread.sleep(5 *60* 1000);
System.out.println("Server exiting ...");
System.exit(0);
*HelloServer* クラスのコード全体を以下に示します-
//HelloServer.java
//HelloServer.java
package com.finddevguides.cxf.pojo;
import org.apache.cxf.frontend.ServerFactoryBean;
public class HelloServer {
   protected HelloServer() throws Exception {
      ServerFactoryBean factory = new ServerFactoryBean();
      factory.setServiceClass(HelloWorld.class);
      factory.setAddress("http://localhost:5000/Hello");
      factory.setServiceBean(new HelloWorldImpl());
      factory.create();
   }
   public static void main(String[] args) throws Exception {
      new HelloServer();
      System.out.println("Listening on port 5000 ...");
      Thread.sleep(5 *60* 1000);
      System.out.println("Server exiting ...");
      System.exit(0);
   }
}

作成したサーバーアプリケーションは、CXFライブラリの ServerFactoryBean クラスを使用します。 HelloServer クラスを正常にコンパイルするには、これらのライブラリをプロジェクトに含める必要があります。 プロジェクトの依存関係を設定するには、 Maven を使用します。

Mavenプロジェクトのセットアップ

Mavenプロジェクトを作成するには、コマンドラインウィンドウに次のコマンドを入力します。 これはMacマシンでテスト済みです。 WindowsおよびLinuxインストールの場合、いくつかの場所で手順が異なる場合があります。

mvn archetype:generate

プロパティを求められたら、次の値を入力します-

Define value for property 'groupId': : com.finddevguides
Define value for property 'artifactId': : cxf-pojo
Define value for property 'version': 1.0-SNAPSHOT: : 1.0
Define value for property 'package': com.finddevguides: : com.finddevguides.cxf.pojo

mavenコマンドが完了すると、pom.xmlファイルとともに現在のフォルダーに適切なフォルダー構造が作成されます。

生成されたディレクトリ構造はここに示されています-

ディレクトリ構造

*pom.xml* にCXF依存関係を追加し、上記で作成したApache CXFファイルを、Mavenで作成した構造の適切なフォルダーにコピーします。 すぐに参照できるように、マシンで作成したプロジェクトのpom.xmlファイルを以下に示します。
<?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.finddevguides</groupId>
   <artifactId>cxf-pojo</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>

   <profiles>
      <profile>
         <id>server</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.finddevguides.cxf.pojo.HelloServer
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>

      <profile>
         <id>client</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                           com.finddevguides.cxf.pojo.HelloClient
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
   </profiles>

   <dependencies>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-features-logging</artifactId>
         <version>3.3.0</version>
         <type>jar</type>
      </dependency>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-frontend-simple</artifactId>
         <version>3.3.0</version>
         <type>jar</type>
      </dependency>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http</artifactId>
         <version>3.3.0</version>
      </dependency>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-frontend-jaxws</artifactId>
         <version>3.3.0</version>
      </dependency>
      <!-- Jetty is needed if you're using the CXFServlet -->
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http-jetty</artifactId>
         <version>3.3.0</version>
      </dependency>
   </dependencies>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
   </properties>
</project>

上記のpom.xmlには、このプロジェクトに関係のない追加の依存関係が含まれている場合がありますが、このチュートリアルの次のプロジェクトには必要です。 とにかく、追加の依存関係を含めること自体に害はありません。

プロジェクトフォルダー構造

サーバーとクライアントのApache CXFファイルを配置した後の私のマシン上のプロジェクトフォルダ構造は、クイックリファレンスのために以下に示されています-

プロジェクトフォルダー構造

実行中のサーバー

プロジェクトをビルドするには、コマンドラインウィンドウで次のコマンドを使用します-

mvn clean install

次のコマンドを使用してサーバーを起動できます-

mvn -Pserver

これによりサーバーが起動し、コンソールに次のプロンプトが表示されます-

INFO: Creating Service {http://pojo.cxf.finddevguides.com/}HelloWorld from class com.finddevguides.cxf.pojo.HelloWorld
INFO: Setting the server's publish address to be http://localhost:5000/Hello
Listening on port 5000 ...

ブラウザウィンドウで、公開されたサービスのURLを指定します。 次の出力が表示されます-

出力ドキュメントツリー

これにより、ローカルホストの指定されたポートでサービスが実行されていることが確認されます。 呼び出しで greetings メッセージを指定しなかったため、SOAPエラーメッセージがブラウザーに返されます。

選択したSOAPクライアントを使用して、Webサービスをさらにテストできます。 ここでは、https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop//%40 [Postman]を使用してサーバーをテストしました。

出力はここに示されているようです-

サーバー出力の実行

*SOAP Request* が手動でコーディングされていることを確認してください。 リクエストを送信した後、サーバーは *SOAP Response* メッセージを送信しました。これはスクリーンショットの下部に表示されます。

このことから、CXFは要求と応答の両方でSOAPプロトコルの使用を維持しながら、今日の世界に存在するさまざまなWebテクノロジーに対する統一されたビューを提供することを理解できます。 これにより、Webアプリケーションの開発が大幅に簡素化されます。

次のタスクは、作成したWebサービスを使用するクライアントを作成することです。

クライアントを作成する

サーバーアプリケーションでは、 HelloWorld はWebサービスを公開するインターフェイスです。 Webサービス自体は、単純な挨拶メッセージをクライアントに提供するだけです。 通常、Webサービスインターフェイスは、WSDL(Webサービス記述言語)を使用して外部に公開されます。 この簡単なアプリケーションでは、サービスインターフェイスを直接公開することでWebサービスをクライアントに公開します。これが HelloWorld.class です。

この目的のために、CXFは ClientProxyFactoryBean と呼ばれるファクトリクラスを提供します。これにより、作成したファクトリインスタンスへの目的のインターフェイスにアタッチできます。

まず、次のようにファクトリBeanインスタンスを作成します-

ClientProxyFactoryBean factory = new ClientProxyFactoryBean();

ファクトリBeanインスタンスで setAddress メソッドを呼び出して、Webサービスを呼び出すURLを設定します。 私たちの場合、前のステップでサーバーを作成するときに使用したURLを使用します-

factory.setAddress("http://localhost:5000/Hello");

次に、 factory インスタンスで create メソッドを呼び出して、サービスインターフェイス HelloWorld.class をアタッチします。

HelloWorld helloServer = factory.create(HelloWorld.class);

最後に、 greetings メソッドを呼び出して、リモートWebサービスを呼び出します。

System.out.println(helloServer.greetings(System.getProperty("user.name")));

これにより、コンソールに挨拶メッセージが出力されます。

クライアントアプリケーションのソース全体を以下に示します-

//HelloClient.java
package com.finddevguides.cxf.pojo;
import org.apache.cxf.frontend.ClientProxyFactoryBean;
public class HelloClient {
   public static void main(String[] args) throws Exception {
      ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
      factory.setAddress("http://localhost:5000/Hello");
      HelloWorld helloServer = factory.create(HelloWorld.class);
      System.out.println(helloServer.greetings(System.getProperty("user.name")));
   }
}

実行中のクライアント

サーバーがまだマシン上で実行されていることを確認してください。 場合には、タイムアウトした場合は、次のコマンドでサーバーを再起動します-

mvn -Pserver

コンソールに次のメッセージが表示されます-

Listening on port 5000 ...

今、5分に設定したサーバーがタイムアウトする前に、別のコマンドラインウィンドウを開き、次のコマンドでクライアントを起動します-

mvn -Pclient

コマンドラインで次のようなメッセージが表示されます-

Hi finddevguides
*finddevguides* はユーザー名です。 自分の名前で挨拶を受け取ります。

次の章では、JAX-WS(XML Webサービス用のApache CXF API)プロジェクトでCXFを使用する方法を学習します。

JAX-WSを使用したApache CXF

このJAX-WSアプリケーションでは、以前のPOJOアプリケーションのようなApache CXFファーストのアプローチを使用します。 そのため、最初にWebサービスのインターフェイスを作成します。

サービスインターフェイスの宣言

前のケースと同様に、グリーティングと呼ばれるインターフェースメソッドを1つだけ持つ簡単なサービスを作成します。 サービスインターフェイスのコードは以下に示されています-

//HelloWorld.java
package com.finddevguides.cxf.jaxws.helloworld;
import javax.jws.WebService;

@WebService
public interface HelloWorld {
   String greetings(String text);
}

インターフェイスに @ WebService タグで注釈を付けます。 次に、このインターフェイスを実装します。

Webインターフェイスの実装

Webインターフェイスの実装はここに示されています-

//HelloWorldImpl.java
package com.finddevguides.cxf.jaxws.helloworld;
public class HelloWorldImpl implements HelloWorld {
   @Override
   public String greetings(String name) {
      return ("hi " + name);
   }
}

greetingsメソッドには @ Override タグで注釈が付けられています。 このメソッドは、呼び出し元に「hi」メッセージを返します。

次に、サーバーを開発するためのコードを記述します。

開発サーバー

POJOアプリケーションとは異なり、CXFが提供するEndpointクラスを使用してサービスを公開することにより、インターフェイスを分離します。 これは、次の2行のコードで行われます-

HelloWorld implementor = new HelloWorldImpl();
Endpoint.publish(
   "http://localhost:9090/HelloServerPort",
   implementor,
   new LoggingFeature()
);

publishメソッドの最初のパラメーターは、クライアントがサービスを利用できるURLを指定します。 2番目のパラメーターは、サービスの実装クラスを指定します。 サーバーのコード全体が以下に示されています-

//Server.java
package com.finddevguides.cxf.jaxws.helloworld;
import javax.xml.ws.Endpoint;
import org.apache.cxf.ext.logging.LoggingFeature;
public class Server {
   public static void main(String[] args) throws Exception {
      HelloWorld implementor = new HelloWorldImpl();
      Endpoint.publish("http://localhost:9090/HelloServerPort",
      implementor,
      new LoggingFeature());
      System.out.println("Server ready...");
      Thread.sleep(5 *60* 1000);
      System.out.println("Server exiting ...");
      System.exit(0);
   }
}

サーバーをデプロイするには、以下にリストされているように、プロジェクトにいくつかの変更を加える必要があります。

サーバーの展開

最後に、サーバーアプリケーションをデプロイするには、pom.xmlをもう1つ変更して、アプリケーションをWebアプリケーションとして設定する必要があります。 あなたが pom.xml に追加する必要があるコードは以下のとおりです-

<profiles>
   <profile>
      <id>server</id>
      <build>
         <defaultGoal>test</defaultGoal>
         <plugins>
            <plugin>
               <groupId>org.codehaus.mojo</groupId>
               <artifactId>exec-maven-plugin</artifactId>
               <version>1.6.0</version>
               <executions>
                  <execution>
                     <phase>test</phase>
                     <goals>
                        <goal>java</goal>
                     </goals>
                     <configuration>
                        <mainClass>
                           com.finddevguides.cxf.jaxws.helloworld.Server
                        </mainClass>
                     </configuration>
                  </execution>
               </executions>
            </plugin>
         </plugins>
      </build>
   </profile>
</profiles>

アプリケーションをデプロイする前に、プロジェクトにさらに2つのファイルを追加する必要があります。 これらは、以下のスクリーンショットに示されています-

JAXWSアプリケーションをデプロイする前

これらのファイルは、 CXFServlet のマッピングを定義するCXF標準ファイルです。 web.xml ファイル内のコードは、クイックリファレンスのためにここに示されています-

//Web.xml
<?xml version = "1.0" encoding = "UTF-8"??>
<web-app xmlns = "http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5"
xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
   <display-name>cxf</display-name>
   <servlet>
      <description>Apache CXF Endpoint</description>
      <display-name>cxf</display-name>
      <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>
   <session-config>
      <session-timeout>60</session-timeout>
   </session-config>
</web-app>
  • cxf-servlet.xml、*で、サービスのエンドポイントのプロパティを宣言します。 これは以下のコードスニペットに示されています-
<beans ...>
   <jaxws:endpoint xmlns:helloworld = "http://finddevguides.com/"
      id = "helloHTTP"
      address = "http://localhost:9090/HelloServerPort"
      serviceName = "helloworld:HelloServiceService"
      endpointName = "helloworld:HelloServicePort">
   </jaxws:endpoint>
</beans>

ここで、サービスエンドポイントのID、サービスを利用できるアドレス、サービス名、エンドポイント名を定義します。 これで、CXFサーブレットによってサービスがどのようにルーティングおよび処理されるかを学習しました。

最終的なpom.xml

*pom.xml* には、さらにいくつかの依存関係が含まれています。 すべての依存関係を記述するのではなく、pom.xmlの最終バージョンを以下に含めました-
<?xml version = "1.0" encoding = "UTF-8"??>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.finddevguides</groupId>
   <artifactId>cxf-jaxws</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
   </properties>
   <profiles>
      <profile>
         <id>server</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <version>1.6.0</version>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.finddevguides.cxf.jaxws.helloworld.Server
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
      <profile>
         <id>client</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        <goals>
                        <configuration>
                           <mainClass>
                              com.finddevguides.cxf.jaxws.helloworld.Client
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
   </profiles>
   <dependencies>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-frontend-jaxws</artifactId>
         <version>3.3.0</version>
      </dependency>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http</artifactId>
         <version>3.3.0</version>
      </dependency>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-features-logging</artifactId>
         <version>3.3.0</version>
      </dependency>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http-jetty</artifactId>
         <version>3.3.0</version>
      </dependency>
   </dependencies>
</project>

このチュートリアルの後半のセクションで学習するクライアントを構築するためのプロファイルも含まれていることに注意してください。

HelloWorldサービスの実行

これで、Webアプリを実行する準備が整いました。 コマンドウィンドウで、次のコマンドを使用してビルドスクリプトを実行します。

mvn clean install
mvn -Pserver

コンソールに次のメッセージが表示されます-

INFO: Setting the server's publish address to be http://localhost:9090/HelloServerPort
Server ready…

前と同じように、ブラウザでサーバーURLを開いてサーバーをテストできます。

サーバーのURLを開く

操作を指定しなかったため、アプリケーションからエラーメッセージのみがブラウザに返されます。

ここで、*?wsdl *をURLに追加してみてください。次の出力が表示されます-

image

したがって、サーバーアプリケーションは期待どおりに実行されています。 前述の Postman などのSOAPクライアントを使用して、サービスをさらにテストできます。

次のセクションでは、サービスを使用するクライアントの作成方法を学習します。

クライアントの開発

CXFアプリケーションでクライアントを作成するのは、サーバーを作成するのと同じくらい簡単です。 クライアントの完全なコードは次のとおりです-

//Client.java
package com.finddevguides.cxf.jaxws.helloworld;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;
public final class Client {
   private static final QName SERVICE_NAME
   = new QName("http://helloworld.jaxws.cxf.finddevguides.com/",
   "HelloWorld");
   private static final QName PORT_NAME
   = new QName("http://helloworld.jaxws.cxf.finddevguides.com/",
   "HelloWorldPort");
   private Client() {
   }
   public static void main(String[] args) throws Exception {
      Service service = Service.create(SERVICE_NAME);
      System.out.println("service created");
      String endpointAddress = "http://localhost:9090/HelloServerPort";
      service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING,
      endpointAddress);
      HelloWorld hw = service.getPort(HelloWorld.class);
      System.out.println(hw.greetings("World"));
   }
}

ここでは、CXF提供の Service クラスを使用して、既知のサービスにバインドします。 Service クラスで create メソッドを呼び出して、サービスのインスタンスを取得します。 service インスタンスで addPort メソッドを呼び出して、既知のポートを設定します。

これで、サービスを使用する準備ができました。まず、 service インスタンスで getPort メソッドを呼び出してサービスインターフェイスを取得します。 最後に、 greetings メソッドを呼び出して、コンソールに挨拶メッセージを印刷します。

Apache CXF-Firstアプローチを使用してCXFの基本を学習したので、次の章でWSDL-FirstアプローチでCXFを使用する方法を学習します。

WSDLを使用したApache CXF

開発したCXF-POJOアプリケーションにより、クライアントとサーバーが非常に緊密に結合されます。 また、サービスインターフェイスへの直接アクセスを許可すると、深刻なセキュリティ上の脅威になります。 そのため、通常、クライアントとサーバー間の分離が望まれます。これは、WSDL(Webサービス記述言語)を使用して実現されます。

XMLベースのWSDLドキュメントでWebサービスインターフェイスを記述します。 ツールを使用して、このWSDLをApache CXFインターフェースにマップし、クライアントおよびサーバーアプリケーションで実装および使用します。 デカップリングを提供するには、WSDLから開始することが好ましい方法です。 このためには、最初に新しい言語であるWSDLを学ぶ必要があります。 WSDLの作成には慎重なアプローチが必要であり、作業を開始する前にこれについてある程度理解しておくとよいでしょう。

このレッスンでは、WSDLドキュメントでWebサービスインターフェイスを定義することから始めます。 CXFを使用して、WSDLで始まるサーバーアプリケーションとクライアントアプリケーションの両方を作成する方法を学習します。 CXFの使用に重点を置いて、アプリケーションをシンプルに保ちます。 サーバーアプリケーションが作成されたら、組み込みのCXFクラスを使用して目的のURLに公開します。

最初に、使用するWSDLについて説明しましょう。

HelloWorldのWSDL

実装するWebサービスには、 greetings という1つのWebメソッドがあります。このメソッドは、ユーザー名を保持する string パラメーターを受け入れ、ユーザー名に挨拶メッセージを追加した後、呼び出し元に文字列メッセージを返します。 完全なWSDLは以下に示されています-

//Hello.wsdl
<?xml version = "1.0" encoding = "UTF-8"?>
<wsdl:definitions xmlns:soap = "http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:tns = "http://helloworld.finddevguides.com/"
   xmlns:wsdl = "http://schemas.xmlsoap.org/wsdl/"
   xmlns:xsd = "http://www.w3.org/2001/XMLSchema"
   name = "HelloWorld"
   targetNamespace = "http://helloworld.finddevguides.com/">
   <wsdl:types>
      <xsd:schema attributeFormDefault = "unqualified"
         elementFormDefault = "qualified"
         targetNamespace = "http://helloworld.finddevguides.com/">
         <xsd:element name = "greetings" type = "tns:greetings"/>
         <xsd:complexType name = "greetings">
            <xsd:sequence>
               <xsd:element minOccurs = "0" name = "arg0" type = "xsd:string"/>
            </xsd:sequence>
         </xsd:complexType>
         <xsd:element name = "greetingsResponse"
         type = "tns:greetingsResponse"/>
         <xsd:complexType name = "greetingsResponse">
            <xsd:sequence>
               <xsd:element minOccurs = "0" name = "return" type = "xsd:string"/>
            </xsd:sequence>
         </xsd:complexType>
      </xsd:schema>
   </wsdl:types>
   <wsdl:message name = "greetings">
      <wsdl:part element = "tns:greetings" name = "parameters"> </wsdl:part>
   </wsdl:message>
   <wsdl:message name = "greetingsResponse">
      <wsdl:part element = "tns:greetingsResponse" name = "parameters"> </wsdl:part>
   </wsdl:message>
   <wsdl:portType name = "HelloWorldPortType">
      <wsdl:operation name = "greetings">
         <wsdl:input message = "tns:greetings" name = "greetings">  </wsdl:input>
         <wsdl:output message = "tns:greetingsResponse" name = "greetingsResponse">
         </wsdl:output>
      </wsdl:operation>
   </wsdl:portType>
   <wsdl:binding name = "HelloWorldSoapBinding" type = "tns:HelloWorldPortType">
      <soap:binding style = "document"
      transport = "http://schemas.xmlsoap.org/soap/http"/>
      <wsdl:operation name = "greetings">
         <soap:operation soapAction = "" style = "document"/>
         <wsdl:input name = "greetings"></wsdl:input>
         <wsdl:output name = "greetingsResponse">
            <soap:body use = "literal"/>
         </wsdl:output>
         </wsdl:operation>
   </wsdl:binding>
   <wsdl:service name = "HelloWorldService">
      <wsdl:port binding = "tns:HelloWorldSoapBinding" name = "HelloWorldPort">
         <soap:address location = "http://localhost:9090/HelloServerPort"/>
      </wsdl:port>
   </wsdl:service>
</wsdl:definitions>

構文的に正しいwsdlを記述することは、開発者にとって常に課題でした。多くのツールがあり、wsdlを作成するためのオンラインエディターが利用できます。 これらのエディターは、実装するメッセージの名前と、メッセージで渡すパラメーター、およびクライアントアプリケーションで受信する戻りメッセージのタイプを要求します。 wsdl構文を知っている場合は、ドキュメント全体を手作業でコーディングするか、エディターの1つを使用して独自のエディターを作成できます。

上記のwsdlでは、 greetings という単一のメッセージを定義しています。 メッセージは、* http://localhost:9090/HelloServerPort。で実行されている *HelloWorldService というサービスに配信されます。

これにより、サーバー開発に進みます。 サーバーを開発する前に、WebサービスへのApache CXFインターフェイスを生成する必要があります。 これは、指定されたwsdlから実行されます。 これを行うには、 wsdl2java というツールを使用します。

wsdl2javaプラグイン

mavenを使用してプロジェクトをビルドするため、 pom.xml ファイルに次のプラグインを追加する必要があります。

<plugins>
   <plugin>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-codegen-plugin</artifactId>
      <version>3.3.0</version>
      <executions>
         <execution>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
            <configuration>
               <wsdlOptions>
                  <wsdlOption>
                     <wsdl>src/main/resources/hello.wsdl</wsdl>
                     <faultSerialVersionUID> 1 </faultSerialVersionUID>
                  </wsdlOption>
               </wsdlOptions>
            </configuration>
            <goals>
               <goal>wsdl2java</goal>
            </goals>
         </execution>
      </executions>
   </plugin>
</plugins>
*wsdl* ファイルの場所を *src/main/resources/Hello.wsdl* として指定していることに注意してください。 プロジェクトに適切なディレクトリ構造を作成し、前述の *hello.wsdl* ファイルを指定したフォルダーに追加することを確認する必要があります。
*wsdl2java* プラグインは、このwsdlをコンパイルし、事前定義されたフォルダーにApache CXFクラスを作成します。 完全なプロジェクト構造は、すぐに参照できるようにここに示されています。

WSDL2Apache CXF事前定義フォルダー

これで、 wsdl2java 生成クラスを使用してサーバーを作成する準備ができました。 wsdl2javaが作成したクラスを以下の図に示します-

WSDL2Apache CXF生成クラス

生成されたサービスインターフェイス

生成されたクラスのリストで、そのうちの1つがApache CXFインターフェースであることに注意してください。これは HelloWorldPortType.java です。 コードエディターでこのファイルを調べます。 ファイルの内容は、すぐに参照できるようにここに表示されます-

//HelloWorldPortType.java
package com.finddevguides.helloworld;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
/**
* This class was generated by Apache CXF 3.3.0
* 2019-02-11T12:05:55.220+05:30
* Generated source version: 3.3.0
*
*/

@WebService(targetNamespace = "http://helloworld.finddevguides.com/",
   name = "HelloWorldPortType")
@XmlSeeAlso({ObjectFactory.class})
public interface HelloWorldPortType {
   @WebMethod
   @RequestWrapper(localName = "greetings", targetNamespace =
      "http://helloworld.finddevguides.com/", className =
      "com.finddevguides.helloworld.Greetings")
      @ResponseWrapper(localName = "greetingsResponse", targetNamespace =
         "http://helloworld.finddevguides.com/", className =
         "com.finddevguides.helloworld.GreetingsResponse")
   @WebResult(name = "return", targetNamespace =
      "http://helloworld.finddevguides.com/")
   public java.lang.String greetings(
      @WebParam(name = "arg0", targetNamespace =
      "http://helloworld.finddevguides.com/")
      java.lang.String arg0
   );
}

インターフェイスには greetings というメソッドが含まれていることに注意してください。 これは、wsdlのメッセージタイプでした。 wsdl2java ツールは、生成されたインターフェースにこのメソッドを追加しました。 これで、wsdlに書き込むメッセージが何であれ、対応するメソッドがインターフェースで生成されることを理解できます。

ここで、タスクは、wsdlで定義したさまざまなメッセージに対応するこれらすべてのメソッドを実装することです。 Apache CXF-Firstの以前の例では、Webサービス用のApache CXFインターフェースから始めたことに注意してください。 この場合、Apache CXFインターフェースはwsdlから作成されます。

サービスインターフェイスの実装

サービスインターフェイスの実装は簡単です。 完全な実装は、以下のリストに示されています-

//HelloWorldImpl.java
package com.finddevguides.helloworld;
public class HelloWorldImpl implements HelloWorldPortType {
   @Override
   public String greetings(String name) {
      return ("hi " + name);
   }
}

このコードは、 greetings と呼ばれる唯一のインターフェイスメソッドを実装します。 このメソッドは string タイプのパラメーターを1つ受け取り、それに「hi」メッセージを付加して、結果のストリングを呼び出し元に返します。

次に、サーバーアプリケーションを作成します。

開発サーバー

サーバーアプリケーションの開発は簡単です。 ここでは、CXFが提供する Endpoint クラスを使用してサービスを公開します。 これは、次の2行のコードで行われます-

HelloWorldPortType implementor = new HelloWorldImpl();
   Endpoint.publish("http://localhost:9090/HelloServerPort",
      implementor,
      new LoggingFeature());

まず、サービス実装クラスのオブジェクト- HelloWorldImpl を作成します。 次に、この参照を publish メソッドの2番目のパラメーターとして渡します。 最初のパラメーターはサービスが公開されるアドレスです-クライアントはこのURLを使用してサービスにアクセスします。 サーバーアプリケーションのソース全体がここに与えられています-

//Server.java
package com.finddevguides.helloworld;
import javax.xml.ws.Endpoint;
import org.apache.cxf.ext.logging.LoggingFeature;
public class Server {
   public static void main(String[] args) throws Exception {
      HelloWorldPortType implementor = new HelloWorldImpl();
      Endpoint.publish("http://localhost:9090/HelloServerPort",
         implementor,
         new LoggingFeature());
      System.out.println("Server ready...");
      Thread.sleep(5 *60* 1000);
      System.out.println("Server exiting");
      System.exit(0);
   }
}

このサーバークラスをビルドするには、 pom.xml にビルドプロファイルを追加する必要があります。 これは以下に示されています-

<profile>
   <id>server</id>
   <build>
      <defaultGoal>test</defaultGoal>
      <plugins>
         <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.6.0</version>
            <executions>
               <execution>
                  <phase>test</phase>
                  <goals>
                     <goal>java</goal>
                  </goals>
                  <configuration>
                     <mainClass>
                        com.finddevguides.helloworld.Server
                     </mainClass>
                  </configuration>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
   <dependencies>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http-jetty</artifactId>
         <version>3.3.0</version>
      </dependency>
   </dependencies>
</profile>
*Server* クラスの完全修飾名が構成で指定されていることに注意してください。 また、依存関係タグは、埋め込みJetty Webサーバーを使用してサーバーアプリケーションを展開することを指定します。

サーバーの展開

最後に、サーバーアプリケーションをデプロイするには、pom.xmlをもう1つ変更して、アプリケーションをWebアプリケーションとして設定する必要があります。 あなたが pom.xml に追加する必要があるコードは以下のとおりです-

<defaultGoal>install</defaultGoal>
<pluginManagement>
   <plugins>
      <plugin>
         <artifactId>maven-war-plugin</artifactId>
         <version>3.2.2</version>
         <configuration>
            <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
            <webResources>
               <resource>
                  <directory>src/main/resources</directory>
                  <targetPath>WEB-INF</targetPath>
                  <includes>
                     <include>*.wsdl</include>
                  </includes>
               </resource>
            </webResources>
         </configuration>
      </plugin>
   </plugins>
</pluginManagement>

アプリケーションをデプロイする前に、プロジェクトにさらに2つのファイルを追加する必要があります。 これらは、以下のスクリーンショットに示されています-

WSDLアプリケーションのデプロイ前

これらのファイルは、 CXFServlet のマッピングを定義するCXF標準ファイルです。 web.xml ファイル内のコードは、クイックリファレンスのためにここに示されています-

//cxf-servlet.xml
<web-app xmlns = "http://java.sun.com/xml/ns/javaee"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" version="2.5"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
   <display-name>cxf</display-name>
   <servlet>
      <description>Apache CXF Endpoint</description>
      <display-name>cxf</display-name>
      <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>
   <session-config>
      <session-timeout>60</session-timeout>
   </session-config>
</web-app>
*cxf-servlet.xml* で、サービスのエンドポイントのプロパティを宣言します。 これは以下のコードスニペットに示されています-
<beans ...>
   <jaxws:endpoint xmlns:helloworld = "http://finddevguides.com/"
      id="helloHTTP"
      address = "http://localhost:9090/HelloServerPort"
      serviceName = "helloworld:HelloServiceService"
      endpointName = "helloworld:HelloServicePort">
   </jaxws:endpoint>
</beans>

ここで、サービスエンドポイントのID、サービスを利用できるアドレス、サービス名、エンドポイント名を定義します。 これで、サービスがCXFサーブレットによってどのようにルーティングおよび処理されるかを理解できました。

最終的なpom.xml

*pom.xml* には、さらにいくつかの依存関係が含まれています。 すべての依存関係を記述するのではなく、pom.xmlの最終バージョンを以下に含めました-
<?xml version="1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.finddevguides</groupId>
   <artifactId>cxf-wsdl</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
   </properties>
   <build>
      <defaultGoal>install</defaultGoal>
      <pluginManagement>
         <plugins>
            <plugin>
               <artifactId>maven-war-plugin</artifactId>
               <version>3.2.2</version>
               <configuration>
                  <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
                  <webResources>
                     <resource>
                        <directory>src/main/resources</directory>
                        <targetPath>WEB-INF</targetPath>
                        <includes>
                           <include>*.wsdl</include>
                        </includes>
                     </resource>
                  </webResources>
               </configuration>
            </plugin>
         </plugins>
      </pluginManagement>
      <plugins>
         <plugin>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-codegen-plugin</artifactId>
            <version>3.3.0</version>
            <executions>
               <execution>
                  <id>generate-sources</id>
                  <phase>generate-sources</phase>
                  <configuration>
                     <wsdlOptions>
                        <wsdlOption>
                           <wsdl>src/main/resources/Hello.wsdl</wsdl>
                           <faultSerialVersionUID>1</faultSerialVersionUID>
                        </wsdlOption>
                     </wsdlOptions>
                  </configuration>
                  <goals>
                     <goal>wsdl2java</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
   <profiles>
      <profile>
         <id>server</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <version>1.6.0</version>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.finddevguides.helloworld.Server
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
         <dependencies>
            <dependency>
               <groupId>org.apache.cxf</groupId>
               <artifactId>cxf-rt-transports-http-jetty</artifactId>
               <version>3.3.0</version>
            </dependency>
         </dependencies>
      </profile>
      <profile>
         <id>client</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.finddevguides.helloworld.Client
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
   </profiles>
   <dependencies>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-frontend-jaxws</artifactId>
         <version>3.3.0</version>
      </dependency>

      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http</artifactId>
         <version>3.3.0</version>
      </dependency>

      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-management</artifactId>
         <version>3.3.0</version>
      </dependency>

      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-features-metrics</artifactId>
         <version>3.3.0</version>
      </dependency>

      <dependency>
         <groupId>org.apache.cxf.xjc-utils</groupId>
         <artifactId>cxf-xjc-runtime</artifactId>
         <version>3.3.0</version>
      </dependency>

      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-features-logging</artifactId>
         <version>3.3.0</version>
      </dependency>

     <dependency>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>exec-maven-plugin</artifactId>
         <version>1.6.0</version>
      </dependency>

      <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-api</artifactId>
         <version>1.8.0-beta2</version>
      </dependency>

      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http-jetty</artifactId>
         <version>3.3.0</version>
      </dependency>
   </dependencies>
</project>

クライアントを構築するためのプロファイルも含まれていることに注意してください。これについては、後のセクションで間もなく学習します。

HelloWorldサービスの実行

これで、Webアプリを実行する準備が整いました。 コマンドウィンドウで、次のコマンドを使用してビルドスクリプトを実行します。

mvn clean install

これにより、wsdlから適切なApache CXFクラスが生成され、Apache CXFクラスがコンパイルされ、組み込みJettyサーバーにサーバーがデプロイされ、アプリケーションが実行されます。

コンソールに次のメッセージが表示されます-

INFO: Setting the server's publish address to be
http://localhost:9090/HelloServerPort
Server ready...

前と同様に、ブラウザでサーバーURLを開いてサーバーをテストできます。

サーバーのURLを開く

操作を指定しなかったため、アプリケーションからエラーメッセージのみがブラウザに返されます。 ここで、*?wsdl *をURLに追加してみてください。次の出力が表示されます-

WSDL出力

したがって、サーバーアプリケーションは期待どおりに実行されています。 前述の Postman などのSOAPクライアントを使用して、サービスをさらにテストできます。

このチュートリアルの次の部分は、サービスを使用するクライアントを作成することです。

クライアントの開発

CXFアプリケーションでクライアントを作成することは、サーバーを作成することと同じくらい重要です。 基本的に3行のみで構成されるクライアントの完全なコードを次に示します。残りの行は、サービス情報をユーザーに出力するだけです。

//Client.java
package com.finddevguides.helloworld;
public class Client {
   public static void main(String[] args) throws Exception {
     //Create the service client with its default wsdlurl
      HelloWorldService helloServiceService = new HelloWorldService();
      System.out.println("service: " +
         helloServiceService.getServiceName());
      System.out.println("wsdl location: " +
         helloServiceService.getWSDLDocumentLocation());
      HelloWorldPortType helloService =
         helloServiceService.getHelloWorldPort();
      System.out.println(helloService.greetings
      (System.getProperty("user.name")));
   }
}

ここでは、サービス HelloWorldService のインスタンスを作成し、 getHelloWorldPort メソッドを呼び出してポートを取得してから、 greetings メッセージを渡します。 クライアントを実行すると、次の出力が表示されます-

service: {http://helloworld.finddevguides.com/}HelloWorldService
wsdl location: file:/Users/drsarang/Desktop/tutorialpoint/cxf-
wsdl/src/main/resources/Hello.wsdl
hi drsarang

これまで、Apache CXF-FirstおよびWSDL-FirstアーキテクチャーでCXFを使用する方法を学びました。 Apache CXF-Firstアプローチでは、CXFライブラリの ServerFactoryBean クラスでPOJOを使用してサーバーを作成しました。 クライアントを作成するには、CXFライブラリの ClientProxyFactoryBean クラスを使用しました。 WSDL-Firstアプローチでは、 Endpoint クラスを使用して、目的のURLおよび指定された実装者でサービスを公開しました。 これらの手法を拡張して、さまざまなプロトコルとトランスポートを統合できるようになりました。

JAX-RSを使用したApache CXF

この章に進む前に、JavaでRESTful Webサービスを作成する方法を知っていることを前提としています。 このJAX-RS(RESTful WebサービスのJava API)上でCXFを使用する方法を紹介します。 最新の映画のリストを保持するWebサービスを作成します。 ユーザーが映画をリクエストするとき、ユーザーはリクエストで映画IDを指定し、サーバーは映画を見つけてクライアントに返します。 些細なケースでは、実際のバイナリMP4ファイルではなく、映画の名前をクライアントに返すだけです。 JAX-RSアプリケーションの作成を始めましょう。

ムービー要素の宣言

特定の映画のIDと名前を保存するために、MovieというXMLルート要素を宣言します。 この要素は、Movie.javaというファイルで宣言されています。 ファイルの内容はここに示されています-

//Movie.java
package com.finddevguides.cxf.jaxrs.movie;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "Movie")
public class Movie {
   private long id;
   private String name;
   public long getId() {
      return id;
   }
   public void setId(long id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}
*Movie* タグのXML要素を宣言するための *XmlRootElement* タグの使用に注意してください。 次に、データベースに映画のリストを保持するサービスを作成します。

ムービーサービスデータベースの作成

映画のリストを保存するには、キーと値のペアを保存するJava提供の Map を使用します。 リストが大きい場合は、管理しやすい外部データベースストレージを使用します。 些細なケースでは、データベースには5つの映画だけを保存します。 MovieServiceクラスのコードは以下のとおりです-

//MovieService.java
package com.finddevguides.cxf.jaxrs.movie;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@Path("/movieservice/")
@Produces("text/xml")
public class MovieService {
   long currentId = 123;
   Map<Long, Movie> movies = new HashMap<>();
   public MovieService() {
      init();
   }
   @GET
   @Path("/movie/{id}/")
   public Movie getMovie(@PathParam("id") String id) {
      long idNumber = Long.parseLong(id);
      return movies.get(idNumber);
   }
   final void init() {
      Movie c1 = new Movie();
      c1.setName("Aquaman");
      c1.setId(1001);
      movies.put(c1.getId(), c1);

      Movie c2 = new Movie();
      c2.setName("Mission Imposssible");
      c2.setId(1002);
      movies.put(c2.getId(), c2);

      Movie c3 = new Movie();
      c3.setName("Black Panther");
      c3.setId(1003);
      movies.put(c3.getId(), c3);

      Movie c4 = new Movie();
      c4.setName("A Star is Born");
      c4.setId(1004);
      movies.put(c4.getId(), c4);

      Movie c5 = new Movie();
      c5.setName("The Meg");
      c5.setId(1005);
      movies.put(c5.getId(), c5);
   }
}

次の2つの注釈を使用して、ムービーサービスのURLパスとその戻り値の型を指定することに注意してください-

@Path("/movieservice/")
@Produces("text/xml")

私たちは@GETと@Pathアノテーションを使用して、GETリクエストのURLを次のように指定します-

@GET
@Path("/movie/{id}/")

ムービーデータベース自体はinitメソッドで初期化され、データベースに5つのムービーアイテムを追加します。

次のタスクは、サーバーアプリケーションを作成することです。

開発サーバー

サーバーを作成するには、CXF提供の JAXRSServerFactoryBean クラスを使用します。

JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
*setResourceClasses* メソッドを呼び出して、リソースクラスを設定します。
factory.setResourceClasses(Movie.class);
factory.setResourceClasses(MovieService.class);
*setResourceProvider* メソッドを呼び出して、サービスプロバイダーを設定します。
factory.setResourceProvider(MovieService.class,
new SingletonResourceProvider(new MovieService()));
*aetAddress* メソッドを呼び出して、目的の *publish* アドレスを設定します-
factory.setAddress("http://localhost:9000/");

最後に、 factory インスタンスでcreateメソッドを呼び出してサーバーを公開します。

factory.create();

サーバーアプリケーションのコード全体は以下のとおりです-

//Server.java
package com.finddevguides.cxf.jaxrs.movie;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
public class Server {
   public static void main(String[] args) throws Exception {
      JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
      factory.setResourceClasses(Movie.class);
      factory.setResourceClasses(MovieService.class);
      factory.setResourceProvider(MovieService.class,
         new SingletonResourceProvider(new MovieService()));
      factory.setAddress("http://localhost:9000/");
      factory.create();

      System.out.println("Server ready...");
      Thread.sleep(5 *60* 1000);

      System.out.println("Server exiting ...");
      System.exit(0);
   }
}

最終的なpom.xml

ここで、pom.xmlの最終バージョンを以下に含めました-

<?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.finddevguides</groupId>
   <artifactId>cxf-jaxrs</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
   </properties>
   <profiles>
      <profile>
         <id>server</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <version>1.6.0</version>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.finddevguides.cxf.jaxrs.movie.Server
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
         <dependencies>
            <dependency>
               <groupId>org.apache.cxf</groupId>
               <artifactId>cxf-rt-transports-http-jetty</artifactId>
               <version>3.3.0</version>
            </dependency>
         </dependencies>
      </profile>
      <profile>
         <id>client</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.finddevguides.cxf.jaxrs.movie.Client
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
   </profiles>
   <dependencies>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http</artifactId>
         <version>3.3.0</version>
      </dependency>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http-jetty</artifactId>
         <version>3.3.0</version>
      </dependency>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-frontend-jaxrs</artifactId>
         <version>3.3.0</version>
         </dependency>
      <dependency>
         <groupId>jakarta.ws.rs</groupId>
         <artifactId>jakarta.ws.rs-api</artifactId>
         <version>2.1.5</version>
      </dependency>
      <dependency>
         <groupId>org.apache.httpcomponents</groupId>
         <artifactId>httpclient</artifactId>
         <version>4.5.7</version>
      </dependency>
   </dependencies>
</project>

クライアントの開発

RSクライアントの作成は簡単です。 URLオブジェクトを作成して、そのストリームを開きます。 CXFが提供するIOUtilsクラスを使用して、入力ストリームのコンテンツをローカルストリームにコピーします。

URL url = new URL("http://localhost:9000/movieservice/movie/1002");
try (InputStream instream = url.openStream();
CachedOutputStream outstream = new CachedOutputStream()) {
   IOUtils.copy(instream, outstream);
}

クライアントアプリケーションのコード全体は以下のとおりです-

//Client.java
package com.finddevguides.cxf.jaxrs.movie;
import java.io.InputStream;
import java.net.URL;
import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.io.CachedOutputStream;
public class Client {
   public static void main(String[] args) throws Exception {
      URL url = new URL("http://localhost:9000/movieservice/movie/1002");
      try (InputStream instream = url.openStream();
      CachedOutputStream outstream = new CachedOutputStream()) {
         IOUtils.copy(instream, outstream);
         String str = outstream.getOut().toString();
         System.out.println(str);
      }
   }
}

JAX-RSアプリケーションのテスト

コマンドラインウィンドウで次のコマンドを使用してサーバーを実行します-

mvn -Pserver

今、あなたはコンソールに次のメッセージが表示されます-

INFO: Setting the server's publish address to be http://localhost:9000

今、あなたのブラウザを開き、次のURLを入力します-

http://localhost:9000/movieservice/movie/1002

ブラウザウィンドウに次のように表示されます。

ブラウザウィンドウ

別のコマンドラインウィンドウで次のコマンドを実行して開発したJavaクライアントアプリケーションを使用して、サービスを呼び出すことができます。

mvn -Pclient

次の出力が表示されます-

<?xml version="1.0" encoding = "UTF-8" standalone="yes"?>
<Movie><id>1002</id><name>Mission Imposssible</name></Movie>

CXFサンプルは、JAX-RSでCXFを使用する方法に関するいくつかの例を提供します。 興味のある読者は、これらのサンプルを研究することが奨励されます。

JMSを使用したApache CXF

前述のように、JMSトランスポートでCXFを使用できます。 この場合、クライアントは既知のMessaging ServerにJMSメッセージを送信します。 私たちのサーバーアプリケーションは、受信メッセージを求めてメッセージングサーバーを継続的にリッスンしています。 メッセージが到着すると、メッセージを処理し、クライアント要求を実行し、応答を別のメッセージとしてクライアントに送信します。

前述のように、 sayHi という単一のWebメソッドを提供するサンプルサーバーアプリケーションを最初に作成します。

サービスインターフェイスの作成

*HelloWorld* サービスのサービスインターフェイスを次に示します-
//HelloWorld.java
package com.finddevguides.service;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

@WebService
public interface HelloWorld {
   @WebMethod
   String sayHi(@WebParam(name = "name") String name);
}

サービスの実装

サービスインターフェイスの実装は次のように定義されています-

//HelloWorldImpl.java
package com.finddevguides.service.impl;

import javax.jws.WebService;
import com.finddevguides.service.HelloWorld;

@WebService
public class HelloWorldImpl implements HelloWorld {
   @Override
   public String sayHi(String name) {
      return "Hello " + name;
   }
}

実装は単純にHelloメッセージをユーザーに返します。 ご覧のとおり、インターフェイスとその実装は、これまで学習したこのチュートリアルの以前のすべてのプロジェクトに似ています。

次に、メッセージキューを設定し、着信メッセージをリッスンし続けるサーバーアプリケーションを作成することが最も重要なポイントになります。

サーバーの作成

サーバーアプリケーションでは、最初に次のように JMS エンドポイントを作成します-

private static final String JMS_ENDPOINT_URI =
   "jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"
      + "&jndiConnectionFactoryName=ConnectionFactory"
      + "&jndiInitialContextFactory"
      + "= org.apache.activemq.jndi.ActiveMQInitialContextFactory"
      + "&jndiURL = tcp://localhost:61616";

指定された期間存続する指定されたポートにキューを設定することに注意してください。 org.apache.activemq.broker.BrokerService クラスをインスタンス化して、メッセージングサービスを作成します。 これは、 ActiveMQ メッセージングサーバーのサーバークラスです。

BrokerService broker = new BrokerService();
*ActiveMQ* 以外の任意のメッセージングサーバーを使用できます。 このサーバーを目的のURIに接続します。
broker.addConnector("tcp://localhost:61616");

私たちは、着信メッセージのデータストレージ用のディレクトリを設定します-

broker.setDataDirectory("target/activemq-data");

最後に、startメソッドを使用してサーバーを起動します-

broker.start();

次に、以前のPOJOアプリケーションで使用されているサーバーファクトリBeanクラスを使用して、サービスBean HelloWorld のインスタンスを作成します-

Object implementor = new HelloWorldImpl();
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
factory.setServiceClass(HelloWorld.class);

次に、ファクトリが受信メッセージをリッスンし続けるように、ファクトリにJMSエンドポイントを設定します-

factory.setTransportId
(JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setAddress(JMS_ENDPOINT_URI);

最後に、ファクトリで実装クラスを設定し、実行を開始します-

factory.setServiceBean(implementor);
factory.create();

この時点で、サーバーは稼働しています。 POJOアプリケーションのようにファクトリBeanクラスを使用しているため、CXFServletとweb.xmlファイルは不要であることに注意してください。

完全なサーバーアプリケーションコードはここに示されています-

//ServerJMS.java
package com.finddevguides.server;

import java.util.Collections;
import org.apache.cxf.ext.logging.LoggingFeature;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.apache.cxf.transport.jms.spec.JMSSpecConstants;
import com.finddevguides.service.HelloWorld;
import com.finddevguides.service.impl.HelloWorldImpl;
import org.apache.activemq.broker.BrokerService;

public final class ServerJMS {

   private static final String JMS_ENDPOINT_URI =
      "jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"
         + "&jndiConnectionFactoryName=ConnectionFactory"
         + "&jndiInitialContextFactory"
         + "= org.apache.activemq.jndi.ActiveMQInitialContextFactory"
         + "&jndiURL = tcp://localhost:61616";

   public static void main(String[] args) throws Exception {

      BrokerService broker = new BrokerService();
      broker.addConnector("tcp://localhost:61616");
      broker.setDataDirectory("target/activemq-data");
      broker.start();

      Object implementor = new HelloWorldImpl();
      JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
      factory.setServiceClass(HelloWorld.class);
      factory.setTransportId
      (JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
      factory.setAddress(JMS_ENDPOINT_URI);
      factory.setServiceBean(implementor);
      factory.setFeatures(Collections.singletonList(new LoggingFeature()));
      factory.create();

      System.out.println("Server ready...");
      Thread.sleep(5 *60* 1000);
      System.out.println("Server exiting");
      System.exit(0);
   }
}

依存関係の追加

作成したサーバーアプリケーションは、ActiveMQメッセージングサーバーを使用します。 したがって、プロジェクトにいくつかの依存関係を追加する必要があります。 追加の必要な依存関係を理解するために、完全なpom.xmlファイルがここに表示されます。

<?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.finddevguides</groupId>
   <artifactId>cxf-jms</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
   </properties>

   <profiles>
      <profile>
         <id>server</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <version>1.6.0</version>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.finddevguides.server.ServerJMS
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
      <profile>
         <id>client</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.finddevguides.client.ClientJMS
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
   </profiles>

   <dependencies>
      <dependency>
         <groupId>org.apache.activemq</groupId>
         <artifactId>activemq-broker</artifactId>
         <version>5.15.8</version>
      </dependency>

      <dependency>
         <groupId>org.apache.activemq</groupId>
         <artifactId>activemq-kahadb-store</artifactId>
         <version>5.15.8</version>
      </dependency>

      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-frontend-jaxws</artifactId>
         <version>3.3.0</version>
      </dependency>

      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-jms</artifactId>
         <version>3.3.0</version>
      </dependency>

      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-features-logging</artifactId>
         <version>3.3.0</version>
      </dependency>

      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http-jetty</artifactId>
         <version>3.3.0</version>
      </dependency>
   </dependencies>
</project>

実行中のサーバー

以前の場合のように、サーバーの実行を開始するには、コマンドウィンドウに次のコマンドを入力します-

mvn -Pserver

これにより、ActiveMQメッセージサーバーが起動し、メッセージングキューが設定され、このキューをリッスンし続けるファクトリBeanが作成されます。

次のタスクは、クライアントアプリケーションを作成することです。

クライアントを作成する

クライアントアプリケーションでは、最初にサーバーアプリケーションで使用されるものと同じJMSエンドポイントを設定します-

private static final String JMS_ENDPOINT_URI =
   "jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"
      + "&jndiConnectionFactoryName=ConnectionFactory"
      + "&jndiInitialContextFactory"
      + " = org.apache.activemq.jndi.ActiveMQInitialContextFactory"
      + "&jndiURL = tcp://localhost:61616";

POJOアプリケーションのようにファクトリーを作成します。

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

次のようにエンドポイントURIと実装クラスを設定します-

factory.setTransportId (JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setAddress (JMS_ENDPOINT_URI);
HelloWorld client = factory.create(HelloWorld.class);

最後に、サービスメソッドを呼び出して、その結果の出力を印刷します-

String reply = client.sayHi("finddevguides");
System.out.println(reply);

完全なクライアントコードは以下のとおりです-

//ClientJMS.java
package com.finddevguides.client;

import com.finddevguides.service.HelloWorld;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.jms.spec.JMSSpecConstants;

public final class ClientJMS {
   private static final String JMS_ENDPOINT_URI =
   "jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"
   + "&jndiConnectionFactoryName=ConnectionFactory"
   + "&jndiInitialContextFactory"
   + " = org.apache.activemq.jndi.ActiveMQInitialContextFactory"
   + "&jndiURL = tcp://localhost:61616";

   public static void main(String[] args) throws Exception {
      JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
      factory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
      factory.setAddress(JMS_ENDPOINT_URI);
      HelloWorld client = factory.create(HelloWorld.class);
      String reply = client.sayHi("finddevguides");
      System.out.println(reply);
      System.exit(0);
   }
}

Apache CXF-結論

CXFは、今日の世界に存在するいくつかのWebプロトコルとトランスポートを組み合わせてWebアプリケーションを作成するための統合アプローチを提供します。 従来のJavaインターフェースから始めて、CXFを使用するWebアプリケーションを作成する方法を学びました。 次に、WSDLからWebアプリケーションとそのクライアントを作成する方法を学びました。

WSDLは、サービスインターフェイスのXML表現を提供します。 wsdl2javaツールを使用してWSDLからJavaインターフェースを作成し、最終的に作成されたインターフェースを使用してサーバーとクライアントの両方を作成しました。 このチュートリアルでは、RESTful WebサービスアプリケーションでCXFを使用する方法についても簡単に紹介しました。 最後に、CXFをJMSで使用する方法についても説明しました。 今後の調査については、https://cxf.apache.org/docs/sample-projectsl [CXF-samples]を参照してください。

-プロジェクトのソースコード全体は、ここからダウンロードできます。