サービスインタフェースにおける xsd:any による XML ドキュメントの記述: デザインの詳細

java.net 主催の bpcatalog プロジェクトにあるドキュメント指向のアプリケーションは、ドキュメント中心のインタフェースとエンドポイントをデザインする際にドキュメント型として xsd:any を使用する方法の具体例です。このアプリケーションには、ドキュメント型として xsd:any を使用するようにデザインされたサービスエンドポイントがあります。XML ドキュメントは、クライアントが送信する注文書で表されます。

このアプリケーションは、3 つの主要エンティティーで構成されています。

サービスの WSDL ファイル

コード例 1 の WSDL ファイルは、Web サービスの記述です。開発スタイルとしては、WSDL から始めて、そこから必要な Java[tm] クラスを生成するスタイルを採用しました。このため、WSDL のメッセージ部に適切な型を選択することは非常に重要です。WSDL ファイル内のこれらの型が、生成される Java コードに含まれるパラメータの型になるためです。戻り値ばかりでなく、submitPO メソッドに対するパラメータとして送信されるドキュメントにも <any/> 型が指定されていることに注意してください。また、WSDL 内にアプリケーション定義のサービス例外が宣言されていることにも注意してください。

<types>
  <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="urn:AnyPurchaseOrderService">
    <complexType name="submitPO">
      <sequence>
          <any/>                       
      </sequence>
    </complexType>
    <complexType name="submitPOResponse">
    <sequence>
          <any/>                       
    </sequence>
    </complexType>
      <complexType name="InvalidPOException">
    <sequence>
      <element name="message" type="string" nillable="true"/>                   
    </sequence>
    </complexType>
    <element name="submitPO" type="tns:submitPO"/>
    <element name="submitPOResponse" type="tns:submitPOResponse"/>
    <element name="InvalidPOException" type="tns:InvalidPOException"/>
    </schema>
</types>
<message name="AnyPurchaseOrderServiceSEI_submitPO">
    <part name="parameters" element="tns:submitPO"/>
</message>
<message name="AnyPurchaseOrderServiceSEI_submitPOResponse">
    <part name="result" element="tns:submitPOResponse"/>
</message>
<message name="InvalidPOException">
    <part name="InvalidPOException" element="tns:InvalidPOException"/>
</message>
<portType name="AnyPurchaseOrderServiceSEI">
    <operation name="submitPO">
      <input message="tns:AnyPurchaseOrderServiceSEI_submitPO"/>
      <output message="tns:AnyPurchaseOrderServiceSEI_submitPOResponse"/>
      <fault name="InvalidPOException" message="tns:InvalidPOException"/>
    </operation>
</portType>
コード例 1: サービスの WSDL からの抜粋

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

WSDL から始めているため、コード例 2 のサービスエンドポイントインタフェースは、WSDL に含まれる情報に基づいて生成されます。サービスエンドポイントインタフェースには、SubmitPO オブジェクトを受け付ける submitPO() メソッドがあります。クラス SubmitPO は、WSDL に定義されている xsd:any を含む複合型に対応し、基本的には、javax.xml.soap.SOAPElement 表現の XML 注文書ドキュメントを含むラッパークラスにすぎない JavaBeans[tm] コンポーネントです。 xsd:any を使用して応答型が指定されているため、返される XML ドキュメントにも、SOAPELement として注文書 XML ドキュメントを含む、SubmitPOResponse というラッパー JavaBeans クラスが含まれることに注意してください。アプリケーション定義の例外 InvalidPOException も WSDL から生成されます。

public interface AnyPurchaseOrderServiceSEI extends Remote {
    public SubmitPOResponse submitPO(SubmitPO parameters) throws
        InvalidPOException, RemoteException;
}
コード例 2: サービスエンドポイントインタフェース

コード例 3 は、WSDL から生成される SubmitPO クラスを示しています。この JavaBeans ラッパークラスには、SOAPElement 要素として注文書 XML ドキュメントが含まれます。

public class SubmitPO {
    protected javax.xml.soap.SOAPElement _any;

public SubmitPO() {
}

public SubmitPO(javax.xml.soap.SOAPElement _any) {
this._any = _any;
}
public javax.xml.soap.SOAPElement get_any() {
return _any;
}
public void set_any(javax.xml.soap.SOAPElement _any) {
this._any = _any;
}
}
コード例 3: SOAP 要素として、WSDL から生成される注文書 XML ドキュメントを含む SubmitPO ラッパークラス

Java エンドポイント実装

このアプリケーションでは、Web コンポーネントを使用して、サービスインタフェースを実装しています。コード例 4 は、エンドポイント実装クラスを示しています。別の方法として、Enterprise JavaBeans[tm] (EJB[tm]) コンポーネントを使用して、このエンドポイントを実装することもできます。どちらでも問題ありません。ここで大切なことは、注文書 XML が SOAPElement として扱われ、コード例 3 に示す SubmoitPO ラッパークラスで取得メソッドが呼び出されたあとに、使用されることです。

public class AnyPurchaseOrderServiceImpl implements
        AnyPurchaseOrderServiceSEI, ServiceLifecycle {
   
    private ServletEndpointContext context;
    private POXMLUtil xmlUtil;
   
    public void init(Object context) {
        this.context = (ServletEndpointContext) context;
        xmlUtil = new POXMLUtil();
    }
   
    public void destroy() {}
   
    public SubmitPOResponse submitPO(SubmitPO request) throws InvalidPOException, RemoteException {
        String id = null;
        SubmitPOResponse reply = null;
        try{
            SOAPElement requestdata= request.get_any();
            // PO ID を抽出
            NodeList list = ((Element)requestdata).getElementsByTagNameNS("urn:AnyTypePurchaseOrderService", "poId");
           
            for (int loop = 0; loop < list.getLength(); loop++) {
                Node node = list.item(loop);
                if (node != null) {
                    Node child = node.getFirstChild();
                    if ((child != null) && child.getNodeValue() != null){
                        id = child.getNodeValue();
                    }
                }
            }
            SOAPElement replydata = xmlUtil.createSOAPMessage(id);
            reply = new SubmitPOResponse();
            reply.set_any(replydata);
        } catch(Exception exe){
            throw new RuntimeException("AnyPOService Having Problems:"+exe.getMessage(), exe);
        }
        // アプリケーションに固有の例外のスローを紹介することのみを目的としたコード
        if(id.equals("100"))
            throw new InvalidPOException("Invalid ID for the purchase order!!! " +
                    "For demo purposes, we throw " +
                    "an application defined exception for the ID value of 100.");
        return reply;
    }
}
コード例 4: エンドポイント実装

配備記述子

J2EE[tm] プラットフォーム (Java[tm] 2 Platform, Enterprise Edition) 内の Web サービスは、WAR あるいは EAR ファイルなどの配備モジュールにパッケージングされます。このアプリケーションでは、WAR ファイルとしてパッケージングしました。Web サービスエンドポイントを移植可能な形式でパッケージングするには、Java クラスばかりでなく、いくつかの配備記述子が必要です。以下は、エンドポイント配備記述子からの抜粋です。

<servlet>
  <description>Endpoint for AnyPO Web Service</description>
  <display-name>AnyPurchaseOrderServiceImpl</display-name>
  <servlet-name>AnyPurchaseOrderServiceImpl</servlet-name>
  <servlet-class>com.sun.j2ee.blueprints.anyposervice.AnyPurchaseOrderServiceImpl</servlet-class>
  <load-on-startup>0</load-on-startup>
</servlet>
コード例 5: web.xml 配備記述子からの抜粋

エンドポイントには、次に示すような Web サービス配備記述子ファイルの webservices.xml も必要です。

<webservice-description>
<webservice-description-name>AnyPurchaseOrderService</webservice-description-name>
<wsdl-file>WEB-INF/wsdl/AnyPurchaseOrderService.wsdl</wsdl-file>
<jaxrpc-mapping-file>WEB-INF/anypurchaseorderservice-mapping.xml</jaxrpc-mapping-file>
  <port-component>
    <description>port component description</description>
    <port-component-name>AnyPurchaseOrderService</port-component-name>
    <wsdl-port xmlns:anypons="urn:AnyPurchaseOrderService">anypons:AnyPurchaseOrderServiceSEIPort
    </wsdl-port>
<service-endpoint-interface>com.sun.j2ee.blueprints.anyposervice.AnyPurchaseOrderServiceSEI
     </service-endpoint-interface>
<service-impl-bean>
     <servlet-link>AnyPurchaseOrderServiceImpl</servlet-link>
</service-impl-bean>
</port-component>
</webservice-description>
コード例 6: webservice.xml 配備記述子からの抜粋

Web サービス配備記述子ファイルには、WSDL ファイルや JAX-RPC マッピングファイルなどの名前や、サービスエンドポイントインタフェース名、サービス実装クラス名などのサービスに関する情報が含まれます。
© Sun Microsystems 2005. All of the material in The Java BluePrints Solutions Catalog is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.