1. 概要

Java API for XML Webサービス(JAX-WS)は、SOAP(Simple Object Access Protocol)Webサービスを作成および使用するための標準化されたAPIです。

この記事では、SOAP Webサービスを作成し、JAX-WSを使用してそれに接続します。

2. 石鹸

SOAPは、ネットワークを介してメッセージを送信するためのXML仕様です。 SOAPメッセージは、どのオペレーティングシステムからも独立しており、HTTPやSMTPを含むさまざまな通信プロトコルを使用できます。

SOAPはXMLを多用するため、ツール/フレームワークで使用するのが最適です。 JAX-WSは、SOAPの使用を簡素化するフレームワークです。 これは標準のJavaの一部です。

3. トップダウンvs。 一気飲み

SOAPWebサービスを構築する方法は2つあります。 トップダウンアプローチまたはボトムアップアプローチを使用できます。

トップダウン(コントラクトファースト)アプローチでは、WSDLドキュメントが作成され、必要なJavaクラスがWSDLから生成されます。 ボトムアップ(コントラクトラスト)アプローチでは、 Javaクラスが記述され、WSDLはJavaクラスから生成されます。

Webサービスの複雑さによっては、WSDLファイルの作成が非常に難しい場合があります。 これにより、ボトムアップアプローチがより簡単なオプションになります。 一方、WSDLはJavaクラスから生成されるため、コードを変更すると、WSDLが変更される可能性があります。 これは、トップダウンアプローチには当てはまりません。

この記事では、両方のアプローチを見ていきます。

4. Webサービス定義言語(WSDL)

WSDL は、利用可能なサービスのコントラクト定義です。 これは、入出力メッセージの仕様であり、Webサービスを呼び出す方法です。 これは言語に依存せず、XMLで定義されています。

WSDLドキュメントの主要な要素を見てみましょう。

4.1. 定義

definitions 要素は、すべてのWSDLドキュメントのルート要素です。 名前、名前空間などを定義します。 ご覧のとおり、サービスの範囲は非常に広くなっています。

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" 
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
  xmlns:tns="http://jaxws.baeldung.com/" 
  xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
  xmlns:wsp="http://www.w3.org/ns/ws-policy" 
  xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy"
  xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  targetNamespace="http://jaxws.baeldung.com/" 
  name="EmployeeService">
  ...
</definitions>

4.2. 種類

types 要素は、Webサービスで使用されるデータ型を定義します。 WSDLは、相互運用性を支援する型システムとして XSD (XMLスキーマ定義)を使用します。

<definitions ...>
    ...
    <types>
        <xsd:schema>
            <xsd:import namespace="http://jaxws.baeldung.com/" 
              schemaLocation = "http://localhost:8080/employeeservice?xsd=1" />
        </xsd:schema>
    </types>
    ...
</definitions>

4.3. メッセージ

message 要素は、送信されるデータの抽象的な定義を提供します。 各message要素は、サービスメソッドの入力または出力と考えられる例外を説明します。

<definitions ...>
    ...
    <message name="getEmployee">
        <part name="parameters" element="tns:getEmployee" />
    </message>
    <message name="getEmployeeResponse">
        <part name="parameters" element="tns:getEmployeeResponse" />
    </message>
    <message name="EmployeeNotFound">
        <part name="fault" element="tns:EmployeeNotFound" />
    </message>
    ...
</definitions>

4.4. 操作とポートタイプ

portType 要素は、実行可能な各操作と、関連するすべてのメッセージ要素を記述します。 たとえば、 getEmployee 操作は、要求 input output 、およびWebサービスoperation[によってスローされる可能性のあるfault例外を指定します。 X179X]:

<definitions ...>
    ...
    <portType name="EmployeeService">
        <operation name="getEmployee">
            <input 
              wsam:Action="http://jaxws.baeldung.com/EmployeeService/getEmployeeRequest" 
              message="tns:getEmployee" />
            <output 
              wsam:Action="http://jaxws.baeldung.com/EmployeeService/getEmployeeResponse" 
              message="tns:getEmployeeResponse" />
            <fault message="tns:EmployeeNotFound" name="EmployeeNotFound" 
              wsam:Action="http://jaxws.baeldung.com/EmployeeService/getEmployee/Fault/EmployeeNotFound" />
        </operation>
    ....
    </portType>
    ...
</definitions>

4.5. バインディング

binding 要素は、各portTypeのプロトコルとデータ形式の詳細を提供します。

<definitions ...>
    ...
    <binding name="EmployeeServiceImplPortBinding" 
      type="tns:EmployeeService">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" 
          style="document" />
        <operation name="getEmployee">
            <soap:operation soapAction="" />
            <input>
                <soap:body use="literal" />
            </input>
            <output>
                <soap:body use="literal" />
            </output>
            <fault name="EmployeeNotFound">
                <soap:fault name="EmployeeNotFound" use="literal" />
            </fault>
        </operation>
        ...
    </binding>
    ...
</definitions>

4.6. サービスとポート

service 要素は、Webサービスでサポートされるポートを定義します。 serviceport要素は、サービスの name binding 、およびaddressを定義します。

<definitions ...>
    ...
    <service name="EmployeeService">
        <port name="EmployeeServiceImplPort" 
          binding="tns:EmployeeServiceImplPortBinding">
            <soap:address 
              location="http://localhost:8080/employeeservice" />
        </port>
    </service>
    ...
</definitions>

5. トップダウン(契約優先)アプローチ

WSDLファイルを作成することによるトップダウンアプローチから始めましょう employeeservicetopdown.wsdl。 簡単にするために、1つの方法しかありません。

<?xml version="1.0" encoding="UTF-8"?>
<definitions 
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:tns="http://topdown.server.jaxws.baeldung.com/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns="http://schemas.xmlsoap.org/wsdl/"
  targetNamespace="http://topdown.server.jaxws.baeldung.com/"
  qname="EmployeeServiceTopDown">
    <types>
        <xsd:schema 
          targetNamespace="http://topdown.server.jaxws.baeldung.com/">
            <xsd:element name="countEmployeesResponse" type="xsd:int"/>
        </xsd:schema>
    </types>

    <message name="countEmployees">
    </message>
    <message name="countEmployeesResponse">
        <part name="parameters" element="tns:countEmployeesResponse"/>
    </message>
    <portType name="EmployeeServiceTopDown">
        <operation name="countEmployees">
            <input message="tns:countEmployees"/>
            <output message="tns:countEmployeesResponse"/>
        </operation>
    </portType>
    <binding name="EmployeeServiceTopDownSOAP" 
      type="tns:EmployeeServiceTopDown">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" 
          style="document"/>
        <operation name="countEmployees">
            <soap:operation 
              soapAction="http://topdown.server.jaxws.baeldung.com/
              EmployeeServiceTopDown/countEmployees"/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
        </operation>
    </binding>
    <service name="EmployeeServiceTopDown">
        <port name="EmployeeServiceTopDownSOAP" 
          binding="tns:EmployeeServiceTopDownSOAP">
            <soap:address 
              location="http://localhost:8080/employeeservicetopdown"/>
        </port>
    </service>
</definitions>

5.1. 生成 WSDLからのWebサービスソースファイル

WSDLドキュメントからWebサービスソースファイルを生成する方法はいくつかあります。

1つの方法は、JDK8まで( $ JAVA_HOME / binにある)JDKの一部であるwsimportツールを使用することです。

コマンドプロンプトから:

wsimport -s . -p com.baeldung.jaxws.server.topdown employeeservicetopdown.wsdl

使用されるコマンドラインオプション:-pはターゲットパッケージを指定します。 -s は、生成されたソースファイルを配置する場所を指定します。

それ以降のJDKバージョンでは、ここで説明されているように、MojoHausによるjaxws-maven-pluginを使用できます。

または、 SpringでのSOAPWebサービスの呼び出しで詳しく説明されているように、org.jvnet.jaxb2maven-jaxb2-pluginが便利です。

生成されたファイル:

  • EmployeeServiceTopDown.java –メソッド定義を含むサービスエンドポイントインターフェイス(SEI)です
  • ObjectFactory.java –プログラムでスキーマ派生クラスのインスタンスを作成するためのファクトリメソッドが含まれています
  • EmployeeServiceTopDown_Service.java –JAX-WSクライアントで使用できるサービスプロバイダークラスです。

5.2. Webサービスエンドポイントインターフェイス

wsimport ツールは、WebサービスエンドポイントインターフェイスEmployeeServiceTopDownを生成しました。 Webサービスメソッドを宣言します。

@WebService(
  name = "EmployeeServiceTopDown", 
  targetNamespace = "http://topdown.server.jaxws.baeldung.com/")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@XmlSeeAlso({
    ObjectFactory.class
})
public interface EmployeeServiceTopDown {
    @WebMethod(
      action = "http://topdown.server.jaxws.baeldung.com/"
      + "EmployeeServiceTopDown/countEmployees")
    @WebResult(
      name = "countEmployeesResponse", 
      targetNamespace = "http://topdown.server.jaxws.baeldung.com/", 
      partName = "parameters")
    public int countEmployees();
}

5.3. Webサービスの実装

wsimport ツールは、Webサービスの構造を作成しました。 Webサービスの実装を作成する必要があります。

@WebService(
  name = "EmployeeServiceTopDown", 
  endpointInterface = "com.baeldung.jaxws.server.topdown.EmployeeServiceTopDown",
  targetNamespace = "http://topdown.server.jaxws.baeldung.com/")
public class EmployeeServiceTopDownImpl 
  implements EmployeeServiceTopDown {
 
    @Inject 
    private EmployeeRepository employeeRepositoryImpl;
 
    @WebMethod
    public int countEmployees() {
        return employeeRepositoryImpl.count();
    }
}

6. ボトムアップ(契約-最後)アプローチ

ボトムアップアプローチでは、エンドポイントインターフェイスと実装クラスの両方を作成する必要があります。 WSDLは、Webサービスが公開されるときにクラスから生成されます。

Employeeデータに対して簡単なCRUD操作を実行するWebサービスを作成しましょう。

6.1. モデルクラス

Employee モデルクラス:

public class Employee {
    private int id;
    private String firstName;

    // standard getters and setters
}

6.2. Webサービスエンドポイントインターフェイス

Webサービスメソッドを宣言するWebサービスエンドポイントインターフェイス:

@WebService
public interface EmployeeService {
    @WebMethod
    Employee getEmployee(int id);

    @WebMethod
    Employee updateEmployee(int id, String name);

    @WebMethod
    boolean deleteEmployee(int id);

    @WebMethod
    Employee addEmployee(int id, String name);

    // ...
}

このインターフェースは、Webサービスの抽象コントラクトを定義します。 使用される注釈:

  • @WebService は、それがWebサービスインターフェースであることを示します
  • @WebMethod は、Webサービス操作をカスタマイズするために使用されます
  • @WebResult は、戻り値を表すXML要素の名前をカスタマイズするために使用されます

6.3. Webサービスの実装

Webサービスエンドポイントインターフェイスの実装クラス:

@WebService(endpointInterface = "com.baeldung.jaxws.EmployeeService")
public class EmployeeServiceImpl implements EmployeeService {
 
    @Inject 
    private EmployeeRepository employeeRepositoryImpl;

    @WebMethod
    public Employee getEmployee(int id) {
        return employeeRepositoryImpl.getEmployee(id);
    }

    @WebMethod
    public Employee updateEmployee(int id, String name) {
        return employeeRepositoryImpl.updateEmployee(id, name);
    }

    @WebMethod
    public boolean deleteEmployee(int id) {
        return employeeRepositoryImpl.deleteEmployee(id);
    }

    @WebMethod
    public Employee addEmployee(int id, String name) {
        return employeeRepositoryImpl.addEmployee(id, name);
    }

    // ...
}

7. Webサービスエンドポイントの公開

Webサービス(トップダウンおよびボトムアップ)を公開するには、アドレスとWebサービス実装のインスタンスをjavax.xmlのpublish()メソッドに渡す必要があります。 ws.Endpoint クラス:

public class EmployeeServicePublisher {
    public static void main(String[] args) {
        Endpoint.publish(
          "http://localhost:8080/employeeservicetopdown", 
           new EmployeeServiceTopDownImpl());

        Endpoint.publish("http://localhost:8080/employeeservice", 
          new EmployeeServiceImpl());
    }
}

これで、EmployeeServicePublisherを実行してWebサービスを開始できます。 CDI機能を利用するために、WebサービスをWARファイルとしてWildFlyやGlassFishなどのアプリケーションサーバーにデプロイできます。

8. リモートWebサービスクライアント

次に、 EmployeeServiceWebサービスにリモートで接続するためのJAX-WSクライアントを作成しましょう。

8.1. クライアントアーティファクトの生成

JAX-WSクライアントアーティファクトを生成するために、wsimportツールをもう一度使用できます。

wsimport -keep -p com.baeldung.jaxws.client http://localhost:8080/employeeservice?wsdl

生成されたEmployeeService_Serviceクラスは、URLおよびQNameを使用してサーバーポートを取得するロジックをカプセル化します。

8.2. Webサービスへの接続

Webサービスクライアントは、生成された EmployeeService_Service を使用してサーバーに接続し、リモートでWebサービス呼び出しを行います。

public class EmployeeServiceClient {
    public static void main(String[] args) throws Exception {
        URL url = new URL("http://localhost:8080/employeeservice?wsdl");

        EmployeeService_Service employeeService_Service 
          = new EmployeeService_Service(url);
        EmployeeService employeeServiceProxy 
          = employeeService_Service.getEmployeeServiceImplPort();

        List<Employee> allEmployees 
          = employeeServiceProxy.getAllEmployees();
    }
}

9. 結論

この記事は、JAX-WSを使用したSOAPWebサービスの簡単な紹介です。

JAX-WSAPIを使用してSOAPWebサービスを作成するために、ボトムアップとトップダウンの両方のアプローチを使用しました。 また、サーバーにリモート接続してWebサービス呼び出しを行うことができるJAX-WSクライアントも作成しました。

完全なソースコードは、GitHubから入手できます。