Sun Java Solaris Communities My SDN Account Join SDN
 
Article

Patterns and Strategies for Building Document-Based Web Services

 
Using XML in the SOAP Body

[Page 1] [Page 2] [Page 3] [Page 4] [Page 5] [Page 6]

In this strategy, the web service is deployed with document-literal formatting and the XML document that needs to be exchanged is passed in the body of the SOAP message.

Example: Start with the WSDL and XML Schema

This top-down approach revolves around consuming a WSDL. Nailing down the WSDL that will describe the service is quite often the first step in the development lifecycle. Doing so establishes the publicly exposed contract that the service will adhere to. With the WSDL in hand, tools can be used to generate the service implementation. This approach is also useful when developing a service that must adhere to an existing or externally developed WSDL.

Best Practices for WSDL Design

WSDL provides the grammar to describe the details of the web service’s publicly-exposed interface, such as how it should be invoked, and supplies some prequisite information for the consumer to use in the service invocation. Minimally, the consumer will need to know the signature of the service (what goes in and what comes out), the wire protocol to be used to send the invocation message, and the location of the service. A WSDL document is an XML document-based on the schema defined in the WSDL specifications. The information contained in a WSDL document can be organized it into two logical sections, the Abstract Descriptions and Concrete Descriptions respectively. This is also shown in Figure 4.

 
Figure 4: Abstract and Concrete Elements in WSDL
Figure 4: Abstract and Concrete Elements in WSDL
Abstract Description

Interaction between two objects can be characterized as a series of message exchanges: The object being invoked accepts the incoming message, may return an outgoing message or may throw an exception message. Each type of message can be described further by listing the data-types and order of its parameters. When the object has multiple methods, it is possible that some methods exchange the same messages (two methods could have the same return value, for example, the same "output" message) and that some data types are common across messages. In order to represent all this information about the object in a normalized form, one would:

  1. Describe all the data types used in all messages
  2. List all messages that can be exchanged and represent the message as a set of data types.
  3. Describe each method (interaction with the object) as a collection of input, output and exception type messages.

The description of what the object does could then be described as a collection of possible interactions.

The points outlined above can be thought of as abstract descriptions. For a web service, these descriptions would need to be captured in a platform- and language-independent manner. This helps define a set of services that a diverse set of consumers can use. In WSDL, the abstract descriptions can be thought of as four significant elements in the XML:

  1. types: Contains the platform- and language-independent data type definitions.
  2. messages: The message elements contain input and output parameters for the service, and are used to describe different messages that the service exchanges.
  3. operations: The operation element represents a particular interaction with the service and is used to describe the input, output, and exception messages that are possible during that interaction
  4. portTypes: Uses the messages section to describe function signatures (operation name, input and output parameters). It represents a set of operations supported by the service.

Concrete Descriptions

Each web service or "end point" runs on a network address. The web service also understands a particular protocol, such as, the messages and data that are sent to the web service must be sent in a particular format that the web service understands. All these aspects of the service description are specific to the implementation of the service and are thus logically grouped into one category. In short, the concrete descriptions define the implementation-specific descriptions for the web service. There are three significant elements in the XML which fall in this category:

  1. bindings: Specifies binding of each operation in the portTypes section.
    It associates the abstract descriptions of a portType (for example, a portType’s operations, messages and data types) with a protocol
  2. services: In addition to protocol-specific information, the WSDL document should also describe where the service is deployed. The associationbetween a binding and the network address at which it can be found is defined by a port. The service element specifies a port that describes a network location for a binding.

When designing WSDL documents, it is good practice to separate out the abstract descriptions, concrete descriptions, and the XML schemas into individual files and aggregate them using import statements. The logical separation of abstract information (like methods, parameters, and error messages) from information that changes with the implementation type (like transport protocols) allows the reuse of abstract definitions of the service across different implementations of the service. Also, the XML schemas can be used independently of the WSDL by other tools and applications without having to parse the WSDL file.

As an example, the same service may be exposed over the HTTP transport, as well as the SMTP/POP transports. In both cases, the service does the same function, so the abstract description of the service and its methods can be reused and only the concrete, implementation-specific information needs to be changed across the two instances of the service.

 
Figure 5: WSDL Aggregation
Figure 5: WSDL Aggregation

Code Sample 7: Abstract WSDL for the Document-Literal Example

<definitions xmlns:tns="http://www.examples.com/wsdl/poservice" 
xmlns="http://schemas.xmlsoap.org/wsdl/" 
xmlns:ns1="http://www.examples.com/types" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
targetnamespace="http://www.examples.com/wsdl/poservice" name="POService">
    <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="http://www.examples.com/types">
            <import schemalocation="PurchaseOrder.xsd"
                    namespace="http://www.examples.com/types" id="ns1"/>
            <import schemalocation="PurchaseOrderStatus.xsd"  
                    namespace="http://www.examples.com/types" id="ns1"/>
            <import schemalocation="POProcessingProblem.xsd" 
                    namespace="http://www.examples.com/types" id="ns1"/>
        </schema>
    </types>
    <message name="IPurchaseOrder_acceptPO">
        <part name="parameters" element="ns1:PurchaseOrderDocument"/>

    </message>
    <message name="IPurchaseOrder_acceptPOResponse">
        <part name="result" element="ns1:Status"/>
    </message>
    <message name="POProcessingProblem">
        <part name="POProcessingProblem" element="ns1:POProcessingFault"/>
    </message>
    <porttype name="IPurchaseOrder">
        <operation name="acceptPO">
            <input message="tns:IPurchaseOrder_acceptPO"/>
            <output message="tns:IPurchaseOrder_acceptPOResponse"/>
            <fault name="POProcessingProblem" message="tns:POProcessingProblem"/>
        </operation>
    </porttype>
    </definitions>

Code Sample 8: Concrete WSDL for the Document-Literal Example

<definitions xmlns:tns="http://www.examples.com/wsdl/poservice" 
xmlns="http://schemas.xmlsoap.org/wsdl/" 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
targetnamespace="http://www.examples.com/wsdl/poservice" name="POService">
	<import namespace="http://www.examples.com/wsdl/poservice" 
             location="Abstract.wsdl"/>
	<binding name="IPurchaseOrderBinding" type="tns:IPurchaseOrder">
		<soap:binding style="document" 
                         transport="http://schemas.xmlsoap.org/soap/http"/>
		<operation name="acceptPO">
			<soap:operation/>
			<input>
				<soap:body use="literal"/>
			</input>

			<output>
				<soap:body use="literal"/>
			</output>
			<fault name="POProcessingProblem">
				<soap:fault name="POProcessingProblem" use="literal"/>
			</fault>
		</operation>
	</binding>
	<service name="POService">
	   <port name="IPurchaseOrderPort" binding="tns:IPurchaseOrderBinding">
		<soap:address location="http://127.0.0.1:8080/docliteralfromjava/jaxrpc"/>
	   </port>
	</service>
</definitions>

Once the WSDL is available, the service endpoint can be developed to implement the WSDL as a JAX-RPC web service using the wscompile tool. Code Sample 9 shows the service endpoint interface, and the service implementations are listed in Code Samples 10 and 11.

Code Sample 9: Service Endpoint Interface

// This class was generated by the JAXRPC SI, do not edit.
// Contents subject to change without notice.
// JAX-RPC Standard Implementation (1.1_03, build R65)

package com.examples.docliteral;

public interface IPurchaseOrder extends java.rmi.Remote {
    public com.examples.docliteral.PurchaseOrderStatus
	    acceptPO(com.examples.docliteral.PurchaseOrder parameters) throws
            com.examples.docliteral.POProcessingProblem,  java.rmi.RemoteException;
}

Code Sample 10: Generated Implementation Adapter Class

package com.examples.docliteral;

public class IPurchaseOrder_Impl implements com.examples.docliteral.IPurchaseOrder, 
        java.rmi.Remote {
    public com.examples.docliteral.PurchaseOrderStatus
	    acceptPO(com.examples.docliteral.PurchaseOrder parameters) throws 
            com.examples.docliteral.POProcessingProblem,  java.rmi.RemoteException {
        com.examples.docliteral.PurchaseOrderStatus _retVal = null;
        return _retVal;
    }
}

IPurchaseOrder is the generated service endpoint interface, PurchaseOrder, Address, and LineItem are the corresponding value types used within the interface, and PurchaseOrder_Impl is a template implementation class which is used as the base class for the service endpoint implementation class which is shown in Code Sample 11.

Code Sample 11: Service Implementation

package com.examples.docliteral;

import java.rmi.RemoteException;
import java.util.Date;

public class PurchaseOrderService extends IPurchaseOrder_Impl {

    public PurchaseOrderStatus acceptPO(PurchaseOrder order) throws 
                                              POProcessingProblem, RemoteException {
     if (order == null) {
       throw new POProcessingProblem("Web service was passed a null Purchase order");
        } else if (order.getItems() == null ||
                order.getPoID() == null ||
                order.getBillTo() == null) {
            throw new POProcessingProblem("Purchase order cannot have null fields");
        }
	System.out.println("PurchaseOrder received in the Web service");
	System.out.println("Order ID " +order.getPoID());
	System.out.println("Order creation date "+order.getCreateDate());
	System.out.println("Ship To Address " +order.getShipTo());
	System.out.println("Bill To Address " +order.getBillTo());
	System.out.println("Order Contents :");
     LineItem[] items=order.getItems();
     for(int i=0;i<items.length;i++)
        System.out.println(items[i]);
	PurchaseOrderStatus status= new PurchaseOrderStatus();
	status.setTimestamp( new Date().toString());
	status.setOrderid("ABC"+System.currentTimeMillis());
     return status ;
    }
}

The client for the web service can also be generated from the WSDL. Note that in order to parse the WSDL effectively, the client needs to have access to the XSD schemas that are referenced in the WSDL. It is for this purpose that they are packaged with the WAR file during the deployment (see the Ant target in Code Sample 12).

Code Sample 12: Included Schemas are Packaged in the WAR

<!-- Create the portable WAR FILE. This is the standard J2EE WAR file-->
  <target name="create-war" depends="generate-server-from-wsdl,compile-server">

    <war warfile="${buildhome}/${appname}/jaxrpc-${appname}-raw.war"
         webxml="${webapp.webxml}">
	<!-- Include the schema's and abstract WSDL file for the Purcahseorder 
	and status so that the client has access to them -->
	 <fileset dir="${basedir}/configs/">
		  <include name="**/*.xsd"/>
		  <include name="Abstract.wsdl"/>
	</fileset>
	<webinf dir="${basedir}/configs/" includes="*.wsdl,jaxrpc-ri.xml"/>
        <webinf dir="${buildhome}/${appname}/" includes="model.gz"/>
        <webinf dir="${basedir}/configs/"
		    includes="${webapp.jaxrpc.file}" defaultexcludes="no"/>

        <classes dir="${buildhome}/${appname}/classes/server" 
		    includes="**/*.class" defaultexcludes="no"/>
    </war>
  </target>

The client code, shown in Code Sample 13, creates a purchase order and populates it, invokes the service and obtains the reply. The generated stub actually checks the data being passed and validates it against the schema. For example, many elements in the schema (Code Sample 4) are marked as nillable="false". If any of these elements are not populated, the client will get an exception (a client side fault) before sending the message as shown in Code Sample 14.

Code Sample 13: Document-Literal Client

import com.examples.docliteral.clientbindings.*;

import java.util.Calendar;
import java.math.BigDecimal;


public class WSDLClient {

    public static void main(String[] args) throws Exception {
        String url = "http://localhost:9090/docliteralfromwsdl/jaxrpc";
        if (args.length == 1) {
            url = args[0];
        }
        POService_Impl serviceproxy = new POService_Impl();
        IPurchaseOrder_Stub stub = (IPurchaseOrder_Stub) 
		    (serviceproxy.getIPurchaseOrderPort());
        stub._setProperty(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY, url);
        PurchaseOrderStatus result= sendPurchaseOrder(stub);
        System.out.println("Order id is : " + result.getOrderid());
        System.out.println("Timestamp is : " + result.getTimestamp());
    }


    /**
     * Sends a purchaseorder to the service
     *
     * @param stub
     * @throws java.rmi.RemoteException
     */
    private static PurchaseOrderStatus sendPurchaseOrder(IPurchaseOrder_Stub stub) 
	    throws java.rmi.RemoteException {
        PurchaseOrderStatus result=null;
		try {
 	Address addrs = new Address("1 Main Street", "Beverly Hills", "CA", "90210");
			LineItem items[] = new LineItem[]{
				new LineItem("Copier Paper", new BigDecimal(10.00), 2),
				new LineItem("Toner", new BigDecimal(920.00), 1)};

			PurchaseOrder order = new PurchaseOrder();
			order.setCreateDate(Calendar.getInstance());
			order.setBillTo(addrs);
			order.setShipTo(addrs);
			order.setItems(items);
			order.setPoID("ABC-CO-19282");
			result = stub.acceptPO(order);
	        } catch (POProcessingProblem e1) {
            System.out.println("Problem processing PO on the Web service : " + e1);
		    }
			return result;
    }


}

Code Sample 14: Client Side Exception When Required Elements are Null

run-wsdl-client:
     [echo] Running the Client program....
     [java] java.rmi.RemoteException: unexpected null value for literal 
	     data; nested exception is:
     [java]     unexpected null value for literal data
     [java]     at
         com.examples.docliteral.clientbindings.IPurchaseOrder_Stub.acceptPO(
		     IPurchaseOrder_Stub.java:81)
     [java]     at WSDLClient.sendPurchaseOrder(Unknown Source)
     [java]     at WSDLClient.main(Unknown Source)

Code Samples 15 and 16 show the SOAP request and response sent over the wire for the successful invocation of the preceding example in a document-literal formatting.

Code Sample 15: Generated SOAP Request

<?xml version="1.0" encoding="UTF-8"?>
<env:envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:ns0="http://www.examples.com/types">
	<env:body>
		<ns0:purchaseorderdocument>
			<billto>
				<street>1 Main Street</street>
				<city>Beverly Hills</city>

				<state>CA</state>
				<zipcode>90210</zipcode>
			</billto>
			<createdate>2004-03-27T12:21:02.055-05:00</createdate>
			<items>
				<itemname>Copier Paper</itemname>
				<price>10</price>

				<quantity>2</quantity>
			</items>
			<items>
				<itemname>Toner</itemname>
				<price>920</price>
				<quantity>1</quantity>
			</items>
			<poid>ABC-CO-19282</poid>
			<shipto>
				<street>1 Main Street</street>
				<city>Beverly Hills</city>
				<state>CA</state>
				<zipcode>90210</zipcode>
			</shipto>
		</ns0:purchaseorderdocument>
	</env:body>
</env:envelope>

Code Sample 16: Generated SOAP Response

<?xml version="1.0" encoding="UTF-8"?>
<env:envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:ns0="http://www.examples.com/types">
	<env:body>
		<ns0:status>
			<orderid>ABC1080408062475</orderid>
			<timestamp>Sat Mar 27 12:21:02 EST 2004</timestamp>
		</ns0:status>
	</env:body>
</env:envelope>

The wscompile tool contains a switch that enables the unwrapping of literal elements in the document-literal style. This is an option that specifies the code-level mechanism for binding between SOAP messages and methods. This means that in the endpoint interface, instead of the generating a method signature that accepts the Java Bean corresponding to the parent complex type, it will unwrap the parent element and generate a method signature that accepts as parameters Java data types corresponding to the individual elements inside the parent element. Code Sample 17 shows the ant target for with the unwrap option enabled, and Code Sample 18 shows the corresponding service endpoint interface. Note how this does not accept a PurchaseOrder as an argument, but accepts the data types corresponding to the contents of the PurchaseOrder. Note also that this does not affect the WSDL, or how the message appears on the wire.

Code Sample 17: Ant Target With No Wrapping

  <!-- Generate the client stubs code from the WSDL -->
  <target name="generate-client-from-wsdl" depends="init"
	description="Runs wscompile to generate the client stub classes">
      <echo message="Running wscompile...."/>
    <exec executable="${wscompile}">
	<arg line="-f:wsi"/>
		<arg line="-f:unwrap"/>
       <arg line="-gen:client"/>
       <arg line="-d ${buildhome}/${appname}/classes/client"/>
       <arg line="${config.wsdl.client}"/>
       <arg line="-keep"/> 
    </exec>
  </target>

Code Sample 18: Generated Endpoint Interface With no Wrapping

// This class was generated by the JAXRPC SI, do not edit.
// Contents subject to change without notice.
// JAX-RPC Standard Implementation (1.1_03, build R65)

package com.examples.docliteral.clientbindings;

public interface IPurchaseOrder extends java.rmi.Remote {
    public com.examples.docliteral.clientbindings.PurchaseOrderStatus     
                     acceptPO(com.examples.docliteral.clientbindings.Address billTo, 
                             java.util.Calendar createDate, 
                             com.examples.docliteral.clientbindings.LineItem[] items, 
                             java.lang.String poID, 
                             com.examples.docliteral.clientbindings.Address shipTo) 
        throws java.rmi.RemoteException;
}

Example: Start with Java Interfaces generate WSDL, Schema

In this bottom-up approach, existing code containing business logic or process flows are exposed as web services, which could take the form of writing wrapper classes around existing Enterprise JavaBean (EJB) components or even exposing the EJB directly. In short, the bottom-up approach is one of surfacing existing code using the web service interface. The development of such a service starts with defining the data types and service endpoint interface. For example, to realize the service in Figure 3, developers will define JavaBean components that wrap the PurchaseOrder, LineItem, and Address, and then develop the service endpoint interface that uses these data wrappers in an operation. Figure 6 shows the corresponding class diagram.

 
Figure 6: Top Down Approach
Figure 6: Top Down Approach

Code Sample 19a shows the code for the PurchaseOrder JavaBean class and Code Sample 19b shows the corresponding JAX-RPC service endpoint interface. With these classes available, the corresponding server side artifacts like the WSDL can be automatically generated using the tools like wscompile and it’s –define switch (more details and step by step procedure can be found in Understanding your JAX-RPC SI Environment).

Code Sample 19-a: Developer-Written PurchaseOrder JavaBean

package com.examples.docliteral;


import java.util.Calendar;

public class PurchaseOrder {
    private String poID;
    private Calendar createDate;
    private Address shipTo;
    private Address billTo;
    private LineItem[] items;

    public PurchaseOrder() {
    }
    public PurchaseOrder(String id, Calendar createDate, Address shipTo,
                         Address billTo, LineItem[] items) {
        this.poID = id;
        this.createDate = createDate;
        this.shipTo = shipTo;
        this.billTo = billTo;
        this.items = items;
    }
    public String getPoID() {
        return poID;
    }
    public void setPoID(String value) {
        poID = value;
    }
    public Calendar getCreateDate() {
        return createDate;
    }
    public void setCreateDate(Calendar value) {
        createDate = value;
    }
    public Address getShipTo() {
        return shipTo;
    }
    public void setShipTo(Address value) {
        shipTo = value;
    }
    public Address getBillTo() {
        return billTo;
    }
    public void setBillTo(Address value) {
        billTo = value;
    }
    public LineItem[] getItems() {
        return items;
    }
    public void setItems(LineItem[] value) {
        items = value;
    }
}

Code Sample 19-b: Developer-Written Service Endpoint Interface

public interface IPurchaseOrder extends Remote {
    public PurchaseOrderStatus acceptPO(PurchaseOrder order) 
         throws POProcessingProblem, RemoteException;
}

Comparison with RPC-Literal Formatting

The preceding example can be modified and redeployed as an RPC-literal formatting. The purpose of discussing this variation is to clarify the earlier discussion and demonstrate the orthogonal relationship between the formatting of the SOAP message on the wire and the architectural paradigm used. The changes to the WSDL are highlighted in bold in Code Sample 20. The rest of the example code (including the client) remains unchanged and can be executed as is. The build tree can be found in the <RPC-Literal-From-WSDL> directory.

Code Sample 20: WSDL for the RPC-Literal Example

<definitions xmlns:tns="http://www.examples.com/wsdl/poservice" 
xmlns="http://schemas.xmlsoap.org/wsdl/" 
xmlns:ns2="http://www.examples.com/types" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
targetNamespace="http://www.examples.com/wsdl/poservice" name="POService">
	<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="http://www.examples.com/types" 
		xmlns:ns1="http://www.examples.com/types">
   <import schemaLocation="PurchaseOrder.xsd"  
           namespace="http://www.examples.com/types"/>
<import schemaLocation="PurchaseOrderStatus.xsd" 
            namespace="http://www.examples.com/types"/>
		</schema>
	</types>
	<message name="IPurchaseOrder_acceptPO">

		<part name="PurchaseOrder" type="ns2:PurchaseOrder"/>
	</message>
	<message name="IPurchaseOrder_acceptPOResponse">
		<part name="PurchaseOrderStatus" type="ns2:PurchaseOrderStatus"/>
	</message>
	<portType name="IPurchaseOrder">

		<operation name="acceptPO" parameterOrder="PurchaseOrder">
			<input message="tns:IPurchaseOrder_acceptPO"/>
			<output message="tns:IPurchaseOrder_acceptPOResponse"/>
		</operation>
	</portType>
	<binding name="IPurchaseOrderBinding" type="tns:IPurchaseOrder">

		<soap:binding style="rpc" 
                        transport="http://schemas.xmlsoap.org/soap/http"/>
	 <operation name="acceptPO">
	  <soap:operation/>
	  <input>
	   <soap:body use="literal" namespace="http://www.examples.com/wsdl/poservice"/>
	  </input>
	  <output>
	   <soap:body use="literal" namespace="http://www.examples.com/wsdl/poservice"/>
	  </output>
		</operation>
	</binding>
	<service name="POService">
		<port name="IPurchaseOrderPort" binding="tns:IPurchaseOrderBinding">
		<soap:address location="http://127.0.0.1:8080/rpcliteralfromwsdl/jaxrpc"/>
		</port>
	</service>
</definitions>

The corresponding SOAP request and response generated by the client for this RPC-literal formatted WSDL is shown in Code Sample 21 and Code Sample 22, respectively. Inspecting the WSDL and the SOAP messages, it should be clear that there is no definition for any schema with a root node corresponding to acceptPO. Further, this element is in the namespace of the WSDL. Since the SOAP message follows the RPC convention, the <ns0:acceptPO> element is defined to match the name of the operation in the portType, and a child element is created to match the message part and the parameterOrders attribute. This should help clarify why validation against document schemas for SOAP requests with RPC-literal formatting is difficult. Such validation can only be performed effectively in the SOAP endpoint that has intimate knowledge of the RPC conventions, whereas in a document-literal formatting, validation can be offloaded to intermediaries.

Code Sample 21: SOAP Request for RPC-Literal Formatting

<?xml version="1.0" encoding="UTF-8"?>
<env:envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:ns0="http://www.examples.com/wsdl/poservice">
	<env:body>
		<ns0:acceptpo>
			<purchaseorder>
				<billto>
					<street>1 Main Street</street>
					<city>Beverly Hills</city>
					<state>CA</state>
					<zipcode>90210</zipcode>
				</billto>
				<createdate>2004-03-25T23:40:19.576-05:00</createdate>
				<items>
					<itemname>Copier Paper</itemname>
					<price>10</price>
					<quantity>2</quantity>
				</items>
				<items>
					<itemname>Toner</itemname>
					<price>920</price>
					<quantity>1</quantity>
				</items>
				<poid>ABC-CO-19282</poid>
				<shipto>
					<street>1 Main Street</street>
					<city>Beverly Hills</city>
					<state>CA</state>
					<zipcode>90210</zipcode>
				</shipto>
			</purchaseorder>
		</ns0:acceptpo>
	</env:body>
</env:envelope> 

Code Sample 22: SOAP Response for the RPC-Literal Formatting

<?xml version="1.0" encoding="UTF-8"?>
<env:envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:ns0="http://www.examples.com/wsdl/poservice">
	<env:body>
		<ns0:acceptporesponse>
			<purchaseorderstatus>
				<orderid>ABC1080276021379</orderid>
				<timestamp>Thu Mar 25 23:40:21 EST 2004</timestamp>
			</purchaseorderstatus>
		</ns0:acceptporesponse>
	</env:body>

</env:envelope>

Consequences

Pros
  • Interoperability
  • Validate against schema if XML docs are used
  • Better performance than if RPC-encoded
Cons
  • The endpoint receives the Java representation of the XML document, not the XML structure. In cases where integration with third party systems or XML processing tools is required, the document must be reconstructed.

[Page 1] [Page 2] [Page 3] [Page 4] [Page 5] [Page 6]