bea.com | products | dev2dev | support | askBEA |
![]() |
![]() |
|
![]() |
e-docs > WebLogic Platform > WebLogic Integration > B2B Topics > Implementing cXML > Using the cXML API |
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:
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.
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:
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:
Your application should be able to deal with all of the messaging objects included in the payload:
cXML DTDs
The DTDs you will need are available at the following locations:
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).
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:
private static CXMLManager cxmlm = CXMLManager.getInstance();
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");
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:
// Get the cXML document
CXMLDocument reqMsgDoc = cmsg.getRequestDocument();
// Get the XML DOM doc
Document reqXMLDoc = reqMsgDoc.getDocument();
String otherSharedSecret = cxmlm.getSharedSecret(otherTradingPartnerName);
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.
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);
Element request = punchoutDoc.createElement("Request");
// 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")),
CXMLDocument replyMsgDoc = new CXMLDocument();
replyMsgDoc.setDocument(replyXMLDoc);
cmsg.setReplyDocument(replyMsgDoc);
cmsg.setCollaborationAgreement(prop);
cmsg.reply();
Processing Outgoing Messages
You must initialize outgoing messages before you send them. To do so:
private static CXMLToken token;
private static CXMLManager cxmlm = CXMLManager.getInstance();
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");
token = cxmlm.register(prop);
Sending the Message
To send a message, your application must perform the following actions:
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);
Element request = punchoutDoc.createElement("request");
Element trans = punchoutDoc.createElement("PunchoutSetupRequest");
request.appendchild(trans);
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")),
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);
CXMLDocument reqMsgDoc = new CXMLDocument();
reqMsgDoc.setDocument(reqXMLDoc);
cmsg.setRequestDocument(reqMsgDoc);
cmsg.setCollaborationAgreement(prop);
CXMLMessageToken sendToken = (CXMLMessageToken) cmsg.send();
CXMLDocument replyMsgDoc = cmsg.getReplyDocument();
org.w3c.dom.Document replyXMLDoc = replyMsgDoc.getDocument();
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);
}
}
}
![]() |
![]() |
![]() |
![]() |
||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |