使用 xsd:any 表示服务接口中的 XML 文档:设计详细信息

本文档以 java.netbpcatalog 项目下的面向文档的应用程序为例,说明了在设计以文档为中心的接口和端点时使用 xsd:any 作为文档类型的策略。此应用程序具有一个服务端点,旨在将 xsd:any 用作文档类型。XML 文档以客户端发送的订单表示。

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

服务的 WSDL 文件

代码示例 1 中的 WSDL 文件描述了 Web 服务。我们选择的开发形式是从 WSDL 开始的,并基于 WSDL 生成必要的 Java[TM] 类。因此,为消息部分在 WSDL 中选择正确的类型是非常重要的,因为 WSDL 文件中的这些类型会在生成的 Java 代码中产生参数类型。请注意,<any/> 类型是为以参数形式发送到 submitPO 方法的文档以及返回值指定的。此外,还请注意在 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 开始的,因此会基于 WSDL 中包含的信息生成代码示例 2 中的服务端点接口。服务端点接口具有一个接收 SubmitPO 对象的 submitPO() 方法。类 SubmitPO 与包含 WSDL 中定义的 xsd:any 的复杂类型相对应,它是一个 JavaBeans[TM] 组件,基本上只是一个包含表示 XML 订单文档的 javax.xml.soap.SOAPElement 的封装类。请注意,响应类型是使用 xsd:any 指定的,因此返回的 XML 文档也具有一个名为 SubmitPOResponse 的 JavaBeans 封装类,该类包含了作为 SOAPELement 的订单 XML 文档。应用程序定义的异常 InvalidPOException 也是从 WSDL 生成的。

public interface AnyPurchaseOrderServiceSEI extends Remote {
    public SubmitPOResponse submitPO(SubmitPO parameters) throws
        InvalidPOException, RemoteException;
}
代码示例 2:服务端点接口

代码示例 3 显示了从 WSDL 生成的 SubmitPO 类。此 JavaBean 封装类包含作为 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:SubmitPO 封装类包含了作为 SOAP 元素的订单 XML 文档,该元素是从 WSDL 生成的

Java 端点实现

对于此应用程序,我们选择使用 Web 组件实现服务接口。代码示例 4 显示了端点实现类。还可以使用 Enterprise JavaBeans[TM] (EJB[TM]) 组件实现端点。两种选择均可。需要特别注意的是,订单 XML 被作为 SOAPElement 处理,并在为代码示例 3 中显示的 SubmoitPO 包装类调用 get 方法后使用。

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();
            //extract the 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);
        }
        //this is done just to illustrate throwing an application specific exception
        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:端点实现

部署描述符

将 Java[TM] 2 Platform, Enterprise Edition(J2EE[TM] 平台)中的 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。Java BluePrints Solutions Catalog 中的所有内容受版权保护,未经 Sun Microsystems 的明确书面许可,不得在其他产品中发布。