Message Profiling Using JAXM


Sun has released the Java API for XML Messaging (JAXM) to combine messaging and XML processing capabilities into one API. It enables both synchronous and asynchronous communication (refer to the discussion related to synchronous and asynchronous communications in the section "Messaging Versus Request-Response" earlier in this chapter).

JAXM follows the standard SOAP 1.1 and SOAP with Attachments specifications. It can generate SOAP-compatible messages and work in any of the following ways:

  • JAXM as a simple SOAP client JAXM can author a simple SOAP message with only a SOAP Body inside the SOAP Envelope. After authoring the SOAP message, JAXM will send it synchronously through HTTP communication. This is the simplest form of SOAP communication, in that JAXM acts like a simple SOAP-over-HTTP client.

  • Using JAXM for SOAP Header authoring JAXM can also add a SOAP Header in the SOAP message being sent. The SOAP Header is an extensibility mechanism used to build higher layers of protocols on top of the basic SOAP framework. This means that a protocol layer operating above SOAP will define its own XML syntax to be included in the SOAP Header. The SOAP specification does not dictate anything about its header. So, you can build whatever mechanism you feel like using in the SOAP Header.

    One of the most significant efforts in building SOAP-based protocols is in defining the Web services security mechanism for SOAP-based Web services. Another important use of SOAP Headers is to define the ebXML Messaging Service framework.

  • Using JAXM providers and profiles JAXM supports asynchronous communication for both the preceding points. This means that you can send SOAP messages with or without Headers asynchronously. You will use JAXM providers for asynchronous communication. A JAXM client will hand over the message to the JAXM provider. The JAXM provider is responsible to route the message to its destination asynchronously. The provider will also inform the client when a response is received from the other end.

    JAXM also allows the use of preconfigured JAXM profiles. A JAXM profile represents a specific SOAP-based protocol. When you use the preconfigured profiles, you no longer need to author SOAP Headers yourself. The JAXM profile will create the correct Header according to the protocol that it supports. The JAXM 1.0 Reference Implementation comes with two profiles one for the simple SOAP Remote Provider (SOAPRP), and one for the ebXML Messaging Service.

    A JAXM provider implementation is required to support the basic features as specified by the SOAP 1.1 and SOAP with Attachments specifications. Anything beyond the basic SOAP features is optional. However, most JAXM provider implementations will implement at least something (probably one or more profiles supporting some SOAP-based protocols) on top of the basic SOAP functionality. Building profiles to support SOAP-based protocols is among the most important objectives of JAXM.

Note

Note that a JAXM provider may support multiple profiles, but an application can use only one at a time.


We will now see the details of how the three types of operations are accomplished using JAXM.

JAXM As a Simple SOAP Client

We will now discuss the first and simplest case, in which JAXM acts as a SOAP client. In this case, we will use JAXM to perform the following tasks:

  1. Author a SOAP request consisting of a SOAP Envelope containing a SOAP Body. JAXM will also author the application-specific contents of the SOAP Body.

  2. Create a connection with the remote server.

  3. Send the SOAP request to the remote SOAP server synchronously and wait for the response.

  4. Process and display the SOAP response received from the SOAP server.

Let's see how these tasks are accomplished using JAXM. The following lines of code author a complete SOAP request:

 MessageFactory messageFactory = MessageFactory.newInstance();  SOAPMessage request = messageFactory.createMessage(); SOAPPart soapPartOfRequest = request.getSOAPPart(); SOAPEnvelope soapEnvelope = soapPartOfRequest.getEnvelope(); SOAPBody soapBody = soapEnvelope.getBody(); Name methodName = soapEnvelope.createName( "invoke" , "jaxm", "urn:P2PCarRental"); soapBody.addChildElement(methodName); 

The first step is to instantiate a MessageFactory that will be used to author a SOAP request message using the MessageFactory.createMessage method. The createMessage method authors a default SOAPMessage object, which contains a SOAP Envelope. The SOAP Envelope in turn contains an empty SOAP Header and an empty SOAP Body.

The following is the XML representation of a default SOAPMessage object created by createMessage method:

 <soap-env:Envelope      xmlns:soap-env=http://schemas.xmlsoap.org/soap/envelope/">     <soap-env:Header/>     <soap-env:Body/> </soap-env:Envelope> 

SOAP messages can also optionally contain non-SOAP (or even non-XML) parts. They are treated as attachments with the SOAP part of the message.

Your interest lies with the SOAP part of the message, so you can add SOAP service invocation details to the SOAP Body. The getSOAPPart method of the SOAPMessage class will extract the SOAP part of the message (a SOAPPart object).

Next you will call the SOAPPart.getEnvelope method that returns the SOAPEnvelope object. The SOAPEnvelope class has a method named getSOAPBody. The getSOAPBody method will eventually bring you the SOAPBody object that you will manipulate.

You will now author the application-specific XML content of your SOAP request, and then add the content to the SOAPBody object. XML authoring with JAXM is generally a two-step procedure. You first create a new element, and then add the newly created element to the appropriate place.

A new element is created by using the createName method of the SOAPEnvelope class. This returns a Name object. A newly created element is empty, and therefore just carries an XML name (which might include an element name, a namespace prefix, and a namespace URI). That's probably the reason why JAXM calls a new element a Name object.

You will need to specify three parameters while creating a new element for the XML contents of SOAP Body: the name of the element, the namespace prefix, and the namespace URI. The name of the element in this case is invoke; the namespace prefix is jaxm; and the namespace URI is urn:P2PcarRental. The following is how this new element looks like in XML format:

 <jaxm:invoke xmlns:jaxm="urn:P2PCarRental"/>  

You have created the new element. Now just add the new element to the SOAP Body. The addChildElement method of the SOAPBody class does this job for you.

The following is the complete XML structure that you have just authored:

 <soap-env:Envelope      xmlns:soap-env=http://schemas.xmlsoap.org/soap/envelope/">     <soap-env:Header/>     <soap-env:Body>         <jaxm:invoke xmlns:jaxm="urn:P2PCarRental"/>     </soap-env:Body> </soap-env:Envelope> 

We have authored the SOAP request that we want to send to the remote SOAP server. It is time to connect to the SOAP server.

Connecting to a SOAP server using JAXM is a three-step procedure:

  1. Create an end point by specifying the URL of the SOAP server. The following line of code accomplishes this by using the URLEndpoint constructor:

     URLEndpoint soapServerAddress = new URLEndpoint( "http://localhost:8080/soap/servlet/ graphics/ccc.gifrpcrouter");  

    Note

    We tested all this code with an Apache SOAP server deployed on a Tomcat Web server. The SOAP server address used previously (http://localhost:8080/soap/servlet/rpcrouter) is the address of the local Apache SOAP server on our machine. You may want to specify some remote SOAP server over the Internet.

  2. Create a new instance of SOAPConnectionFactory:

     SOAPConnectionFactory connectionFactory = SOAPConnectionFactory.newInstance();  
  3. Call the createConnection method of the newly instantiated SOAPConnectionFactory:

     SOAPConnection connection = connectionFactory.createConnection();  

You are now ready to send the SOAP request over this connection. The following code sends your request synchronously to the remote server:

 SOAPMessage soapResponse = connection.call(request, soapServerAddress);  

Notice that it is a synchronous request, so SOAPConnection.call method will return only when the SOAP server responds.

The SOAP response is a SOAPMessage object. Recall that our request was also a SOAPMessage object. Therefore, to process this SOAP response, you can follow the same sequence of getSOAPPart, getEnvelope, and getBody methods that we explained earlier while authoring the SOAP request.

We have summed up all this code in Listing 12.10 as a simple Java program named JAXMSOAPClient, which is a simple JAXML-based SOAP client. To compile and execute this application , you will need the following JAR files in your classpath: jaxm.jar, dom4j.jar, mail.jar, and client.jar.

Listing 12.10 JAXMSOAPClient
 import java.io.*; import javax.xml.soap.*; import javax.xml.messaging.*; import java.net.URL; import javax.mail.internet.*; import javax.xml.transform.*; import javax.xml.transform.stream.*; import org.dom4j.*; public class JAXMSOAPClient{         public static void main(String args[]) {         try {             //Author a SOAP request.             MessageFactory messageFactory = MessageFactory.newInstance();             SOAPMessage request = messageFactory.createMessage();             SOAPPart soapPartOfRequest = request.getSOAPPart();             SOAPEnvelope soapEnvelope = soapPartOfRequest.getEnvelope();             SOAPBody soapBody = soapEnvelope.getBody();             Name methodName = soapEnvelope.createName( "invoke" , "jaxm", "urn: graphics/ccc.gifP2PCarRental");             soapBody.addChildElement(methodName);             //Add code for SOAP Header authoring here.             //Establish the SOAP connection.             URLEndpoint soapServerAddress = new URLEndpoint( "http://localhost:8080/soap/ graphics/ccc.gifservlet/rpcrouter");             SOAPConnectionFactory connectionFactory = SOAPConnectionFactory.newInstance();             SOAPConnection connection = connectionFactory.createConnection();             //Display the request.             System.out.println();             System.out.println("Sending SOAP request:");             request.writeTo(System.out);             System.out.println();             //Send the request and wait for the response.             SOAPMessage soapResponse = connection.call(request, soapServerAddress);             //We have received the response. Display it.             System.out.println();             System.out.println("Received reply from: "+soapServerAddress);             soapResponse.writeTo(System.out);             //Job done. Close the connection.             connection.close();         } catch(Throwable e) {             e.printStackTrace();         }//catch     }//main }//class 

Using JAXM for SOAP Header Authoring

We'll now show how to author a SOAP Header and add it to a SOAP message. The following is how the completed SOAP message will look after authoring is complete:

 <soap-env:Envelope      xmlns:soap-env=http://schemas.xmlsoap.org/soap/envelope/">     <soap-env:Header>         <sh:sampleHeader xmlns:sh=http://sampleNamespace.com/>     </soap-env:Header>     <soap-env:Body>         <jaxm:invoke xmlns:jaxm="urn:P2PCarRental"/>     </soap-env:Body> </soap-env:Envelope> 

The following lines of JAXM code will author the preceding SOAP message:

 SOAPHeader soapHeader = soapEnvelope.getHeader();  Name soapHeaderName = soapEnvelope.createName( "sampleHeader", "sh", "http:// graphics/ccc.gifsampleNamespace.com"); soapHeader.addHeaderElement(soapHeaderName); 

You can add the lines of code shown here just after authoring the SOAP request message and before establishing the SOAP connection in Listing 12.10.

The first line in this code obtains a reference to the SOAP Header element. Recall that you used the getBody method of the SOAPEnvelope class to obtain a reference to the SOAP Body. Similarly, you will now use the getHeader method of the SOAPEnvelope class to obtain a reference to the SOAP Header.

The second line creates a new sampleHeader element with the fictitious namespace http://sampleHeaderName.com. The third line of code simply adds the sampleHeader element to the SOAP Header.

This is a generic procedure to author any Header. The actual element names and namespace declaration will depend on the protocol that you wish to support through the SOAP Header.

Using JAXM Providers and Profiles

This section describes the use of JAXM providers and profiles. The use of a JAXM provider enables asynchronous communication, which means you will hand your message over to the provider and will not wait for the response. The provider will take care of routing and delivery and will inform you upon receipt of the response.

The JAXM profile is used to author preconfigured SOAP Headers confirming to a specific SOAP-based protocol (such as the ebXML Message Service Specification).

The JAXM providers only work inside J2EE or servlet containers. They cannot work alone, so if you are designing a standalone client, you cannot use a JAXM provider.

Your application will use the following steps to make use of the JAXM providers and profiles:

  1. Look for a provider connection factory in a JNDI-based naming service and create a connection with the provider using the ProviderConnectionFactory. createConnection method. The createConnection method returns an instance of the ProviderConnection class.

    An alternative way is to use the default provider connection (without the JNDI lookup) using the ProviderConnectionFactory.newInstance method. After calling the newInstance method, you will also call the ProviderConnectionFactory.createConnection to create the connection (a ProviderConnection instance) on the default ProviderConnectionFactory.

  2. Check for supported profiles and create a message factory using the profile of your choice.

  3. Include the routing and destination information in the message.

  4. Author the message, and optionally the SOAP Header as well (if you want to include something in the Header not supported by your JAXM profile).

  5. Hand the message over to the provider.

You might have noticed that these steps do not include any action about receiving messages. How will you implement the message receiving logic in your application? We'll make use of the OnewayListener interface to receive messages asynchronously. Let's see how all of this is accomplished.

We will use a sample application called soaprp to demonstrate these steps. The soaprp sample application comes bundled with the JAXM version 1.0 Reference Implementation. It's a WAR file that can be deployed directly on a J2EE or servlet container such as Tomcat.

You might want to see what this application does before going into the technical details. Deploying this application on Tomcat involves nothing more than copying the soaprp.war file in the webapps directory after you have successfully installed JAXM, for which you will find comprehensive instructions in the documentation accompanying the Reference Implementation.

If you deploy the soaprp application on your container and access it through a normal Web browser, you will see the following message on the browser window:

 This is an example of a roundtrip JAXM message exchange via the  remote provider.. Click here to send the message 

The message will contain a hyperlink. Click on the hyperlink and the message will be delivered to the provider, and in turn sent to its destination. You will also notice that the JAXM-based recipient of the message has some message-receiving logic that reported the receipt of the incoming message on the System.out console of your container.

How soaprp Uses JAXM

You can unzip the soaprp.war file using any unzipping tool. Look for the src folder that contains the source code for this application. You will find two JavaBeans inside: SendingServlet.java and ReceivingServlet.java.

SendingServlet is responsible for authoring messages and handing them over to the provider. ReceivingServlet demonstrates the use of the OnewayListener interface that's responsible for receiving messages. This is a simple and generic arrangement that you can use to build your own messaging logic.

Look at the SendingServlet JavaBean, which extends the HttpServlet class. The most interesting part is in the doGet method, where you will look for the profile of your interest and create the message factory with it. Look at the following code extract from the sample application (mf is a MessageFactory instance, and pc is a ProviderConnection instance in the following code):

 if (mf == null) {      ProviderMetaData metaData = pc.getMetaData();     String[] supportedProfiles = metaData.getSupportedProfiles();     String profile = null;     for(int i=0; i < supportedProfiles.length; i++) {         if(supportedProfiles[i].equals("soaprp")) {             profile = supportedProfiles[i];             break;         }//if     }//for     mf = pc.createMessageFactory(profile); }//if // Create a message from the message factory. SOAPRPMessageImpl soaprpMsg = (SOAPRPMessageImpl)mf.createMessage(); 

The if (mf==null) block is only meant to create the required message factory by selecting the correct profile. When you have the message factory, you can create the message the same way you created it in Listing 12.10. However, this time you will store the message in a SOAPRPMessageImpl object, which represents the profile-specific message format with the correct SOAP Header.

The rest is logically the same as in Listing 12.10, except that you will use the ProviderConnection.send method instead of the SOAPConnection.call method to send the message. The send and call methods differ from each other in the sense that send is asynchronous, or one-way (meaning it returns immediately without waiting for the response), whereas call is synchronous (meaning it waits and remains blocked until it gets a response).

Now look at the ReceivingServlet.java file. The ReceivingServlet class implements the OnewayListener interface, which consists of only one method, onMessage. This method assumes control upon receipt of an incoming message.



JavaT P2P Unleashed
JavaT P2P Unleashed
ISBN: N/A
EAN: N/A
Year: 2002
Pages: 209

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net