Using xsd:any to Represent XML Documents in a Service Interface: Design Details

The strategy for using xsd:any as the document type when designing  a document centric interface and endpoint is illustrated by the document oriented applications available under the bpcatalog project hosted at java.net. This application has a service endpoint designed to use xsd:any as the document type. The XML document is represented by a purchase order sent by the client.

The application consists of these major entities:

The WSDL File for the Service

The WSDL file in Code Example 1 describes the web service. The development style we chose was to start with WSDL and generate the necessary Java[TM] classes from it. So choosing the proper types for the message parts in the WSDL is very important, since these types in the WSDL file will result in the types of the parameters in the generated Java code. Note that  the <any/> type is specified for the document sent as a parameter to the submitPO method as well as for the return value. Also note an application defined service exception declared in the 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>
Code Example 1:  Snippet of the WSDL for the Service

The Service Endpoint Interface

Since we start with the WSDL, the service endpoint interface in Code Example 2 gets generated based on the information contained in the WSDL. The service endpoint interface has a submitPO() method that accepts a SubmitPO object. The class SubmitPO corresponds to the complex type containing  xsd:any defined in the WSDL and is a JavaBeans[TM] component that is basically just a wrapper class containing a javax.xml.soap.SOAPElement representation of the XML purchase order document.  Note that the response type was specified using xsd:any so the XML document returned also has a wrapper JavaBeans class called  SubmitPOResponse containing the purchase order XML document as a SOAPELement. The application-defined exception InvalidPOException is also generated from the WSDL.

public interface AnyPurchaseOrderServiceSEI extends Remote {
    public SubmitPOResponse submitPO(SubmitPO parameters) throws
        InvalidPOException, RemoteException;
}
Code Example 2:  The service endpoint interface

Code Example 3 shows the SubmitPO class that gets generated from the WSDL. This JavaBean wrapper class contains the purchase order XML document as a SOAPElement.

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;
}
}
Code Example 3:  The SubmitPO Wrapper Class Containing the Purchase Order XML Document as a SOAP Element That Is Generated From the WSDL

The Java Endpoint Implementation

For this application we chose to use a web component to implement the service interface.  Code Example 4 shows the endpoint implementation class. We could instead have used an Enterprise JavaBeans[TM] (EJB[TM]) component to implement the endpoint. Either choice would work. An important point to notice is that the purchase order XML is handled as a SOAPElement and is used after calling a get method on the SubmoitPO wrapper class shown in Code Example 3.

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;
    }
}
Code Example 4:  The Endpoint Implementation

The Deployment Descriptors

A web service in Java[TM] 2 Platform, Enterprise Edition (J2EE[TM] platform) is packaged into a deployment module such as a war or an ear file. In this application, we packaged it as a war file. The portable packaging of a web service endpoint requires several deployment descriptors as well as the Java classes. Here are some snippets from the endpoint deployment descriptors:

<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>
Code Example 5: Snippet From web.xml Deployment Descriptor

The endpoint also needs a web services deployment descriptor file, webservices.xml, as shown below:

<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>
Code Example 6: Snippet From webservice.xml Deployment Descriptor

The web services deployment descriptor file contains information about the service such as the names of the WSDL file, the JAX-RPC mapping file, and also the service endpoint interface and the service implementation class names.
© 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.