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

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

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

サービスの WSDL ファイル

WSDL ファイルは Web サービスの記述です。WSDL 内にアプリケーション定義のサービス例外が宣言されていることに注意してください。このサービスの WSDL からの抜粋を次に示します。

<>  <types>
    <schema targetNamespace="urn:StringPurchaseOrderService" xmlns:tns="urn:StringPurchaseOrderService" 
    xmlns:soap11-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://www.w3.org/2001/XMLSchema">
      <complexType name="submitPO">
        <sequence>
          <element name="String_1" type="string" nillable="true"/>
        </sequence>
      </complexType>
      <complexType name="submitPOResponse">
        <sequence>
          <element name="result" type="string" nillable="true"/>
        </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="StringPurchaseOrderServiceSEI_submitPO">
    <part name="parameters" element="tns:submitPO"/>
  </message>
  <message name="StringPurchaseOrderServiceSEI_submitPOResponse">
    <part name="result" element="tns:submitPOResponse"/>
  </message>
  <message name="InvalidPOException">
    <part name="InvalidPOException" element="tns:InvalidPOException"/>
  </message>
  <portType name="StringPurchaseOrderServiceSEI">
    <operation name="submitPO">
      <input message="tns:StringPurchaseOrderServiceSEI_submitPO"/>
      <output message="tns:StringPurchaseOrderServiceSEI_submitPOResponse"/>
      <fault name="InvalidPOException" message="tns:InvalidPOException"/>
    </operation>
  </portType>

コード例 1: サービスの WSDL からの抜粋

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

エンドポイントインタフェースには、XML ドキュメントを文字列型として受け付ける submitPO() メソッドがあります。そのサービスエンドポイントインタフェースを、次に示します。

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

Java[tm] エンドポイント実装

このアプリケーションでは、EJB[tm] (Enterprise JavaBeans[tm]) コンポーネントを使用して、サービスインタフェースを実装しています。代わりに、Web コンポーネントを使用してエンドポイントを実装することもでき、どちらの方法でも問題ありません。getID() メソッドは、単にクライアントに注文書 ID を返すだけであることに注意してください。現実には、クライアントに結果を返す前に行う必要がある仕事がありますが、ここではビジネスロジックに注目しません。また、エンドポイントが最初にそのスキーマとドキュメントを照合することにも注意してください。大切なことは、注文書 XML が文字列型として処理されることです。エンドポイント実装クラスは、次のようになります。

public class StringPurchaseOrderServiceBean implements SessionBean {
   
    private SessionContext sc;
    private DocumentBuilderFactory docBuilderFactory;
   
    public StringPurchaseOrderServiceBean(){}
   
    public String submitPO(String xmlPO) throws InvalidPOException, RemoteException {
        String id =null;
        if (!(validate(xmlPO))) {
            throw new InvalidPOException("Error parsing the purchase order XML document!!!");
        }
        try {
            //ドキュメントから PO ID を抽出し、クライアントに返す
            id = getID(xmlPO);
        } catch (Exception e) {
            throw new EJBException("StringPurchaseOrderService implementation had trouble parsing PO.xml, some system or
            configuration problem " + 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 id;
    }
   
    private String getID(String xmlDoc) throws org.xml.sax.SAXException, javax.xml.parsers.ParserConfigurationException, 
        java.io.IOException {
        String ret = "";
        DocumentBuilder db = null;
        if (docBuilderFactory != null)
            db = docBuilderFactory.newDocumentBuilder();
        InputSource is =  new InputSource(new StringReader(xmlDoc));
        Document doc = db.parse(is);
        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) return child.getNodeValue();
            }
        }
        return ret;
    }
  private boolean validate(String xmlDoc) {
        Document doc = null;
        try {
            DocumentBuilderFactory dbf = null;
            DocumentBuilder db = null;
            try {
                dbf = DocumentBuilderFactory.newInstance();
                dbf.setValidating(true);
                dbf.setNamespaceAware(true);
                dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
                        "http://www.w3.org/2001/XMLSchema");
                if (dbf != null){
                    db = dbf.newDocumentBuilder();
                }
                db.setEntityResolver(new POEntityResolver());
                db.setErrorHandler(new POXMLErrorHandler());
            } catch ( javax.xml.parsers.ParserConfigurationException pce) {
                System.err.println(pce);
            }
            InputSource is =  new InputSource(new StringReader(xmlDoc));
            doc = db.parse(is);
            return true;
        } catch (Exception e) {
            System.err.println("XML Validation Error " + e);
        }
        return false;
    }
   
// ライフサイクルメソッド
    ...
}
コード例 3: エンドポイント実装

配備記述子

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

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

ejb-jar.xml 内でサービスエンドポイントインタフェースが <service-endpoint> として定義されていることに注意してください。このエンドポイントにはまた、次のような Web サービス配備記述子ファイル webservices.xml も必要です。

<webservice-description>
  <webservice-description-name>StringPurchaseOrderService</webservice-description-name>
  <wsdl-file>META-INF/wsdl/StringPurchaseOrderService.wsdl</wsdl-file>
  <jaxrpc-mapping-file>META-INF/stringpurchaseorderservice-mapping.xml</jaxrpc-mapping-file>
  <port-component>
    <description>port component description</description>
    <port-component-name>StringPurchaseOrderService</port-component-name>
    <wsdl-port xmlns:PurchaseOrderns="urn:StringPurchaseOrderService">PurchaseOrderns:StringPurchaseOrderServiceSEIPort</wsdl-port>
    <service-endpoint-interface>
      com.sun.j2ee.blueprints.stringposervice.StringPurchaseOrderServiceSEI
    </service-endpoint-interface>
    <service-impl-bean>
      <ejb-link>StringPurchaseOrderServiceBean</ejb-link>
    </service-impl-bean>
 </port-component>
</webservice-description>
コード例 5: 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.