bea.com | products | dev2dev | support | askBEA

Download Docs | Site Map | Glossary
Search

Implementing cXML

Using the cXML API

Note: The cXML business protocol is deprecated as of this release of WebLogic Integration. For information about the features that are replacing it, see the BEA WebLogic Integration Release Notes.

The following sections describe some key programming issues for the cXML API:

- cXML Methods

- cXML Message Structure

- cXML DTDs

- Dealing with Shared Secrets

- Processing Incoming Messages

- Processing Outgoing Messages

For more information about programming business operations, see Creating Workflows for B2B Integration.

cXML Methods

The following table describes the methods available for cXML message manipulation.

Table 3-1 Public cXML Methods

Method | Package | Description
--- | --- | ---
onMessage | com.bea.b2b.protocol.cxml.CXMLListener | Receives an incoming CXMLMessage
deregister | com.bea.b2b.protocol.cxml.CXMLManager | Deregisters the application with this CXMLManager. Uses a set of properties to select the registration.
getInstance | com.bea.b2b.protocol.cxml.CXMLManager | Gets an instance of the CXMLManager.
getSharedSecret | com.bea.b2b.protocol.cxml.CXMLManager | Gets the Shared Secret for this Trading Partner. Uses the Trading Partner name to find the Shared Secret.
register | com.bea.b2b.protocol.cxml.CXMLManager | Registers the application with this CXMLManager. Uses a set of properties to select the collaboration agreement for this Trading Partner. Use for sending cXML messages.
getHttpStatusCode | com.bea.b2b.protocol.cxml.CXMLHttpStatusException | Returns the HTTP Status code from the exception.
getAsString | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets the cXML part as a String.
getDocument | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets the associated XML Document.
getFromCredentialDomains | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets the From Credential Domains from the document header.
getFromCredentialIdentities | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets the From Credential Identities from the document header.
getIdentifier | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets either the document identifier or the message identifier, as appropriate.
getNodeValue | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets the value of a document node using the specified XPath expression to locate the node. If multiple nodes match the XPath expression, then only the first node is used.
getSenderCredentialDomain | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets the Sender Credential Domain from the document header.
getSenderCredentialIdentity | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets the Sender Credential Identity from the document header.
getSenderSharedSecret | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets the Sender Credential Shared Secret from the document header.
getSenderUserAgent | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets the Sender User Agent from the document header.
getTimeStamp | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets either the document timestamp or the message timestamp, as appropriate.
getToCredentialDomain | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets the To Credential Domain from the document header.
getToCredentialIdentity | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets the To Credential Identity from the document header.
getVersion | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Gets the document version.
setDocument | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Sets the associated XML document.
setNodeValue | com.bea.b2b.protocol.cxml.messaging.CXMLDocument | Sets the value of a document node using the specified XPath expression to locate the node.
reply | com.bea.b2b.protocol.cxml.messaging.CXMLMessage | Replies to the request message. This method is only valid when this object is used as a parameter to CXMLListener.onMessage(). The reply may be sent asynchronously after the method has been called.
getReplyDocument | com.bea.b2b.protocol.cxml.messaging.CXMLMessage | Gets the reply cXML document.
getRequestDocument | com.bea.b2b.protocol.cxml.messaging.CXMLMessage | Gets the request cXML document.
send | com.bea.b2b.protocol.cxml.messaging.CXMLMessage | Sends a request message. This method blocks until a reply is received. The reply can be accessed via getReplyDocument().
setCollaborationAgreement | com.bea.b2b.protocol.cxml.messaging.CXMLMessage | Sets the Collaboration Agreement ID for the collaboration agreement to which this message belongs. Uses a set of properties to select the Collaboration Agreement.
setReplyDocument | com.bea.b2b.protocol.cxml.messaging.CXMLMessage | Sets the reply cXML document.
setRequestDocument | com.bea.b2b.protocol.cxml.messaging.CXMLMessage | Sets the request cXML document.
getHttpStatusCode | com.bea.b2b.protocol.cxml.messaging.CXMLMessageToken | Gets the HTTP status code.

For more information about individual methods, see the BEA WebLogic Integration Javadoc.

Properties Used to Locate Collaboration Agreements

cXML uses a set of defined properties to locate unique collaboration agreements. When attempting to locate a specific collaboration agreement, you must supply values for all of the following properties:

- BusinessProcessName

- BusinessProcessVersion

- DeliveryChannel

- toRole

- fromTradingPartner

- toTradingPartner

cXML Message Structure

A cXML message is based on the message envelope. The message envelope includes the following data structures.

Figure 3-1 cXML Message Architecture

The message data structures are as follows:

- Header—Contains addressing and validation information, including the From, To, and Sender data arrays. These data arrays provide information on the various parties to the transaction, as well as validation information for each of the participants.

- Payload—All the business documents and attachments that make up the body of a message.

Your application should be able to deal with all of the messaging objects included in the payload:

- Business document—One or more cXML documents, each containing cXML data, each part of which can be validated using cXML DTDs.

- cXML document—A cXML-standard document containing data. cXML documents can be validated individually using cXML DTDs.

- Attachment—An optional MIME-encoded binary attachment. WebLogic Integration does not support cXML attachments. If you want to use them, however, you can configure a private process to resolve MIME-encoded attachments.

cXML DTDs

The DTDs you will need are available at the following locations:

- cXML DTDs are available from the cXML.org Web site at the following URL:

http://xml.cxml.org/schemas/cXML/version/cXML.dtd

Here, version represents the full cXML version number (such as 1.1, 1.2, and so on).

- The Confirmation and Ship Notice transactions are contained in a separate DTD, located at the following URL:

http://xml.cxml.org/schemas/cXML/version/Fulfill.dtd

Here, version represents the full cXML version number (such as 1.1, 1.2, and so on).

Validation using these DTDs is not required when you send a cXML message. However, one assumption of the cXML messaging structure is that any message you send has been validated. Therefore it is a good idea to validate your messages routinely against the DTDs, at least while you are testing interoperability with a new trading partner. Once you are comfortable with your trading partner, you may optionally turn off message validation to enhance performance.

Dealing with Shared Secrets

The cXML API provides access to the value of the shared secret stored in the repository. The GetSharedSecret method allows you to retrieve the shared secret from the repository for comparison to the shared secret stored in incoming documents, or for use in outgoing cXML documents.

For incoming documents, your business operation code must perform verification of the shared secret of an incoming message by matching its value with the value specified in the configuration stored in the repository.

In each outgoing cXML document, your business operation code must insert the shared secret in the Credential node.

Processing Incoming Messages

To process an incoming message, you must first initialize it. The registration function associates a collaboration agreement with either a listener or a sending application. The token returned by the initialization process is used in the cXML message when the message is sent or received.

Initialization

To initialize an incoming message:

1. Get a copy of the listener object.

2. Define the return token:
   private static CXMLToken token;

3. Retrieve an instance of the cXML Manager class com.bea.b2b.protocol.cxml.CXMLManager:

   >     private static CXMLManager cxmlm = CXMLManager.getInstance();

4. Define a set of properties to register this application and listener. The properties are used to locate and map a unique collaboration agreement. For more information about the properties needed to map a unique collaboration agreement, see Properties Used to Locate Collaboration Agreements.

   >     prop.setProperty("BusinessProcess", businessProcess);
   >     prop.setProperty("BusinessProcessVersion", businessProcessVersion);
   >     prop.setProperty("DeliveryChannel", deliveryChannel);
   >     prop.setProperty("thisTradingPartner", myTradingPartnerName);
   >     prop.setProperty("otherTradingPartner", otherTradingPartnerName);
   >     prop.setProperty("toRole", toRole);
   >     prop.setProperty("Party", "duns4");

5. Invoke the register method from the CXMLManager class:
   token = cxmlm.register(prop);

Processing the Message

Once you have initiated an incoming message, as described in the Initialization section, you can process it. To do so, your application must:

1. Get the request cXML document from the received cXML message using the onMessage() callback method. This method passes the received cXML message from the WebLogic Integration run time to your application code.

2. Get the XML DOM document from the cXML document:

   >     // Get the cXML document
   >       CXMLDocument reqMsgDoc = cmsg.getRequestDocument();

   >       // Get the XML DOM doc
   >       Document reqXMLDoc = reqMsgDoc.getDocument();

3. Process the request document based on the payload.

4. Retrieve the shared secret from the incoming message. The shared secret for the trading partner is defined in the message, in: //cXML/Header/From/Credential.

   >     String otherSharedSecret = cxmlm.getSharedSecret(otherTradingPartnerName);

5. Verify that the shared secret from the message matches the shared secret defined in the configuration for the trading partner:

   >     debug("Stored Shared Secret for " + otherTradingPartnerName + ": " + otherSharedSecret);

   If the transaction is peer-to-peer, then the trading partner is the buyer or supplier. If the transaction is being conducted through the hub, then the trading partner is the hub.

   The following comparison failure options may occur.

   Table 3-2 Verification Failure Options

   Result | Reason
   --- | ---
   No comparison was performed | The shared secret has not been configured for the trading partner.
   Message was rejected with 400 (bad request) http status code. | Request message could not be parsed. This problem should be resolved in the WebLogic Integration run time.
   Message was rejected with 401 (unauthorized access) http status code. | Shared secrets do not match.
   Message was rejected with 500 (Unable to forward request) http status code. | The listener was not properly configured. This should be resolved in the WebLogic Integration run time.

6. Create the reply XML DOM implementation document:

   >     DOMImplementationImpl domi = new DOMImplementationImpl();

   >     DocumentType dType =
   >     domi.createDocumentType("request", null, "cXML.dtd");

   >     org.w3c.dom.Document punchoutDoc = new DocumentImpl(dType);
   >     CxmlElementFactory cf = new CxmlElementFactory(punchoutDoc);

7. Create the reply cXML document:

   >     Element request = punchoutDoc.createElement("Request");

8. Create the header elements in the document:

   >     // header
   >     cf.createHeaderElement(
   >     // from
   >     cf.createFromElement(
   >     cf.createCredentialElement(
   >     "DUNS",
   >     myTradingPartnerName,
   >     null)),
   >     // to
   >     cf.createToElement(
   >     cf.createCredentialElement(
   >     "DUNS",
   >     otherTradingPartnerName,
   >     null)),
   >     // sender
   >     cf.createSenderElement(
   >     cf.createCredentialElement(
   >     "AribaNetworkUserId",
   >     "admin@acme.com",
   >     otherSharedSecret),
   >     "Ariba ORMS 5.1P4")),

9. Set the XML document in the cXML document:

   >     CXMLDocument replyMsgDoc = new CXMLDocument();
   >     replyMsgDoc.setDocument(replyXMLDoc);

10. Set the cXML document in the reply cXML message:

    >     cmsg.setReplyDocument(replyMsgDoc);

11. Set the collaboration agreement in the cXML message:

    >     cmsg.setCollaborationAgreement(prop);

12. Send the reply message to dispatch the outgoing cXML message from your application to the WebLogic Integration run time:

    >     cmsg.reply();

Processing Outgoing Messages

You must initialize outgoing messages before you send them. To do so:

1. Define the return token:

   >     private static CXMLToken token;

2. Retrieve an instance of the cXML Manager class:
   com.bea.b2b.protocol.cxml.CXMLManager.

   >     private static CXMLManager cxmlm = CXMLManager.getInstance();

3. Define a set of properties to register this application. The properties are used to locate and map a unique collaboration agreement. For more information about the properties needed to map a unique collaboration agreement, see Properties Used to Locate Collaboration Agreements.

   >     prop.setProperty("BusinessProcess", businessProcess);
   >     prop.setProperty("BusinessProcessVersion", businessProcessVersion);
   >     prop.setProperty("DeliveryChannel", deliveryChannel);
   >     prop.setProperty("thisTradingPartner", myTradingPartnerName);
   >     prop.setProperty("otherTradingPartner", otherTradingPartnerName);
   >     prop.setProperty("toRole", toRole);
   >     prop.setProperty("Party", "duns4");

4. Invoke the register method:

   >     token = cxmlm.register(prop);

Sending the Message

To send a message, your application must perform the following actions:

1. Create a cXML message:

   >     DOMImplementationImpl domi = new DOMImplementationImpl();

   >     DocumentType dType =
   >     domi.createDocumentType("request", null, "cXML.dtd");

   >     org.w3c.dom.Document punchoutDoc = new DocumentImpl(dType);
   >     CxmlElementFactory cf = new CxmlElementFactory(punchoutDoc);

2. Create the XML DOM request document:

   >     Element request = punchoutDoc.createElement("request");
   >     Element trans = punchoutDoc.createElement("PunchoutSetupRequest");
   >     request.appendchild(trans);

3. Create the header elements in the request document:

   >     punchoutDoc.appendChild(
   >     cf.createCxmlElement(
   >     // header
   >     cf.createHeaderElement(
   >     // from
   >     cf.createFromElement(
   >     cf.createCredentialElement(
   >     "DUNS",
   >     myTradingPartnerName,
   >     null)),
   >     // to
   >     cf.createToElement(
   >     cf.createCredentialElement(
   >     "DUNS",
   >     otherTradingPartnerName,
   >     null)),
   >     // sender
   >     cf.createSenderElement(
   >     cf.createCredentialElement(
   >     "AribaNetworkUserId",
   >     "admin@acme.com",
   >     otherSharedSecret),
   >     "Ariba ORMS 5.1P4")),

4. Retrieve the receiving trading partner's shared secret from the appropriate trading partner profile. For peer-to-peer messages, this will be the actual receiving trading partner's shared secret. For messages routed through a hub, this will be the hub's shared secret.

   The value of the receiving trading partner's shared secret (defined in //cXML/Header/To/Credential) is updated to the sender's shared secret element (defined in //cXML/Header/Sender/Credential):

   >     String otherSharedSecret = cxmlm.getSharedSecret(otherTradingPartnerName);
   >     debug("Stored Shared Secret for " + otherTradingPartnerName + ": " + otherSharedSecret);

5. Create the cXML document:

   >     CXMLDocument reqMsgDoc = new CXMLDocument();

6. Set the cXML document in the cXML message:

   >     reqMsgDoc.setDocument(reqXMLDoc);
   >     cmsg.setRequestDocument(reqMsgDoc);

7. Set the collaboration agreement in the cXML message:

   >     cmsg.setCollaborationAgreement(prop);

8. Send the message:

   >     CXMLMessageToken sendToken = (CXMLMessageToken) cmsg.send();

9. Get the reply document:

   >     CXMLDocument replyMsgDoc = cmsg.getReplyDocument();

10. Extract the XML document:

    >     org.w3c.dom.Document replyXMLDoc = replyMsgDoc.getDocument();

11. Verify the response.

Code Samples

This section shows examples of code used by buyers and suppliers to process messages. These examples are provided solely to illustrate the operation of the cXML classes; they are not intended for execution. The examples below are configured for peer-to-peer operation.

For more information about cXML classes, see BEA WebLogic Integration Javadoc.

Sample Buyer

Listing 3-1 Code for Sample Buyer

>     /*
>      *        Copyright (c) 2001 BEA
>      *        All rights reserved
>     */
>     package examples.ibcxmlverifier;

>     import java.io.*;
>     import java.util.*;
>     import javax.servlet.*;
>     import javax.servlet.http.*;

>     import org.w3c.dom.*;
>     import org.apache.html.dom.*;
>     import org.apache.xml.serialize.*;
>     import org.apache.xerces.dom.*;

>     import com.bea.b2b.protocol.cxml.messaging.*;
>     import com.bea.b2b.protocol.cxml.*;

>     import com.bea.eci.logging.*;

>     /**
>      * This example provides a simple test that will verify message flow of cXML
>      * peer-to-peer sending and receiving a cXML document.
>      * The two peers (Partner1 and Partner2) are running on a single WLS.
>      * Partner1 sends a PunchoutRequest to Partner2.  Partner2 generates a
>      * PunchoutSetupResponse and returns it to Partner1.  Shared Secrets are verified
>      * at both ends.
>      */
>     public class Partner1Servlet extends HttpServlet
>     {
>       static final boolean DEBUG = true;

>       private final static String businessProcess = "PunchoutSetup";
>       private final static String businessProcessVersion = "1.1.009";
>       private final static String deliveryChannel = "CXMLPartnerVerifier1";
>       private final static String myTradingPartnerName = "CXMLPartnerVerifier1";
>       private final static String otherTradingPartnerName = "CXMLPartnerVerifier2";
>       private final static String toRole = "Supplier";
>       private final static String expectedURL = "http://xyz/abc?from=" + myTradingPartnerName;
>       private DocSerializer ds;

>       // Create the token for this application
>       private static CXMLToken token;

>       // Get the manager instance
>       private static CXMLManager cxmlm = CXMLManager.getInstance();

>       private static Properties prop = new Properties();

>       public void init(ServletConfig sc) {
>         try {
>           debug("Initializing servlet for Partner1");

>           // Set the properties for finding the Collaboration Agreement
>           prop.setProperty("BusinessProcess", businessProcess);
>           prop.setProperty("BusinessProcessVersion", businessProcessVersion);
>           prop.setProperty("DeliveryChannel", deliveryChannel);
>           prop.setProperty("thisTradingPartner", myTradingPartnerName);
>           prop.setProperty("otherTradingPartner", otherTradingPartnerName);
>           prop.setProperty("toRole", toRole);
>           prop.setProperty("Party", "duns4");

>           // Register the buyer with the manager using properties
>           token = cxmlm.register(prop);

>         } catch (Exception e) {
>           debug("CXMLPartnerVerifier1 init exception: " + e);
>           e.printStackTrace();
>         }
>       }

>       private org.w3c.dom.Document getBusinessDocument() {
>         DOMImplementationImpl domi = new DOMImplementationImpl();

>         DocumentType dType =
>           domi.createDocumentType("request", null, "cXML.dtd");

>         org.w3c.dom.Document punchoutDoc = new DocumentImpl(dType);
>         CxmlElementFactory cf = new CxmlElementFactory(punchoutDoc);

>         try {
>           String otherSharedSecret = cxmlm.getSharedSecret(otherTradingPartnerName);
>           debug("Stored Shared Secret for " + otherTradingPartnerName + ": " + otherSharedSecret);

>           // Header
>           Element request = punchoutDoc.createElement("Request");
>           Element trans = punchoutDoc.createElement("PunchoutSetupRequest");
>           request.appendChild(trans);

>           punchoutDoc.appendChild(
>             cf.createCxmlElement(
>     	      // payload
>     	      "1233444-200@ariba.acme.com",

>     	      // header
>     	      cf.createHeaderElement(
>     	      // from
>     	      cf.createFromElement(
>     	      cf.createCredentialElement(
>     	        "DUNS",
>     	        myTradingPartnerName,
>     	        null)),
>     	      // to
>     	      cf.createToElement(
>     	      cf.createCredentialElement(
>     	        "DUNS",
>     	        otherTradingPartnerName,
>     	        null)),
>     	      // sender
>     	      cf.createSenderElement(
>     	      cf.createCredentialElement(
>     	        "AribaNetworkUserId",
>     	        "admin@acme.com",
>     	        otherSharedSecret),
>     	        "Ariba ORMS 5.1P4")),
>     	      // request
>     	      request));

>         }
>         catch( Exception e )  {
>           debug("MessageDeliveryException: " + e.toString());
>           e.printStackTrace();
>         }
>         return punchoutDoc;
>       }

>       /**
>        * The actual work is done in this routine.  Construct a message document,
>        * publish the message, wait for a reply, terminate and report back.
>        */
>       public void service(HttpServletRequest req, HttpServletResponse res)
>         throws ServletException, IOException
>       {
>         try {

>           // setup for the reply display to client
>           res.setContentType("text/html");
>           PrintWriter pw = res.getWriter();
>           pw.println("<HTML><BODY BGCOLOR=#ff0000>");
>           pw.println("<P><IMG SRC=logo.jpg WIDTH=185 HEIGHT=156"+
>             " ALIGN=TOP BORDER=0 NATURALSIZEFLAG=3></P>");
>           pw.println("<P><FONT SIZE=-1>Partner1 process flow:<BR>");
>           pw.println("Starting Partner1...");

>           debug("Starting Partner1: get Document...");

>           CXMLMessage cmsg = new CXMLMessage();

>           org.w3c.dom.Document reqXMLDoc = getBusinessDocument();

>           CXMLDocument reqMsgDoc = new CXMLDocument();
>           reqMsgDoc.setDocument(reqXMLDoc);
>           cmsg.setRequestDocument(reqMsgDoc);

>           DocSerializer ds = new DocSerializer();

>           debug("buyer: request document:\n" +
>             ds.docToString(reqXMLDoc, true) + "\n");

>           // Set the CA with the properties
>           cmsg.setCollaborationAgreement(prop);

>           // Send the message and get the reply
>           CXMLMessageToken sendToken = (CXMLMessageToken) cmsg.send();
>           CXMLDocument replyMsgDoc = cmsg.getReplyDocument();

>           debug("Got document");
>           if (replyMsgDoc == null) {
>             debug("replyMsgDoc bad");
>           }
>           org.w3c.dom.Document replyXMLDoc = replyMsgDoc.getDocument();

>           debug("buyer: reply document:\n" +
>             ds.docToString(replyXMLDoc, true) + "\n");

>           // Verify we get the correct response
>           String punchoutURL = replyMsgDoc.getNodeValue(
>             "//cXML/Response/PunchoutSetupResponse/StartPage/URL");
>           if (punchoutURL.equals(expectedURL)) {
>             debug("Correct response received");
>             pw.println("<P>Correct response received");
>           }
>           else  {
>             debug("Unexpected response received");
>             pw.println("<P>Unexpected response received");
>           }

>           // Verify that the shared secret is mine
>           String dss = replyMsgDoc.getSenderSharedSecret();
>           debug("Document Shared Secret for " + myTradingPartnerName + ": " + dss);

>           String sss = cxmlm.getSharedSecret(myTradingPartnerName);
>           debug("Stored Shared Secret for " + myTradingPartnerName + ": " + sss);

>           if (dss.equals(sss)) {
>             debug("Shared Secret match");
>             pw.println("<P>Shared Secret match");
>           } else {
>             debug("Shared Secret mismatch");
>             pw.println("<P>Shared Secret mismatch");
>           }
>         }
>         catch( Exception e )  {
>           debug("MessageDeliveryException: " + e.toString());
>           e.printStackTrace();
>         }
>       }

>       /**
>        * A simple routine that writes to the wlc log
>        */
>       private static void debug(String msg){
>         if (DEBUG)
>           UserLog.log("***Partner1Servlet: " + msg);
>       }
>     }

Sample Supplier

Listing 3-2 Code for Sample Supplier

>     /*
>      *        Copyright (c) 20001 BEA
>      *        All rights reserved
>     */
>     package examples.ibcxmlverifier;

>     import java.io.*;
>     import java.util.*;

>     import javax.servlet.*;
>     import javax.servlet.http.*;

>     import org.w3c.dom.*;
>     import org.apache.html.dom.*;
>     import org.apache.xml.serialize.*;
>     import org.apache.xerces.dom.*;

>     import com.bea.b2b.protocol.messaging.*;
>     import com.bea.b2b.protocol.cxml.messaging.*;
>     import com.bea.b2b.protocol.cxml.CXMLListener;
>     import com.bea.b2b.protocol.cxml.*;

>     import com.bea.eci.logging.*;

>     /**
>      * This example provides a simple test that will verify message flow of cXML
>      * peer-to-peer sending and receiving a cXML document.
>      * The two peers (Partner1 and Partner2) are running on a single WLS.
>      * Partner1 sends a PunchoutRequest to Partner2.  Partner2 generates a
>      * PunchoutSetupResponse and returns it to Partner1.  Shared Secrets are verified
>      * at both ends.
>      */
>     public class Partner2Servlet extends HttpServlet {

>       static final boolean DEBUG = true;

>       private final static String businessProcess = "PunchoutSetup";
>       private final static String businessProcessVersion = "1.1.009";
>       private final static String deliveryChannel = "CXMLPartnerVerifier2";
>       private final static String myTradingPartnerName = "CXMLPartnerVerifier2";
>       private final static String otherTradingPartnerName = "CXMLPartnerVerifier1";
>       private final static String toRole = "Buyer";

>       // Create the token for this application
>       private static CXMLToken token;

>       // Get the manager instance
>       private static CXMLManager cxmlm = CXMLManager.getInstance();

>       private static Properties prop = new Properties();

>       public void init(ServletConfig sc) {
>         try {
>           debug("Initializing servlet for Partner2");

>           // Set the properties for finding the Collaboration Agreement
>           prop.setProperty("BusinessProcess", businessProcess);
>           prop.setProperty("BusinessProcessVersion", businessProcessVersion);
>           prop.setProperty("DeliveryChannel", deliveryChannel);
>           prop.setProperty("thisTradingPartner", myTradingPartnerName);
>           prop.setProperty("otherTradingPartner", otherTradingPartnerName);
>           prop.setProperty("toRole", toRole);
>           prop.setProperty("Party", "duns5");

>           // Register the supplier listener with the manager using properties
>           token = cxmlm.register(new Partner2MessageListener(), prop);

>           debug("Partner2 waiting for message...");
>         } catch (Exception e) {
>           debug("CXMLPartnerVerifier2 init exception: " + e);
>           e.printStackTrace();
>         }
>       }

>       /**
>        * This routine starts the peer
>        */
>       public void service(HttpServletRequest req, HttpServletResponse res)
>         throws ServletException, IOException{
>         debug("Starting Partner2");
>       }

>       /**
>        * A simple routine that writes to the wls log
>        */
>       private static void debug(String msg){
>         if (DEBUG)
>           UserLog.log("***Partner2Servlet: " + msg);
>       }

>       public class Partner2MessageListener
>         implements CXMLListener
>       {
>         public void onMessage(CXMLMessage cmsg) {
>             XPathHelper xp = new XPathHelper();

>           try {
>             debug("Partner2 received message");
>             // QualityOfService qos = cmsg.getQoS();

>             CXMLDocument reqMsgDoc = cmsg.getRequestDocument();
>             if (reqMsgDoc == null){
>               throw new Exception("Did not get a request payload");
>             }
>             Document reqXMLDoc = reqMsgDoc.getDocument();
>             if (reqXMLDoc == null){
>               throw new Exception("Did not get a request document");
>             }
>             String from = reqMsgDoc.getNodeValue(
>               "//cXML/Header/From/Credential/Identity" );
>             if (from == null) {
>     	      from = "nobody";
>             }
>             debug("Received request from " + from );

>             DocSerializer ds = new DocSerializer();

>             debug("supplier: request document:\n" +
>               ds.docToString(reqXMLDoc, true) + "\n");

>             debug("Building reply document");

>             DOMImplementationImpl domi = new DOMImplementationImpl();
>             DocumentType dType =
>     	      domi.createDocumentType("response", null, "cXML.dtd");

>             org.w3c.dom.Document replyXMLDoc = new DocumentImpl(dType);
>             CxmlElementFactory cf = new CxmlElementFactory( replyXMLDoc );

>             String otherSharedSecret = cxmlm.getSharedSecret(otherTradingPartnerName);
>             debug("Stored Shared Secret for " + otherTradingPartnerName  + ": " + otherSharedSecret);

>             replyXMLDoc.appendChild(
>               cf.createCxmlElement(
>     	        // payload
>     	          "1233444-200@ariba.acme.com",

>     	        // header
>     	      cf.createHeaderElement(
>     	        // from
>     	      cf.createFromElement(
>     	      cf.createCredentialElement(
>     	        "DUNS",
>     	        myTradingPartnerName,
>     	        null)),
>     	        // to
>     	      cf.createToElement(
>     	      cf.createCredentialElement(
>     	        "DUNS",
>     	        otherTradingPartnerName,
>     	        null)),
>     	      // sender
>     	      cf.createSenderElement(
>     	      cf.createCredentialElement(
>     	        "AribaNetworkUserId",
>     	        "admin@acme.com",
>     	        otherSharedSecret),
>     	        "Ariba ORMS 5.1P4")),
>     	      // body
>     	      cf.createResponseElement(
>     	        "200",
>     	        "ok",
>     	      cf.createPunchoutSetupResponseElement(
>     	        "http://xyz/abc?from=" + from ))));

>             CXMLDocument replyMsgDoc = new CXMLDocument();
>             replyMsgDoc.setDocument(replyXMLDoc);

>             cmsg.setReplyDocument(replyMsgDoc);

>             debug("supplier: reply document:\n" +
>               ds.docToString(replyXMLDoc, true) + "\n");

>             // Verify that the shared secret is mine
>             String dss = reqMsgDoc.getSenderSharedSecret();
>             debug("Document Shared Secret for " + myTradingPartnerName + ": " + dss);

>             String sss = cxmlm.getSharedSecret(myTradingPartnerName);
>             debug("Stored Shared Secret for " + myTradingPartnerName  + ": " + sss);

>             if (dss.equals(sss)) {
>               debug("Shared Secret match");
>             } else {
>               debug("Shared Secret mismatch");
>             }

>             // Set the CA with the properties
>             cmsg.setCollaborationAgreement(prop);
>             cmsg.reply();

>             debug("Partner2 sent reply");
>           } catch(Exception e) {
>             debug("Exception errors" + e);
>             e.printStackTrace();
>           }
>         }

>         public void onTerminate(Message msg) throws Exception {
>           debug(" received terminate notification for " + msg.getConversationId());

>           // Deregister with the manager
>           cxmlm.deregister(prop);
>         }
>       }
>     }