Sun Java Solaris Communities My SDN Account Join SDN
 
Article

Patterns and Strategies for Building Document-Based Web Services

 
Architectures for Asynchronous Processing

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

Document-oriented interaction between the service provider and service consumer is typical to asynchronous processing architectures. This is orthogonal to the formatting choice for the message. In order to build architectures around asynchronous processing and document-based communication using JAX-RPC, developers need do more than just use an appropriate formatting. The next sections detail some of the possible architectures along with sample code and references.

Asynchronous Processing with JAX-RPC

Figure 10 represents the block diagram for how a service can be built to process XML documents asynchronously with the JAX-RPC API.

 
Figure 10: Asynchronous services with JAX-RPC
Figure 10: Asynchronous services with JAX-RPC
  1. A business document like a purchase order or invoice in XML format is sent as the SOAP message in the request. The document packaging and service implementation can use any of the strategies outlined earlier.
  2. The service accepts the document and
    1. Does not return any message to the client. This corresponds to a void return type in the service endpoint interface. If due to HTTP issues the client could not receive a successful HTTP 200 message or receives a SOAP Fault, then it is up to the client to retry the invocation or query the service. This retry logic would need to be built into the application layer.
    2. Sends a SOAP message back to the client. The contents of the message are dictated by the schema in the WSDL. (for example, the PurchaseOrderStatus.xsd in Code Sample 4). The message would typically contain an acknowledgement, informing the client that the request is being processed.
  3. Once the service receives the message it is placed on a JMS queue for processing at a later time.
  4. The Message Driven Beans deployed in the container actively receive and process the message containing the XML business document from the queue.
  5. The response to the business processing, is also placed on another JMS Queue for dispatch to the client at a later time.
  6. Other Message Driven Beans can pick up the responses use the JAX-RPC API to make client calls to the callback services on the service consumer’s side. The responses to the business could be another XML document (for example, PurchaseOrderStatus.xsd in Code Sample 5).
Callback Strategies

Asynchronous processing requires some mechanism for the service consumer (that is, the initiator of the initial request/response) to convey the callback endpoint to the provider (that is, the recipient of the initial request/response exchange) so that a meaningful business reply may be received when the processing is finished.

When the client deploys a service on its side which exposes a callback interface, there has to be an out-of-band negotiation regarding the location, details and message correlation semantics between the different messages. The service provider and service consumer (client) have to negotiate the QoS requirements regarding the mechanics of the callback out of band for example as a part of the SLA.

From an implementation perspective, the callback URI can be passed using the following strategies:

  • URI or WSDL location is passed as a part of the initial invocation at the application layer. For example, the WSDL can be designed so that the client has to supply two additional messages, the callback URI and the message identified (message-id), as arguments to the necessary operations. This allows the service to know where the response messages can be sent at a later time and build a correlation between the messages.
  • The client and the web service provider can negotiate the callback URI externally, possibly as a part of setting up the service level agreement (SLA)
  • Callback URI can be included as custom SOAP headers along with the messages. A scheme like WS-Addressing can be used to describe the details regarding the location of the callback. This may be the case if the business process has been described using BPEL. This strategy allows the callback address to be specified as a part of the SOAP envelope using a mutually agreed upon header description between the client and the service provider. The client still needs to provide a callback services, however additionally in this case, it needs to be capable of understanding and processing the WS-Addressing related headers
Message Correlation Strategies

In a web services exchange, a mechanism needs to be established to correlate the messages that are exchanged between the web service and its consumer. In synchronous web services, this correlation is usually built by piggybacking the response to a message on the underlying transport. For example, the client sends a SOAP message over an HTTP Post and receives its corresponding SOAP reply over the underlying HTTP response. Due to the delayed or long-lived processing, services may need to send messages asynchronously. The asynchronous message exchange between two web services uses a pair of synchronous request-response message exchanges piggybacking on a protocol like HTTP, and this requires some mechanism for correlating an originating request/response with its corresponding generated request/response.

In asynchronous communications, since the messages are exchanged over potentially different underlying transport level request-response exchanges, both parties needs to agree on a common mechanism for correlating a final request/response with its corresponding initial request/response.

 
Figure 11: Message Correlation Between a Request and Response
Figure 11: Message Correlation Between a Request and Response

Figure 11 shows an example. The client sends an initial request (1) and gets it corresponding acknowledgement in reply immediately over the underlying HTTP reply. It thus knows that how the two are related. However, since the business level reply message (3) may be returned at a later time, both parties need to know how message (1) and (3) relate. They also need to agree on the mechanism of how the callback endpoint is conveyed to the service provider. There are essentially two strategies by which this correlation can be established:

  • Either an identifier like a message-id can be created and passed as a part of the initial business request, for example, the schema for a purchase order business document can contain a required field like a purchase-order-id that uniquely identifies the request. The Adventure Builder application uses this strategy (see section 8.2.4).
  • The unique message identifier can be passed external to the payload a part of the SOAP message envelope though the use of SOAP level headers. The WS-I Sample application uses this strategy (see section 8.2.5).

In both cases a unique scheme that distinguishes the purchase orders across clients needs to be devised and agreed upon, possibly as a part of the SLA between the parties. The parties also need to agree upon who generates and maintains these identifiers. For example, does the web service client create the identifier when invoking a request or does it use one from a pre-assigned pool of identifiers?

Consequences

Pros
  • Simple to implement
  • Can be built with J2EE on both sides
  • The MDBs and JMS can be used with transitionally to maintain referential integrity
Cons
  • Requires that developers understand the details regarding the correlation, and develop custom techniques for them.
  • Even though the processing is asynchronous and can be made reliable by using persistent Topics and Queues in JMS, the actual message exchange is still unreliable. There are no guaranteed delivery, one-only-once or duplicate elimination semantics associated with the SOAP message exchange.
  • Custom persistence mechanisms and additional vendor products may be required. Many application server vendors include additional licensing costs for using JMS providers
Sample Architecture: Adventure Builder

The Java Adventure Builder is a sample application from the Java Blueprints Program at Sun Microsystems. It is accompanied with full source code and documentation and illustrates the typical design decisions and tradeoffs a developer makes when building enterprise applications. The application consists of two parts, a web site which provides customers with a catalog of adventure packages, accommodations, and transportation options, and an order processing center module that interacts with all the backend supplier companies.

The web services architecture for this application uses the strategy outlined earlier. Of interest is that the order center is exposed as a web service, and the website application acts as the web service client. Once the customers complete the workflow on the web site, the purchase order is sent for processing to the order module, which in turn interacts with other business partners using web services as shown in Figure 12.

 
Figure 12: Adventure Builder Work Flow
Figure 12: Adventure Builder Work Flow

Code Sample 64 shows the relevant code from the action part of the web framework. The source extract from CheckoutHTMLAction.java shows how the website packages the data in a PurchaseOrder object and invokes the PurchaseOrder web service using JAX-RPC. The service returns an orderId as the correlation-id to the client (the website), which is eventually passed on to the user. The user can track the status of the order in the system using this orderId and another web service provides the tracking functionality in the order module. The orderId is returned over the same HTTP connection synchronously to the client, whereas the order is processed asynchronously in the background.

Code Sample 64: Code Extract from Adventure Builder Website Source

       //  create a new po
        PurchaseOrder mypo = new PurchaseOrder();
        String poId = "AB-" +userId + "-" + System.currentTimeMillis();
        mypo.setPoId(poId);
        mypo.setUserId(userId);
        mypo.setEmailId(shippingInfo.getEmail());
        mypo.setLocale("US");
        mypo.setOrderDate(Calendar.getInstance());
        mypo.setShippingInfo(shippingInfo);
        mypo.setBillingInfo(billingInfo);
        mypo.setTotalPrice((new Double(totalPrice)).floatValue());
        mypo.setCreditCard(card);
        mypo.setHeadCount(cart.getHeadCount());
        mypo.setStartDate(Calendar.getInstance());
        mypo.setEndDate(Calendar.getInstance());
        mypo.setDepartureCity(cart.getOrigin());
        mypo.setActivities(myPoActivities);
        mypo.setLodging(lodgingPO);
        if (dF != null) mypo.setDepartureFlightInfo(dF);
        if (rF != null) mypo.setReturnFlightInfo(rF);

        Context ic = new InitialContext();
        Service opcPurchaseOrderSvc =
          (Service) ic.lookup("java:comp/env/service/OpcPurchaseOrderService");
        PurchaseOrderIntf port =
            (PurchaseOrderIntf)opcPurchaseOrderSvc.getPort(PurchaseOrderIntf.class);
  String server = (request.getServerPort() != 0) ?
      (request.getServerName()+":"+request.getServerPort()) :
    (request.getServerName());
        ((Stub)port)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY,
          "http://" + server + "/webservice/PoEndpointBean");
        String ret = port.submitPurchaseOrder(mypo);
        CheckoutBean checkoutBean = new CheckoutBean(ret);
        request.setAttribute(AdventureKeys.CHECKOUT_BEAN, checkoutBean)

 
Figure 13: Sequence Diagram for the Website and the OPC
Figure 13: Sequence Diagram for the Website and the OPC

The endpoint interface and implementation for the PurchaseOrder web service are shown in Code Samples 65 and 66, respectively. The service is implemented as a stateless EJB that validates the incoming data, and places the order on a JMS Queue. Figure 14 shows the sequence diagram for this interaction.

Code Sample 65: Endpoint Interface for the Adventure Builder PurchaseOrder Web Service

public interface PurchaseOrderIntf extends Remote {
    public String submitPurchaseOrder(PurchaseOrder poObject)
           throws InvalidPOException, ProcessingException, RemoteException;
}

Code Sample 66: Code Extract for the Implementation of the Adventure Builder PurchaseOrder Web Service

public class PoEndpointBean implements SessionBean {

/**
     * Accept a purchase order, place the order in a JMS queue and return the 
     * order id so that the caller can have a correlation id for the order
     */
    public String submitPurchaseOrder(PurchaseOrder po)
        throws InvalidPOException, ProcessingException, RemoteException { 
        //validate PO, make sure all required info is provided.
        if (po == null) {
           throw new InvalidPOException("The Purchase Order received was empty!");
        } else if ( po.getUserId()       == null || 
                    po.getEmailId()      == null || 
                    po.getLocale()       == null || 
                    po.getOrderDate()    == null ||
                    po.getShippingInfo() == null ||
                    po.getBillingInfo()  == null ||
                    po.getTotalPrice()   == 0    ||
                    po.getCreditCard()   == null ||
                    po.getHeadCount()    == 0    ||
                    po.getStartDate()    == null ||
                    po.getEndDate()      == null ||
                    po.getDepartureCity()== null  ) {
         throw new InvalidPOException("No field in the purchase order can be null!");
        }
  if(JMSUtils.sendMessage(JNDINames.WORKFLOW_MGR_MDB_QUEUE, 
        JNDINames.DOC_TYPE, JNDINames.PO_DOCUMENT, 
        (Object)po) == false)
      throw new ProcessingException("Irrecoverable error while submitting the order  
                                     for processing");
        return po.getPoId();
    }

//Other EJB methods
}

 
Figure 14: Sequence Diagram for Order Submission
Figure 14: Sequence Diagram for Order Submission

The JMS queue on which the order is placed has a message driven been associated with it. This message-driven bean called the WorkFlowManagerBean shown in Code Sample 67, receives the order, and processes it in a transactional manner. It takes the order, splits it into multiple smaller orders, and then sends these smaller pieces to the various suppliers for fulfillment. For example, the activity providers fulfill the activity request, while the lodging provider fulfills the hotel request. The interaction with the various suppliers is through web services using a document-oriented interface.

In its implementation, the WorkFlowManagerBean MBD involves (see POHandler.java) storing the message in a database using an entity bean (see POReceiver.java), verifying the credit card associated with the purchase order using another web service (see CreditCardVerifier.java), and finally placing the order on a JMS queue.

Code Sample 67: The WorkFlowManagerBean Message Driven Bean

/**
 * This is the work flow manager that controls 
 * work flow within the Order Processing Center
 */
public class WorkFlowManagerBean implements MessageDrivenBean, MessageListener {

    private  MessageDrivenContext context; 
    private  POHandler poHandler;
    private  InvoiceHandler invHandler;
  
    public void setMessageDrivenContext(MessageDrivenContext context) {
        this.context=context;
    }  
      
    public void ejbCreate() {
        try{
            poHandler = new POHandler();  
            invHandler = new InvoiceHandler();
        } catch (HandlerException he){
            throw new EJBException(he); 
        }     
    }
      
    public void onMessage(Message message) {
        try{
            /*
             * For now, just call the handlers
             * This will change as the state machine is implemented
             */
            String docType = message.getStringProperty(JNDINames.DOC_TYPE);        
            if(docType.equals(JNDINames.PO_DOCUMENT))
                poHandler.handle(message);
            else if(docType.equals(JNDINames.INVOICE_DOCUMENT))
                invHandler.handle(message);
        } catch (HandlerException he){
            throw new EJBException(he); 
        } catch (JMSException exe) {
            throw new EJBException(exe);  
        }
    }
    
    public void ejbRemove() {}
}

 
Figure 15: Sequence Diagram for the MDB WorkFlowManagerBean
Figure 15: Sequence Diagram for the MDB WorkFlowManagerBean

Since the credit card is verified and the order ready for fulfillment, the MDB OrderFillerBean picks up the order and interacts with multiple web services using a web services Broker realized in the BrokerRequestorBean MDB. This interaction is shown in the sequence diagram in Figure 15.

The web service realized though the endpoint interface BrokerServiceIntf shown in Code Sample 68 uses the strategy outlined earlier to pass XML documents as strings. The documents are passed as strings to a single method called submitDocument that accepts an XML String. The implementation of this web service is a stateless session bean (Code Sample 69), and shows how the XML documents are processed asynchronously through the use of JMS Queues.

Code Sample 68: BrokerService Web Service Using String Representation of XML Documents

package com.sun.j2ee.blueprints.opc.webservicebroker.provider;

import java.rmi.Remote;
import java.rmi.RemoteException;
import com.sun.j2ee.blueprints.opc.serviceexceptions.*;

public interface BrokerServiceIntf extends Remote {
    public String submitDocument(String xmlDoc) 
       throws InvalidDocumentException, ProcessingException, RemoteException;
}

Code Sample 69: Implementation of the BrokerService Web Service

public class BrokerServiceBean implements SessionBean {

    private SessionContext sc;
    private BrokerTransformer bt = null;
 
    public BrokerServiceBean(){}
    
    public void ejbCreate() throws CreateException {
        bt = new BrokerTransformer();
    }

    public String submitDocument(String doc) throws InvalidDocumentException,
                                                    ProcessingException {
  // Step 1. Validate Doc
        
        boolean valid =  validate(doc);
        
        if (!valid) {
            throw new ProcessingException("BrokerServiceBean: document does not match schema" + doc);
        }
        // transform the doc
  String tDoc = bt.transform(new InputSource(new StringReader(doc)));
        if (tDoc != null) {
            doc = tDoc;
        }
  // Step 3. Map doc to domain obj
  // In this implementation, the Work Flow Manager expects the doc as it
  // is; no mapping required

  // Step 4. Find which Q to put the doc; 
  // In this implementation, the work flow
  // manager Q is the target for all messages; 

  // Step 5. Delegate the request to processing layer by sending it 
  // on to the Q
  if(delegateToProcessingLayer(JNDINames.WORKFLOW_MGR_MDB_QUEUE, doc)
                                                             == false) 
      throw new ProcessingException("Irrecoverable error while 
	      submitting requestfor processing");

  // Step 6. Send back a correlation ID - sending a dummy value here
  return("INV1234");
    }

    private boolean delegateToProcessingLayer(String destQueue, String xmlDoc)
                                              throws ProcessingException {
  return(JMSUtils.sendMessage(destQueue, JNDINames.DOC_TYPE,
            JNDINames.INVOICE_DOCUMENT, xmlDoc));
    }

// other EJB methods
}

More details about the preceding Adventure Builder example architecture and its source can be found at the AdventureBuilder Sample Application. By illustrating some of the details of this application and key concepts here, one can get an idea of how strategies outlined in this document can be used to build enterprise applications that pass XML documents and process them asynchronously.

Sample Architecture: WS-I Application

The web services Interoperability Organization (WS-I) defines a sample Supply Chain Management application WS-I Sample Application Architecture and Use Cases. It consists of the "retailer" selling electronic goods to consumers and managing stock levels in warehouses by communicating with many manufactures.

When the inventory in a warehouse falls below a minimum level, the warehouse invokes the manufacturer's web services and submits a purchase order. The manufacture ships the goods and sends a shipping notice to the retailer. The callback strategy is implemented using custom SOAP headers, where the warehouse creates a message identifier and passes that along with the callback URI in the StartHeader (see schema extract in Code Sample 70). At a later time, when the manufacturer ships the items and sends a shipping notice to the retailer, the same message identifier is then passed back in the SOAP header of the callback, identified as the CallbackHeader.

Code Sample 70: Schema Extract from the Manufacturer.wsdl Showing SOAP Headers

<xs:element name="StartHeader" type="cb:StartHeaderType"/>

<xs:element name="CallbackHeader" type="cb:CallbackHeaderType"/>
<xs:complextype name="StartHeaderType">
	<xs:sequence>
		<xs:element minoccurs="1" maxoccurs="1" name="conversationID" type="xs:string"/>
		<xs:element minoccurs="1" maxoccurs="1" name="callbackLocation" type="xs:string"/>
	</xs:sequence>
<xs:complextype name="CallbackHeaderType">
<xs:sequence>
	<xs:element minoccurs="1" maxoccurs="1" name="conversationID" type="xs:string"/>
</xs:sequence>
</xs:complextype>

Code Sample 71: Binding for the Operation Invoked by the Warehouse

<wsdl:binding name="ManufacturerSoapBinding" type="tns:ManufacturerPortType">
	<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
	<wsdl:documentation>
		<wsi:claim conformsto="http://ws-i.org/profiles/basic1.0/"/>
	</wsdl:documentation>
	<wsdl:operation name="submitPO">
		<soap:operation/>

		<wsdl:input>
			<soap:body parts="PurchaseOrder" use="literal"/>
			<soap:header message="tns:POSubmit" part="ConfigurationHeader" 
                             use="literal">
 		     <soap:headerfault message="tns:POSubmit" 
                             part="ConfigurationHeader" use="literal"/>
			</soap:header>
           	<soap:header message="tns:POSubmit" part="StartHeader" 
                            use="literal"/>
		</wsdl:input>
		<wsdl:output>
			<soap:body use="literal"/>

		</wsdl:output>
		<wsdl:fault name="POFault">
			<soap:fault name="POFault" use="literal"/>
		</wsdl:fault>
	</wsdl:operation>
</wsdl:binding>

Code Sample 72: Binding for the Callback by the Manufacturer

<wsdl:binding name="WarehouseCallbackSoapBinding" type="tns:WarehouseCallbackPortType">
		<soap:binding style="document" 
                         transport="http://schemas.xmlsoap.org/soap/http"/>
		<wsdl:operation name="submitSN">
			<soap:operation/>
			<wsdl:input>
				<soap:body parts="ShipmentNotice" use="literal"/>
				<soap:header message="tns:SNSubmit" 
                       part="ConfigurationHeader" 
					       use="literal">
					<soap:headerfault message="tns:SNSubmit"
                         part="ConfigurationHeader" 
                             use="literal"/>
				</soap:header>

				<soap:header message="tns:SNSubmit"
				    part="CallbackHeader" use="literal">
					<soap:headerfault message="tns:SNSubmit"
					    part="CallbackHeader" use="literal"/>
				</soap:header>
			</wsdl:input>
			<wsdl:output>
				<soap:body parts="Response" use="literal"/>
			</wsdl:output>
		</wsdl:operation>
<!—other elements ?
</wsdl:binding>

The Java implementation for the WS-I sample application is available with the Java WSDP download. To generate the Java data binding for the custom application level SOAP headers described above, the –f:expclictcontext option available in wscompile is used. This switch turns on explicit service context mapping and generates the class StartHeaderType (Code Sample 74).

The explicit context mapping mechanism where the SOAP headers specified in the WSDL are mapped to generated Java classes (the –f:explicitcontext option) is a feature of the Java WSDP and the Sun ONE Application server. Such features may not be available in other vendor implementations of the JAX-RPC specifications.

Code Sample 73: Explicit for the Callback by the Manufacturer

	<target name="import-wsdl">
		<wscompile
			keep="true"
			import="true"
			base="${build.classes.home}"
			sourcebase="${build.src.home}"
			xprintstacktrace="true"
			model="${work.home}/${model.file}"
			features="explicitcontext, wsi"
			httpproxy="${http.proxyHost}:${http.proxyPort}"
			config="${config.file}">
			<classpath refid="compile.classpath"/>
		</wscompile>
	</target>

Code Sample 74: Generated Java Class for the StartHeaderType SOAP Header

package com.sun.wsi.scm.manufacturer.cb;

public class StartHeaderType {
    protected java.lang.String conversationID;
    protected java.lang.String callbackLocation;
    
    public StartHeaderType() {
    }
    
    public StartHeaderType(java.lang.String conversationID, 
	    java.lang.String callbackLocation) {
        this.conversationID = conversationID;
        this.callbackLocation = callbackLocation;
    }
    
    public java.lang.String getConversationID() {
        return conversationID;
    }
    
    public void setConversationID(java.lang.String conversationID) {
        this.conversationID = conversationID;
    }
    
    public java.lang.String getCallbackLocation() {
        return callbackLocation;
    }
    
    public void setCallbackLocation(java.lang.String callbackLocation) {
        this.callbackLocation = callbackLocation;
    }
}

Sample Architecture: Correlation Using WS-Addressing

Business Process Execution Language for web services (BPEL4WS or BPEL) is an emerging technology which is gaining momentum as a way to specify integration logic and process automation between web services. The BPEL specification defines the syntax and semantics of the BPEL language, which contains a variety of process flow constructs. These constructs can be used to define business processes in XML format using vendor-supplied graphic tools. BPEL as such only defines the process part and what messages are exchanged. It does not define or mandate a particular underlying SOAP-reliable messaging protocol; it does however rely on WS-Addressing constructs to create a correlation between the messages that are exchanged between business partners. WS-Addressing is now being developed in the W3C. These constructs are passed as SOAP headers that conform to the WS-Addressing schema.

From a logical perspective, designing an application using this scheme is identical to the one outlined earlier in Section 8.1.4. The only difference is that there is additional information in the SOAP headers that contains the callback address in the format specified by WS-Addressing. The WSDL describes these SOAP headers as a part of the binding for the web service. The JAX-RPC clients can use the explicit service context mapping to generate Java data bindings for the headers. Code Sample 75 shows the WSDL for a sample loan processing application where the service receives loan applications and responds back at a later time to the caller with the processed loan application replies. The WS-Addressing-based SOAP headers constructs are used to create a correlation between a request/response and also specify the location of the callback. Code Sample 76 shows the corresponding SOAP request generated by the process executing on the service consumer.

Code Sample 75: WSDL with the WS-Addressing Scheme

<definitions xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing">
<message name="ContinueHeader">
	<part name="RelatesTo" element="wsa:RelatesTo"/>
</message>
<message name="StartHeader">
	<part name="MessageID" element="wsa:MessageID"/>
	<part name="ReplyTo" element="wsa:ReplyTo"/>
</message>
<message name="LoanServiceRequestMessage">
	<part name="payload" element="s1:loanApplication"/>
</message>
<porttype name="LoanService">
	<operation name="initiate">
		<input message="tns:LoanServiceRequestMessage"/>
	</operation>
</porttype>
<binding name="LoanServiceBinding" type="tns:LoanService">
	<soap:binding style="document" 
	    transport="http://schemas.xmlsoap.org/soap/http"/>
	<operation name="initiate">
		<soap:operation soapaction="initiate" style="document"/>
		<input>
			<soap:header message="tns:StartHeader" part="MessageID" 
                             use="literal"/>
			<soap:body use="literal"/>
		</input>
	</operation>
</binding>
	<binding name="LoanServiceCallbackBinding" type="tns:LoanServiceCallback">
	<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
	<operation name="onResult">
		<soap:operation soapaction="onResult" style="document"/>
		<input>
			<soap:header message="tns:ContinueHeader" part="RelatesTo"  
                             use="literal"/>
			<soap:body use="literal"/>
		</input>
	</operation>
</binding>
<!-other wsdl elements ' 
</definitions>

Code Sample 76: SOAP Request with WS-Addressing Headers

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<soapenv:header>
	<ns1:messageid xmlns:ns1="http://schemas.xmlsoap.org/ws/2003/03/addressing">
          bpel://localhost/default/LoanFlowPlus~1.0/11-BpInv3-BpSeq5.10-1
    </ns1:messageid>
	<ns2:replyto xmlns:ns2="http://schemas.xmlsoap.org/ws/2003/03/addressing">
	   <ns2:address>
       http://192.168.0.1:9700/LFP/StarLoanService/LoanServiceRequester</ns2:address>
	   <ns2:porttype xmlns:ns3="http://services.cxdn.com">
                      ns3:LoanServiceCallback </ns2:porttype>
        <ns2:servicename xmlns:ns4="http://services.cxdn.com">
                    ns4:LoanServiceCallbackService</ns2:servicename>
	</ns2:replyto>
	</soapenv:header>
	<soapenv:body>
		<loanapplication xmlns="http://www.autoloan.com/ns/autoloan">
			<ssn>123-12-1234</ssn>
			<email>demo1@collaxa.com</email>
			<customername>dave</customername>
			<loanamount>1000</loanamount>
			<carmodel>BMW</carmodel>
			<caryear>2003</caryear>
			<creditrating>560</creditrating>
		</loanapplication>
	</soapenv:body>
</soapenv:envelope>

This strategy allows developers to use a familiar programming API to consume web services and integrate business processes that are exposed through a WSDL. Using JAX-RPC from a J2EE container with this strategy also allows developers to expose web services that can be consumed by third party vendor products that rely on such addressing schemes. However, developers need a good understanding of the message structures to manipulate and cater to the custom headers.

Provider-Based Asynchronous Communication
 
Figure 16: Asynchronous Communication with a Provider-Based Model
Figure 16: Asynchronous Communication with a Provider-Based Model

This architecture relies on the use and implementation of messaging providers. A provider is analogous to a messaging server. Instead of communicating with the service directly, applications communicate with the provider. The provider allows the applications to exit or continue and holds on to the messages until they have been successfully delivered to the destination. It essentially takes care of all the underlying messaging needs including messaging delivery, generating and handling acknowledgements, retrying failed delivery, and message ordering The provider also receives any incoming messages on the application's behalf and delivers them to the application when it is ready to accept and process replies. This model is analogous to the one used in technologies like JMS, where Java applications use the JMS API to communicate with the providers and the providers use some vendor protocol to handle the communication between the two endpoints. To implement such architectures for web services:

  • Both ends of the communication need to
    • Agree on an underlying transport level protocol
    • Agree on an underlying message exchange protocol. For example ebMS MSH, or WS-R RMPs.
    • Implement the corresponding providers for these protocols

Some JMS vendors have actually enhanced their JMS provider implementations to support SOAP messaging over HTTP. They use HTTP as the transport under the JMS API and pass SOAP messages as the JMS TextMessage or ObjectMessage. The message format used to transport data over HTTP is vendor proprietary and usually some form of multipart MIME. Some JMS vendors have taken this approach one step further by using the SOAP with Attachments API for Java (SAAJ) to create and manipulate messages, use an HTTP transport and a SOAP message (instead of an HTTP multipart message) as the wire format. All these are viable implementation techniques; however, unless and until a standards-based wire level SOAP message exchange protocol is used, the drawback is they are accompanied with the downside of vendor lock-in and interoperability issues, since the wire level message format and endpoint are vendor specific and the same vendors implementation is required on both ends.

Sample Architecture

The provider-based architecture is used by applications that utilize an underlying messaging protocol like ebXML Messaging Service (ebMS) or WS-Reliability. The Sun Secure Trading Agent is a lightweight, peer-to-peer, web services-enabled solution based entirely on Java technology that enables secure and reliable exchange of B2B documents over the Internet.

The software supports the ebMS messaging protocol and is accompanied a sample application shown in Figure 16. Partners negotiate their business level and transaction level agreements. In ebXML this is realized a Collaboration Protocol Profile (CPP) and Collaboration Protocol agreement (CPA). The trading partners then configure their ebMS providers and software according to the agreed-upon business processes and details of the agreements. Once configured, they exchange SOAP messages using the ebMS protocol. The providers take care of handling all the details like retries, guaranteed once and only once delivery, and acknowledgements specified in the agreements and implemented using the SOAP headers standardized by the ebMS specifications. Such architectures allow for interoperability between different vendors and implementation technologies because all the providers have to do is implement the relevant SOAP-based ebMS specifications.

 
Figure 17: Sample Application in STA
Figure 17: Sample Application in STA
Pros
  • Providers handle all callback, acknowledgement addressing semantics. Applications only provide the implementations for the processors
Cons
  • Requires that both ends have the provider implementations in place
  • The application-to-provider communication will need to either use an API like SAAJ or JAXM or a provider-specific API, unless the Java bindings for that particular providers' supported protocol are standardized.
    • Using JAXM would mean that the providers have a corresponding messaging profile under JAXM.
    • SAAJ is considered more useful for advanced developers who thoroughly know the technology and who must deal manipulate SOAP messages
    • JAXM is optional in the J2EE 1.4 platform. As a result, a service developed with JAXM may not be portable. When you control both end points of a web service, it makes more sense to consider using JAXM.
Summary

Architects and developers should feel confident that the complete support for XML and web services in an integrated platform like J2EE 1.4 contains all the underpinnings needed to build real world, highly scalable applications. In this article, we looked at the difference between RPC and document-based interactions. We also looked at how document-driven web services can be built using J2EE technologies, the different strategies that can be employed by developers, and as their advantages and disadvantages. An important part of developing a document-driven web service is describing it efficiently, and so we also looked at best practices from a WSDL design perspective. This article also covered some of the strategies and the considerations that developers should keep in mind when implementing web service endpoints that process the web service messages asynchronously. What we didn’t cover is the notion of asynchronous reliable guaranteed delivery between web service endpoints and the role of reliable messaging protocols.

The source for the examples is included with this article in the references section below. More examples, solutions, and best practices can be found in the 'Java Blueprints Solution Catalog' project on Java.net. The catalog consists of an evolving set of guidelines and best practices for the J2EE 1.4 platform. Readers are encouraged to use these examples as well as participate on Java.net.

About the Author

Sameer Tyagi is a Senior Java Architect with the Software Services Organization at Sun Microsystems. He remains focused on architecture, design, and implementation of large-scale enterprise applications with Java technology. His publications include industry periodicals and books on Java and J2EE technologies. Sameer can be reached at s.t@sun.com

References

  1. Interoperability With Patterns and Strategies for Document-Based Web Services: Part 2 in a Series
  2. Realizing Strategies for Document-Based Web Services With JAX-WS 2.0: Part 3 in a Series
  3. Understanding your JAX-RPC SI Environment (Part 1, Part 2)
  4. EAI Patterns: Gregor Hohpe et al
  5. Sun Secure Trading Agent
  6. RFC1521
    MIME Part One: Mechanisms for Specifying and Describing the Format of Internet Message Bodies, section 5.2, "Base64 Content-Transfer-Encoding")
  7. iHarder.net Public Domain Java class providing a Base64 encoding and decoding in the form of convenience methods and input/output streams
  8. XML Schema DataTypes
  9. <any> element
  10. AdventureBuilder Sample Application
  11. WS-I Sample Application Architecture and Use Cases
  12. OASIS WS-BPEL Technical Committee
  13. Web services Addressing (WS-Addressing), March 2003
  14. J2EE Tutorial
  15. The Java Community Process
  16. Microsoft-Building Interoperable Web Services: WS-I Basic Profile 1.0
  17. JAX-RPC)
  18. Using Web Services Enhancements to Send SOAP Messages with Attachments
  19. Web Service Broker : Core J2EE Patterns
  20. ebXML Transport, Routing & Packaging
  21. RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax
  22. J2EE 1.4
  23. JWSDP 1.4
  24. JAX-RPC
  25. JAXMail
  26. WS-I
  27. White Paper
  28. WS-Addressing
  29. OASIS Web Services Reliable Messaging
  30. Java Blueprints Catalog
  31. Source code for all Examples

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


The Java BluePrints Program provides best practices, guidelines, and sample applications for developing enterprise Java applications and Web services. JAX-RPC is a fundamental technology in service-oriented architectures. You can find JAX-RPC best practices, as well as sample code that uses JAX-RPC, in the Java BluePrints Solutions Catalog which presents (among other things) best practices, guidelines, and sample applications for developing Service-Oriented Architectures (SOA) with Web services. Learn more about Java BluePrints for SOA and get questions answered in this online chat with two key members of the Java BluePrints team, Inderjeet Singh and Sean Brydon, and with Enterprise Java architect, Sameer Tyagi.

Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.