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


java.net 主催の bpcatalog プロジェクトには、ドキュメント中心のインタフェースおよびエンドポイントのデザインにアタッチメントを使用する方法の具体例としてドキュメント指向のアプリケーションが用意されています。このアプリケーションには、アタッチメントを使用して注文を処理するようにデザインされたサービスエンドポイントがあります。XML ドキュメントは、クライアントが送信する注文書で表されます。このアプリケーションでは、注文書はアタッチメントとして受信され、注文書 ID を含む短い XML ドキュメントがアタッチメントとして返されます。つまり、この例では、Web サービスの対話でアタッチメントを使用して XML ドキュメントを交換する 2 通りの方法が提供されます。

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

サービスの WSDL ファイル

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

受け取る注文書と返される短い XML メッセージの型を少し詳しく見てみましょう。両方ともアタッチメントですが、異なる型が使用されています。アタッチメントのスキーマが、WSDL ファイル内の <import namespace="http://ws-i.org/profiles/basic/1.1/xsd" schemaLocation="WS-ISwA.xsd"/> を使用してインポートされていることに注意してください。この文があることによって、サービスからアタッチメントとして返される注文書 ID を含む短い XML ドキュメントで、この型を使用することができます。この文では、wsi:swaRef を使用して、スキーマファイルに定義されている型を参照しています。submitPO オペレーションでサービスが注文書を受け取るにあたり、ドキュメントにはその型に xsd:hexBinary が使用され、そのバインドでは、MIME の内容の種類として text/xml が指定されています。この MIME の種類が選択されることで、JAX-RPC 実行時環境は、そのドキュメントを Java の javax.xml.transform.Source オブジェクトにマッピングします。この WSDL ファイルを使用して、コード例 3 の Java インタフェースが生成されると、アタッチメントに対するこれら 2 つの型が、2 つの異なる Java の型にマッピングされます。

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:tns="urn:AttachmentPurchaseOrderService" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="urn:AttachmentPurchaseOrderService" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="urn:AttachmentPurchaseOrderService" name="AttachmentPurchaseOrderService">

   <types>
    <schema xmlns="http://www.w3.org/2001/XMLSchema"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
     xmlns:wsi="http://ws-i.org/profiles/basic/1.1/xsd" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
     targetNamespace="urn:AttachmentPurchaseOrderService">
    <import namespace="http://ws-i.org/profiles/basic/1.1/xsd" schemaLocation="WS-ISwA.xsd"/>
    <element name="statusmessage" type="wsi:swaRef"/>
    <element name="InvalidPOException" type="string"/>
    </schema>
   </types>
   
    <message name="AttachmentPurchaseOrderServiceSEI_submitPO">
          <part name="attachment_1" type="xsd:hexBinary"/>
    </message>

    <message name="AttachmentPurchaseOrderServiceSEI_submitPOResponse">
        <part name="response" element="ns1:statusmessage"/>
    </message>
       
        <message name="InvalidPOException">
        <part name="InvalidPOException" element="ns1:InvalidPOException"/>
    </message>

    <portType name="AttachmentPurchaseOrderServiceSEI">
        <operation name="submitPO">
            <input message="tns:AttachmentPurchaseOrderServiceSEI_submitPO"/>
            <output message="tns:AttachmentPurchaseOrderServiceSEI_submitPOResponse"/>
                        <fault name="InvalidPOException" message="tns:InvalidPOException"/>
        </operation>
    </portType>

    <binding name="AttachmentPurchaseOrderServiceSEIBinding" type="tns:AttachmentPurchaseOrderServiceSEI">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="submitPO">
            <input>
                <mime:multipartRelated>       
                                        <mime:part>
                        <soap:body use="literal"/>
                    </mime:part>
                    <mime:part>
                        <mime:content part="attachment_1" type="text/xml"/>
                    </mime:part>
                </mime:multipartRelated>
            </input>
            <output>
                <mime:multipartRelated>
                    <mime:part>
                        <soap:body parts="response"  use="literal"/>
                    </mime:part>
                </mime:multipartRelated>
            </output>
                        <fault name="InvalidPOException">
                <soap:fault name="InvalidPOException" use="literal"/>
            </fault>
        </operation>
    </binding>
    <service name="AttachmentPurchaseOrderService">
        <port name="AttachmentPurchaseOrderServiceSEIPort" binding="tns:AttachmentPurchaseOrderServiceSEIBinding">
            <soap:address location="http://localhost:8080/webservice/AttachmentPurchaseOrderService"/>
        </port>
    </service>
</definitions>

コード例 1: アタッチメントを使用して XML ドキュメントを交換するサービスの WSDL からの抜粋

コード例 1 の WSDL ファイルは、アタッチメントを持つ SOAP のスキーマをインポートすることに注意してください。このスキーマはかなり短いですから、これも見てみましょう。コード例 2 は、インポートされるスキーマです。このスキーマは、xsd:anyURI に基づく、wsi:swaRef という型を作成します。

<?xml version="1.0" encoding="utf-8" ?>
<!-- July, 2002
    (c) Copyright 2003, The Web Services-Interoperability Organization (WS-I)
    Download or use of this file is governed by the Policies and Bylaws of WS-I.
    For more information, send email info@ws-i.org.    
-->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
 targetNamespace="http://ws-i.org/profiles/basic/1.1/xsd"
 xmlns:tns="http://ws-i.org/profiles/basic/1.1/xsd">
    <xsd:simpleType name="swaRef">
        <xsd:restriction base="xsd:anyURI" />
    </xsd:simpleType>
</xsd:schema>
コード例 2: アタッチメントを持つ SOAP のスキーマ

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

WSDL から始めていますから、サービスエンドポイントインタフェースは、WSDL に含まれる情報に基づいて生成されます。サービスエンドポイントインタフェースには、javax.xml.transform.Source オブジェクトを受け付ける submitPO() メソッドがあります。また、アプリケーション定義の例外 InvalidPOException も WSDL から生成されます。このインタフェースは、Attachment Profile スキーマを使用する wsi:swaRef アタッチメント型に対しては java.net.URI 型を返し、xsd:hexBinary 型を使用して指定されたアタッチメントとして受信された注文書 XML ドキュメントには、javax.xml.transform.Source 型を使用することに注意してください。

public interface AttachmentPurchaseOrderServiceSEI extends Remote {
    public URI submitPO(Source attachment_1) throws
        InvalidPOException, RemoteException;
}
コード例 3: サービスエンドポイントインタフェース

Java エンドポイント実装

このアプリケーションの場合は、EJB[tm] コンポーネントを使用して、サービスインタフェースを実装しています。コード例 4 は、エンドポイント実装クラスを示しています。代わりに、Web コンポーネントを使用してエンドポイントを実装することもできます。どちらでも問題ありません。WS-I Attachment Profile 1.0 を使用し、アタッチメントとして返信メッセージを送信する方法を簡単に見てみましょう。セッションコンテキストからメッセージコンテキストを読み出す方法、メッセージコンテキストにアタッチメントコンテキストプロパティーを設定する方法に注意してください。この型のアタッチメントのサポートはアプリケーションサーバーに依存するため、J2EE[TM] 1.4 プラットフォームによって、この処理は異なることがあります。

public class AttachmentPurchaseOrderServiceBean implements SessionBean {
   
    private SessionContext sc;
    private TransformerFactory transfactory;
   
    public AttachmentPurchaseOrderServiceBean() {}
   
    /**
     * This method implements a web service that processes an XML purchase
     * order document it receives as an attachment
     * and returns a WS-I Attachment profile conformat message
     * using the swaRef data type
     */
    public java.net.URI submitPO(Source xmlsrc) throws InvalidPOException, RemoteException{
        URI uri = null;
        String id = null;
        try {
            Transformer transformer = transfactory.newTransformer();
            DOMResult result = new DOMResult();
            transformer.transform(xmlsrc, result);
            Document doc = (Document)result.getNode();
            Element root = doc.getDocumentElement();
            NodeList list = root.getElementsByTagName("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();
                }
            }
            MessageContext mc = sc.getMessageContext();
            AttachmentPart att = MessageFactory.newInstance().createMessage().createAttachmentPart();
            att.setContentId(" < "+ id + " >");
            att.setContent("<submitPO response/>","text/plain");
            ArrayList arrList = new ArrayList();
            arrList.add(att);
            // アプリケーションサーバーの実装によって異なる
            mc.setProperty("com.sun.xml.rpc.attachment.SetAttachmentContext", arrList);
            uri = new java.net.URI("cid:" + id);
        } catch (Exception e) {
            throw new EJBException("AttachmentPOService Having Problems:"+e.getMessage(),  e);
        }
        // アプリケーションに固有の例外のスローを紹介することのみを目的としたコード
        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 uri;
    }
   
// ライフサイクルメソッド
   ...
}
コード例 4: エンドポイント実装 Java クラス

ドキュメントの交換にアタッチメントを使用するこの種のサービスのクライアントのコードも簡単に見てみましょう。コード例 5 は、この Web サービスにアクセスするクライアントアプリケーションのコードの一部です。このクライアントアプリケーションは、サービスからの WSDL ファイルを使用して、サービスへのアクセスに使用できる Java クラスを生成することに注意してください。この Java サービスインタフェースは、WSDL ファイルに指定されている型にマッピングされている Java 型を使って生成されています。submitPO に対するパラメータとして注文書を渡すには、クライアントコード側で、XML ドキュメントから Java ソースオブジェクトを作成する必要がありました。この submitPO メソッドによって返される短い XML ドキュメントには、Java URI オブジェクトが使用されています。

public class  AttachmentPOServiceBD {
   
    ...
   
    public String submitPO(PurchaseOrder po) throws RequestHandlerException {
        try {
            AttachmentPurchaseOrderServiceSEI port = (AttachmentPurchaseOrderServiceSEI)
            serviceLocator.getServicePort(JNDINames.ATTACHMENT_SERVICE_REF,
                    AttachmentPurchaseOrderServiceSEI.class);
            String xmlDoc = po.toXMLString();
            Source src = new StreamSource(new StringReader(xmlDoc));
            URI resp= port.submitPO(src);
            return resp.getSchemeSpecificPart();
        } catch(InvalidPOException ipe){
            ...
    }
}

コード例 5: アタッチメント Web サービスにアクセスするクライアントアプリケーションからの抜粋

配備記述子

J2EE 内の Web サービスは、WAR あるいは EAR ファイルなどの配備モジュールにパッケージングされます。このアプリケーションでは、EAR ファイルとしてパッケージングしました。Web サービスエンドポイントを移植可能な形式でパッケージングするには、Java クラスばかりでなく、いくつかの配備記述子が必要です。アタッチメントを使用する場合、配備記述子で特別に行う必要があることは何もありません。エンドポイント配備記述子からの抜粋を、次に示します。

  <enterprise-beans>
    <session>
      <ejb-name>AttachmentPurchaseOrderServiceBean</ejb-name>
      <service-endpoint>com.sun.j2ee.blueprints.attachmentservice.AttachmentPurchaseOrderServiceSEI</service-endpoint>
      <ejb-class>com.sun.j2ee.blueprints.attachmentservice.AttachmentPurchaseOrderServiceBean</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Container</transaction-type>
   </session>  
  </enterprise-beans>
コード例 6: ejb-jar.xml 配備記述子からの抜粋

ejb-jar.xml 内でサービスエンドポイントインタフェースが <service-endpoint> として定義されています。エンドポイントには、コード例 5 に示すような Web サービス配備記述子ファイルの webservices.xml も必要です。アタッチメントを使用する場合、配備記述子で特別に行う必要があることは何もありません。

  <webservice-description>
    <webservice-description-name>AttachmentPurchaseOrderService</webservice-description-name>
    <wsdl-file>META-INF/wsdl/AttachmentPurchaseOrderService.wsdl</wsdl-file>
    <jaxrpc-mapping-file>META-INF/attachmentpurchaseorderservice-mapping.xml</jaxrpc-mapping-file>
    <port-component>
      <description>port component description</description>
      <port-component-name>AttachmentPurchaseOrderService</port-component-name>
      <wsdl-port xmlns:PurchaseOrderns="urn:AttachmentPurchaseOrderService">PurchaseOrderns:AttachmentPurchaseOrderServiceSEIPort</wsdl-port>
      <service-endpoint-interface>
        com.sun.j2ee.blueprints.attachmentservice.AttachmentPurchaseOrderServiceSEI
      </service-endpoint-interface>
      <service-impl-bean>
        <ejb-link>AttachmentPurchaseOrderServiceBean</ejb-link>
      </service-impl-bean>
    </port-component>
  </webservice-description>
コード例 7: 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.