Sharing structured data

XML Magazine

Subscribe to XML Magazine: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get XML Magazine: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


XML Authors: Peter Silva, Stackify Blog, Mamoon Yunus, Progress Blog, XebiaLabs Blog

Related Topics: Java EE Journal, XML Magazine

J2EE Journal: Article

XML Messaging with JAXM Part 2

XML Messaging with JAXM Part 2

Part 1 of this article looked at the JAXM API and some of the components you can use to send messages synchronously. But the JAXM API offers more features, such as the ability to send and receive messages asynchronously. To make the JAXM API easier to use in your applications, there is also a set of custom JSP tags.

Communications in enterprise applications are rarely only synchronous in nature. Some applications send a request and don't expect an immediate response. Applications that send a request and receive a response at a later time are said to be asynchronous in nature. This ability to "fire-and-forget" is a common practice in distributed applications.

An asynchronous JAXM client uses a messaging provider to send messages to instead of sending them directly to the recipient. A messaging provider is somewhat similar to a JMS queue. The difference is that, with a JMS queue, messages may not be delivered automatically to the recipient, depending on the type of queue and messaging model used. With a SOAP messaging provider, the messages are forwarded to the recipient automatically. There are provisions for handling retries should a message recipient be unavailable. This enables some rudimentary form of reliable messaging, as messages can be persisted to disk in a directory until they can be delivered. This could take several hours to several days.

When you send messages using a messaging provider, you also create messages and connections differently from when you send messages directly to a recipient. When you want to create a message, you still use the MessageFactory class, but you get a reference to the MessageFactory class from an object called a ProviderConnection.

The ProviderConnection Object
To get a ProviderConnection object, you first have to obtain a reference to a ProviderConnectionFactory, which is responsible for creating ProviderConnection objects that are retrieved using the JNDI (Java Naming and Directory Interface). The ProviderConnectionFactory is found at the URL where it has been registered. The following snippet illustrates how you can retrieve an instance of a ProviderConnection object.

Context ctx = new InitialContext();
ProviderConnectionFactory pcf =
(ProviderConnectionFactory)ctx.lookup
("http://www.yourprovider.com/provider");
ProviderConnection pc = pcf.createConnection();
The first line of code, which retrieves a Context object, is used by applications that will use JNDI operations such as the lookup() method in the next line of code. This method is used to obtain a reference to the ProviderConnectionFactory object that you'll use to create a connection. The URI you provide to the lookup() method must be bound by some other means before you attempt to use it. Usually JNDI names are bound by the objects that need to be located by the JNDI name in question. If you've written code that uses RMI or EJBs, the preceding code may look familiar. Remote objects are looked up and accessed in a similar way.

Once you have an instance of the ProviderConnection object, you're ready to create the MessageFactory from which you'll create SOAPMessage objects. To create a MessageFactory using the ProviderConnection object you'll use code that looks like the following:

MessageFactory messageFactory = pc.createMessageFactory("XMLJournal")

The createMessageFactory() method is called to create a MessageFactory instance, unlike previous examples where you used the newInstance() method. You pass in a single argument representing the name of a profile for a MessageFactory that creates a certain type of message.

Once you've created the desired message type, you can go about populating the message. Depending on the message profile retrieved, you set different parts of the message to meet your needs. For instance, if you were creating a basic SOAP message, you might execute code that looks like:

SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = soapPart.getEnvelope(true);

SOAPBody soapBody = soapEnvelope.getBody();
soapBody.addTextNode("XML Journal");

You could also subclass the SOAPMessage class and create message classes that are unique to your own message. The JAXM reference implementation, for example, includes an ebXML message class. You would of course need to have the implementation of the class on the sending and receiving ends.

Having set the content of the message the way you want it, you can now send it. Sending a message using a messaging provider looks like:

pc.send(soapMessage);
pc.close();

The send() method takes an instance of a SOAPMessage class. After the send() method returns, you should call the close() method to close the connection with the provider. Listing 1 shows the source code for a JAXM client application that sends a message asynchronously.

Unlike a message sent directly to a recipient, a message sent to a recipient via a provider involves knowing only the name of the profile. This hides many details of the recipient and can be somewhat confusing if you know nothing about the recipient, but it's also good in that you don't have to know the details. The messaging provider is responsible for delivering the message and knowing about the address of the recipient. The JAXM specification defines a construct known as a message profile.

Message Profiles
Profiles are used with JAXM clients that use a messaging provider, unlike JAXM clients that talk directly to the client using a SOAPConnection. Profiles are used to describe information about a particular message type Ð in the case of the JAXM API, a sample XML-Journal message profile is provided. You could also create your own custom profile to describe other types of messages.

A list of supported profiles can be retrieved from a messaging provider by using the getSupportedProfiles() method of the ProviderMetaData object. You can retrieve an instance of the ProviderMetaData object from the ProviderConnection object using the getMetaData() method of the ProviderConnection object. To do this you'd use code that looks like this:

ProviderMetaData metaDat = pc.getMetaData();
String[] supportedProfiles = metaData.getSupportedProfiles();
The getSupportedProfiles() method returns a String array of the profiles it knows about. You can then look through them to find which profiles it supports. Message profiles are created at runtime by loading an XML file containing information about the profile. The JAXM specification defines a DTD that indicates what the profile should look like. A message profile consists of, for example:
  • Where the messaging provider should store messages persistently
  • How many times the message provider should attempt to forward a message
  • What URI a client should use to contact the provider
  • What transport protocol you should use to contact the provider
  • How many messages are stored persistently in one file
The message profile is contained in an XML document that's loaded at runtime by a messaging provider. The document contains one or more profiles that describe the previously mentioned information as well as some other pieces of information about the profile. A message profile might look the one in Listing 2.

This profile defines the XML-Journal message profile. It can be found at www.xmljournal/com/sender using HTTP. The provider will store messages in a directory called xmljournal and place up to 10 messages in each message log file. These messages represent the messages that will be sent to the recipient.

JAXM clients that use a messaging provider must also be configured with a similar profile about the messaging provider. The JAXM specification also defines a DTD for these clients. The client configuration is XML-based as well, of course, and provides the client with the following information:

  • An endpoint identifying the client
  • A URL that the provider can send pending messages to
  • A URL that the client can use to contact the provider
Reading in and utilizing profiles isn't covered in the current reference implementation, but at least one of the examples that ships with the reference implementation uses profiles.

One thing you should note is that clients that use messaging providers should be able to process messages asynchronously. A provider can deliver messages to a client at any time, which is in sharp contrast to the JAXM client you saw earlier, which sent a message and received a response synchronously. The client wouldn't be able to send a message, close the connection, and then later receive a message from a provider on a different connection. You have clients that send messages to other clients that are later delivered by the provider.

The JAXM API defines the JAXMServlet class as a convenience class for writing JAXM clients that run in a servlet container. This enables a JAXM client to make use of the facilities of the servlet container. You don't need any additional infrastructure such as a Web server or HTTP message-handling classes.

The API also defines two interfaces; AsyncListener and SyncListener, that are generally used by JAXM clients written as servlets. Both interfaces and the JAXMServlet class reside in the javax.xml.messaging package.

Both the SyncListener and AsyncListener define an onMessage() method that takes a SOAPMessage object as the single argument. The SyncListener implementation of onMessage() also returns an instance of a SOAPMessage object as the response. Listing 3 shows the source for a Java servlet that can act as an asynchronous SOAP message listener.

Servlets that implement the AsyncListener interface operate similarly to message-driven beans in J2EE applications. The EJB container handles forwarding the message to the MDB in the same way that the messaging provider handles forwarding the HTTP request to the JAXM client receiving the message. I would't be surprised to see JAXM become a standard component of J2EE.

Writing lots of Java code to use JAXM isn't a requirement of using JAXM. In fact, if you primarily use JSPs in parts of your application, you can then make use of JAXM without writing a lot of the code you've seen previously.

JAXM JSP Custom Tags
Writing JAXM applications can also be done using a custom JSP tag library that's included with the API. The tag library defines a number of custom tags that encapsulate the functionality you've seen in Part 1 and the first part of this article. These tags enable you to send messages, access the contents of SOAP messages, and receive a message asynchronously. These tags take care of the necessary details of transforming an HTTP POST request into a SOAP message so you can work with it. It also enables you to formulate a SOAP message request or response and send it to a recipient.

If you're unfamiliar with custom tags, they encapsulate program logic into an XML-like element. The custom tag is used on a Java Server Page; when the page is run, the tag is executed and performs some action, possibly inserting new content dynamically into the output of the JSP where the tag was defined. Table 1 shows all the tags and a brief description of each.

Before discussing each tag, let's examine how to install the tag library these tags are a part of. What follows assumes the use of the Tomcat server, but any J2EE-compliant application server or servlet container should work just as well.

To use each tag requires that your JSP can find the tag. To this end, you need to specify the tag library using a declaration that looks like this:

<%@ taglib uri="http://java.sun.com/jaxm" prefix="jaxm" %>

Deploying the JAXM WAR
The JAXM custom tags and library are packaged as a Web Application Archive (WAR) named jaxmtags.war. This file can be found in the \jaxm\samples directory of the JAXM distribution. To deploy the tag library in Tomcat, copy the jaxmtags.war file into the \tomcat\webapps directory and then restart Tomcat. Once restarted, the tag library, along with several examples, will be deployed. You can then access a JAXM custom tag example page by visiting this URL with your Web browser:

http://localhost:8080/jaxmtags

The port listed in the command line above may need to be changed, depending on how you've configured the Tomcat Web server. The example page has a few examples you can experiment with to get an idea of what's possible with the tag library.

Now that you have Tomcat up and running and can access the JAXM example page, we'll look at each tag, starting with the <jaxm:context> tag.

A Look at Each Tag
The <jaxm:context> tag is used to initialize the JAXM runtime, set up any message factories, and construct variables that you can use to access the context elsewhere in the page. This tag creates the variables jaxmConnection and jaxmMessageFactory. It also defines a variable named jaxmPageURI that represents the URI of the Web application this JSP is a part of. The <jaxm:context> tag is used at the top of the JSP before any other JAXM-related custom tags.

The <jaxm:onMessage> tag allows you to write JSPs that receive SOAP. If you recall, the onMessage() method is called when an HTTP POST is sent. The SOAP message is in the body of the HTTP message and is extracted and made into an instance of the javax.xml.soap.SOAPMessage class and passed to the recipient. To extract the incoming SOAP message, we need to look at the attributes of the <jaxm:onMessage> tag.

The tag defines three attributes: msgId, which will hold the incoming SOAP message; resId, which will hold the response SOAP message; and useBody, which is used to indicate whether the response SOAP message will be constructed using a scriptlet or the body of the tag. The following snippet illustrates the use of the <jaxm:onMessage> tag.

<%@ taglib uri="http://java.sun.com/jaxm" prefix="jaxm" %>
<jaxm:context/>

<jaxm:onMessage msgId="mId">
<jaxm:soapBody>
<response> Message Received
</jaxm:soapBody>

</jaxm:onMessage>

I haven't specified the useBody attribute in the above example because the default value of this attribute is true, which means you use the body of the tag to define the response.

When you build the response message, you're specifying only the body of the SOAP message, not the entire message, such as the envelope or headers. If I were to dump the SOAP message created with the body of <response> Message Received </response>, it would look like this:

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<response>Message Received</response>
</Body>
</Envelope>
The custom tags take care of building the SOAP <Envelope> and <Body> elements for you.

The <jaxm:call> tag is used to send a SOAP message to an endpoint defined by its endpoint attribute. If you recall from Part 1, the call() method was used by JAXM clients to send messages directly to a recipient. The <jaxm:call> tag defines three attributes: msgId, which is used to hold the request SOAP message; resId, which is used to hold the response to the message; and endPoint, which is used to indicate the URL of the endpoint you're sending the SOAP message to.

The code snippet in Listing 4 illustrates the use of the <jaxm:call> tag to send a message to a JSP named jaxmreceiver.jsp. When using this tag, you can retrieve the response SOAP message by accessing the variable created by the resId attribute. In the previous example the variable sres can be used to access the contents of the response programmatically using the JAXM SOAP classes. Listing 5 shows the source of a JSP that uses the SOAP classes to programmatically access the body of the returned SOAP message.

The section of code that appears within the scriptlet tags <% and %> extracts the SOAPMessage object representing the response by casting the sres variable to a SOAPMessage class. I then proceed to access the various parts of the SOAP message such as the envelope and the body. Once I have the body of the message, I use the getChildElements() method to retrieve an iterator over the child elements in the body of the SOAP message.

The <jaxm:soapBody> tag is used to define the contents of a SOAP message when using the body of the tag instead of a scriptlet to define the content. You use this tag in conjunction with the <jaxm:call> tag to define the contents of the SOAP message you're sending. You also use the tag in conjunction with the <jaxm:onMessage> tag to define the body of the SOAP message you're sending as a response. Following is an example of using the <jaxm:soapBody> tag to define the contents of a response to a SOAP message:

<%@ taglib uri="http://java.sun.com/jaxm" prefix="jaxm" %>
<jaxm:context jndiLookup="Sender"/>

<jaxm:onMessage msgId="mId">
<jaxm:soapBody>
<response> Message Received </response>
</jaxm:soapBody>
</jaxm:onMessage>

The <jaxm:dump> tag will display the raw SOAP message, including the envelope, when given a message ID previously defined on another tag with an msgId attribute. Because you can easily dump the contents of a SOAP message, this tag is useful for debugging. Listing 6 is an example of the <jaxm:dump> tag used to dump a message you've sent and the response you received.

In this example I used the <jaxm:dump> tag to dump the contents of the SOAP request message defined in the sreq variable as well as the response to the message held in the sres variable. The output from using the <jaxm:dump> tag to dump a SOAP message could result in output that looks like this:

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"
xmlns: SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<magazines>
<magazine>XML Journal</magazine>
<magazine> Java Developers Journal </magazine>
<magazine> Web Services Journal </magazine>
</magazines>
</Body>
</Envelope>
The output of using the <jaxm:dump> tag to dump the contents of the response would look nearly identical to that of the request.

Summary
The JAXM API can be used to send messages asynchronously using a messaging provider that acts like a post office, forwarding the message to the recipient and possibly performing retries if the message can't be delivered. The custom tag library that's distributed with the JAXM API is used to incorporate sending SOAP messages using JSPs. There are tags for sending messages, receiving messages asynchronously, and viewing the raw contents of SOAP messages, just to name a few.

Links
For more information about SOAP, XML, and messaging in general, as well as locations for downloading the APIs discussed in this article:

  • Java API for XML messaging: http://java.sun.com/xml/jaxm
  • Simple Object Access Protocol 1.1 (SOAP w/Attachments): www.w3.org/TR/SOAP-Attachments
  • Simple Object Access Protocol 1.1 (SOAP): www.w3.org/TR/SOAP
  • Java Message Service: http://java.sun.com/products/jms/index.html
  • Hypertext Transfer Protocol 1.1: www.w3.org/Protocols/rfc2616/rfc2616.html
  • Java Server Page Tag Libraries: http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags.html
  • Message-driven beans: http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/MDB.html
  • More Stories By Mike Jasnowski

    Mike Jasnowski is a senior software engineer on the BEA WebLogic Server Administration Console team. He has been involved in development for almost 20 years and in many industries. Mike is a contributing author to several books and author of JMX Programming (Wiley)

    Comments (0)

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.