使用结构定义的类型表示服务接口中的 XML 文档:设计详细信息

本文档以 java.netbpcatalog 项目下的面向文档的应用程序为例,说明了设计以文档为中心的接口和端点时将文档结构用作文档类型的策略。此应用程序具有一个服务端点,该服务端点旨在将 XML 文档用作结构定义的类型。XML 文档以客户端发送的订单表示。此应用程序演示了将订单服务设计为接收订单文档的策略,其中订单的结构是服务接口的一部分。

此应用程序由以下主要实体组成:

服务的 WSDL 文件

WSDL 文件用于对 Web 服务进行描述。我们选择的开发形式是从 WSDL 开始的,基于 WSDL 生成必要的 Java 类。因此,为 WSDL 中的消息部分选择正确的类型是非常重要的,因为这些类型会在生成的 Java 代码中产生参数类型。请注意,订单结构在单独的文件中,它是从 WSDL 中导入的。另请注意在 WSDL 文件中声明的应用程序定义的服务异常。代码示例 1 包含此服务的 WSDL 中的代码片段:

<types>
   <schema targetNamespace="urn:SchemaDefinedPurchaseOrderService" 
   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">
   <xsd:import namespace="http://java.sun.com/blueprints/ns/po" schemaLocation="PurchaseOrder.xsd"/>
   <element name="submitPO">
    <complexType>
       <sequence>
            <element name="inputDoc" type="pons:PurchaseOrder" nillable="true"/>                       
      </sequence>
    </complexType>
   </element>
   <element name="submitPOResponse">
    <complexType>
      <sequence>
            <element name="result" type="string" nillable="true"/>                       
      </sequence>
    </complexType>
   </element>
   <element name="InvalidPOException">
    <complexType>
      <sequence>
        <element name="message" type="string" nillable="true"/>                   
      </sequence>
    </complexType>
   </element>                             
   </schema>
   </types>
  <message name="SchemaDefinedPurchaseOrderServiceSEI_submitPO">
    <part name="parameters" element="tns:submitPO"/>
 </message>
  <message name="SchemaDefinedPurchaseOrderServiceSEI_submitPOResponse">
    <part name="result" element="tns:submitPOResponse"/>
 </message>
  <message name="InvalidPOException">
   <part name="InvalidPOException" element="tns:InvalidPOException"/>
  </message>
  <portType name="SchemaDefinedPurchaseOrderServiceSEI">
    <operation name="submitPO">
      <input message="tns:SchemaDefinedPurchaseOrderServiceSEI_submitPO"/>
      <output message="tns:SchemaDefinedPurchaseOrderServiceSEI_submitPOResponse"/>
      <fault name="InvalidPOException" message="tns:InvalidPOException"/>
    </operation>
  </portType>
代码示例 1:  服务的 WSDL 中的代码片段

现在看一下作为服务接口一部分的订单文档。代码示例 2 显示了订单结构。此文件是通过语句 <xsd:import namespace="http://java.sun.com/blueprints/ns/po" schemaLocation="PurchaseOrder.xsd"/> 导入到代码示例 1 中的 WSDL 文件的
通过导入订单结构,WSDL 文件可以在服务接口中使用此类型来表示交换的文档。

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema targetNamespace="http://java.sun.com/blueprints/ns/po" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://java.sun.com/blueprints/ns/po" elementFormDefault="qualified">
  <xsd:element name="PurchaseOrder" type="PurchaseOrder"/>
    <xsd:complexType name="Address">
        <xsd:sequence>
            <xsd:element name="street" type="xsd:string" nillable="false"/>
            <xsd:element name="city" type="xsd:string" nillable="false"/>
            <xsd:element name="state" type="xsd:string" nillable="false"/>
            <xsd:element name="postalCode" type="xsd:string" nillable="false"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="LineItem">
        <xsd:sequence>
            <xsd:element name="itemId" type="xsd:string" nillable="false"/>
            <xsd:element name="price" type="xsd:float" nillable="false"/>
            <xsd:element name="quantity" type="xsd:int" nillable="false"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="PurchaseOrder">
        <xsd:sequence>
            <xsd:element name="poId" type="xsd:string" nillable="false"/>
            <xsd:element name="createDate" type="xsd:date" nillable="false"/>
            <xsd:element name="shipTo" type="Address" nillable="false"/>
            <xsd:element name="billTo" type="Address" nillable="false"/>
            <xsd:element name="items" type="LineItem" nillable="false" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema>
代码示例 2:  订单结构

服务端点接口

因为此示例应用程序的开发是从 WSDL 开始的,所以服务端点接口会基于 WSDL 中包含的信息来生成。服务端点接口具有 submitPO() 方法,该方法用于接收 PurchaseOrder 对象。此时会生成 PurchaseOrder 类,并与导入到 WSDL 文件中的订单结构相匹配。此外,还从 WSDL 生成了应用程序定义的异常 InvalidPOException

public interface SchemaDefinedPurchaseOrderServiceSEI extends Remote {
    public String submitPO(PurchaseOrder inputDoc) throws
        InvalidPOException, RemoteException;
}

代码示例 3:服务端点接口

Java 端点实现

对于此应用程序,我们选择使用 EJB 组件来实现服务接口。还可以使用 Web 组件来实现端点。两种选择均可。请注意,getPoId() 方法仅将订单 ID 返回至客户端。在实际情况下,将结果返回至客户端之前还需要执行一些操作。此外,为了演示如何抛出特定于应用程序的异常,端点会检查订单 ID 是否为特定的编号,并在满足条件时抛出异常。端点实现类会如下所示:

public class SchemaDefinedPurchaseOrderServiceBean implements SessionBean {  
    private SessionContext sc;  
    public SchemaDefinedPurchaseOrderServiceBean(){}  

    public String submitPO(PurchaseOrder po) throws InvalidPOException, RemoteException {      
        //this is done just to illustrate throwing an application specific exception
        if(po.getPoId().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.");      
        //extract the PO ID and return to the client
        return po.getPoId();
    }  

    //life cycle methods
    public void ejbCreate() throws CreateException {}  
    public void setSessionContext(SessionContext sc) {
        this.sc = sc;
    }  
    public void ejbRemove(){}  
    public void ejbActivate() {}  
    public void ejbPassivate() {}
}
代码示例 4:  端点实现

部署描述符

将 J2EE 中的 Web 服务打包为 war 或 ear 文件之类的部署模块。在此应用程序中,我们将其打包为一个 ear 文件。Web 服务端点的可移植打包需要多个部署描述符以及 Java 类。下面是端点部署描述符中的一些代码片段:

<enterprise-beans>
  <session>
    <ejb-name>SchemaDefinedPurchaseOrderServiceBean</ejb-name>
    <service-endpoint>com.sun.j2ee.blueprints.objectposervice.SchemaDefinedPurchaseOrderServiceSEI</service-endpoint>
    <ejb-class>com.sun.j2ee.blueprints.objectposervice.SchemaDefinedPurchaseOrderServiceBean</ejb-class>
    <session-type>Stateless</session-type>
    <transaction-type>Container</transaction-type>
  </session>
</enterprise-beans>
代码示例 5:ejb-jar.xml 部署描述符中的代码片段

请注意服务端点接口在 ejb-jar.xml 中定义为 <service-endpoint>
该端点还需要一个显示为以下内容的 Web 服务部署描述符文件 webservices.xml:

<webservice-description>   
  <webservice-description-name>SchemaDefinedPurchaseOrderService</webservice-description-name>   
  <wsdl-file>META-INF/wsdl/SchemaDefinedPurchaseOrderService.wsdl</wsdl-file>   
  <jaxrpc-mapping-file>META-INF/schemadefinedpurchaseorderservice-mapping.xml</jaxrpc-mapping-file>
  <port-component>
    <description>port component description</description>     
    <port-component-name>SchemaDefinedPurchaseOrderService</port-component-name>
    <wsdl-port xmlns:PurchaseOrderns="urn:SchemaDefinedPurchaseOrderService">
      PurchaseOrderns:SchemaDefinedPurchaseOrderServiceSEIPort
    </wsdl-port>
    <service-endpoint-interface>     
      com.sun.j2ee.blueprints.objectposervice.SchemaDefinedPurchaseOrderServiceSEI
    </service-endpoint-interface>
    <service-impl-bean>     
      <ejb-link>SchemaDefinedPurchaseOrderServiceBean</ejb-link>
    </service-impl-bean>
  </port-component>
</webservice-description>
代码示例 6:webservice.xml 部署描述符中的代码片段

Web 服务部署描述符文件包含有关服务的信息,例如 WSDL 文件的名称、JAX-RPC 映射文件的名称以及服务端点接口和服务实现类的名称。
© Sun Microsystems 2005。Java BluePrints Solutions Catalog 中的所有内容受版权保护,未经 Sun Microsystems 的明确书面许可,不得在其他产品中发布。