Skip Navigation Links | |
Exit Print View | |
Oracle GlassFish Server Message Queue 4.5 Developer's Guide for Java Clients |
3. Message Queue Clients: Design and Features
4. Using the Metrics Monitoring API
SOAP with Attachments API for Java
The Language Implementation Layer
Using Namespaces when Creating a SOAP Name
Destination, Message Factory, and Connection Objects
Using the Endpoint to Address a Message
SOAP Messaging Models and Examples
SOAP Messaging Programming Models
To Create and Add an Attachment
Integrating SOAP and Message Queue
Example 1: Deferring SOAP Processing
To Transform the SOAP Message into a JMS Message and Send the JMS Message
To Receive the JMS Message, Transform it into a SOAP Message, and Process It
Example 2: Publishing SOAP Messages
6. Embedding a Message Queue Broker in a Java Client
This section explains how you use SAAJ to send and receive a SOAP message. It is also possible to construct a SOAP message using SAAJ and to send it as the payload of a JMS message. For information, see Integrating SOAP and Message Queue.
This section provides a brief summary of the programming models used in SOAP messaging using SAAJ.
A SOAP message is sent to an endpoint by way of a point-to-point connection (implemented by the SOAPConnection class).
You use point-to-point connections to establish a request-reply messaging model. The request-reply model is illustrated in Figure 5-6.
Figure 5-6 Request-Reply Messaging
Using this model, the client does the following:
Creates an endpoint that specifies the URL that will be passed to the SOAPConnection.call method that sends the message.
See Endpoint for a discussion of the different ways of creating an endpoint.
Creates a SOAPConnection factory and obtains a SOAP connection.
Creates a message factory and uses it to create a SOAP message.
Creates a name for the content of the message and adds the content to the message.
Uses the SOAPConnection.call method to send the message.
It is assumed that the client will ignore the SOAPMessage object returned by the call method because the only reason this object is returned is to unblock the client.
The SOAP service listening for a request-reply message uses a ReqRespListener object to receive messages.
For a detailed example of a client that does point-to-point messaging, see Writing a SOAP Client.
If a message contains any data that is not XML, you must add it to the message as an attachment. A message can have any number of attachment parts. Each attachment part can contain anything from plain text to image files.
To create an attachment, you must create a URL object that specifies the location of the file that you want to attach to the SOAP message. You must also create a data handler that will be used to interpret the data in the attachment. Finally, you need to add the attachment to the SOAP message.
To create and add an attachment part to the message, you need to use the JavaBeans Activation Framework (JAF) API. This API allows you to determine the type of an arbitrary piece of data, encapsulate access to it, discover the operations available on it, and activate a bean that can perform these operations. You must include the activation.jar library in your application code in order to work with the JavaBeans Activation Framework.
URL url = new URL("http://wombats.com/img.jpg");
DataHandler dh = new DataHandler(url);
AttachmentPart ap1 = message.createAttachmentPart(dh);
myMessage.addAttachmentPart(ap1);
After creating the attachment and adding it to the message, you can send the message in the usual way.
If you are using JMS to send the message, you can use the SOAPMessageIntoJMSMessage conversion utility to convert a SOAP message that has an attachment into a JMS message that you can send to a JMS queue or topic using Message Queue.
A SOAP application can use two error reporting mechanisms: SOAP exceptions and SOAP faults:
Use a SOAP exception to handle errors that occur on the client side during the generation of the SOAP request or the unmarshalling of the response.
Use a SOAP fault to handle errors that occur on the server side when unmarshalling the request, processing the message, or marshalling the response. In response to such an error, server-side code should create a SOAP message that contains a fault element, rather than a body element, and then it should send that SOAP message back to the originator of the message. If the message receiver is not the ultimate destination for the message, it should identify itself as the soapactor so that the message sender knows where the error occurred. For additional information, see Handling SOAP Faults.
The following steps show the calls you have to make to write a SOAP client for point-to-point messaging.
SOAPConnectionFactory myFct = SOAPConnectionFactory.newInstance();
SOAPConnection myCon = myFct.createConnection();
The myCon object that is returned will be used to send the message.
MessageFactory myMsgFct = MessageFactory.newInstance();
SOAPMessage message = myMsgFct.createMessage();
The message that is created has all the parts that are shown in Figure 5-7.
Figure 5-7 SOAP Message Parts
At this point, the message has no content. To add content to the message, you need to create a SOAP body element, define a name and content for it, and then add it to the SOAP body.
Remember that to access any part of the message, you need to traverse the tree, calling a get method on the parent element to obtain the child. For example, to reach the SOAP body, you start by getting the SOAP part and SOAP envelope:
SOAPPart mySPart = message.getSOAPPart(); SOAPEnvelope myEnvp = mySPart.getEnvelope();
SOAPBody body = myEnvp.getBody();
The children that you will add to the body element define the content of the message. (You can add content to the SOAP header in the same way.)
Name bodyName = envelope.createName("GetLastTradePrice", "m", "http://eztrade.com") SOAPBodyElement gltp = body.addBodyElement(bodyName);
Name myContent = envelope.createName("symbol"); SOAPElement mySymbol = gltp.addChildElement(myContent);
mySymbol.addTextNode("SUNW");
The resulting SOAP message object is equivalent to this XML scheme:
<SOAP-ENV: Envelope xmlns:SOAPENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <m:GetLastTradePrice xmlns:m="http://eztrade.com"> <symbol>SUNW</symbol> </m:GetLastTradePrice> </SOAP-ENV:Body> </SOAP-ENV: Envelope>
message.saveChanges();
URLEndpoint endPt = new URLEndpoint("http://eztrade.com//quotes");
SOAPMessage reply = myCon.call(message, endPt);
The reply message (reply) is received on the same connection.
myCon.close();
A SOAP service represents the final recipient of a SOAP message and should currently be implemented as a servlet. You can write your own servlet or you can extend the JAXMServlet class, which is furnished in the soap.messaging package for your convenience. This section describes the task of writing a SOAP service based on the JAXMServlet class.
Your servlet must implement either the ReqRespListener or OneWayListener interfaces. The difference between these two is that ReqRespListener requires that you return a reply.
Using either of these interfaces, you must implement a method called onMessage(SOAPMsg). JAXMServlet will call onMessage after receiving a message using the HTTP POST method, which saves you the work of implementing your own doPost() method to convert the incoming message into a SOAP message.
Example 5-2 shows the basic structure of a SOAP service that uses the JAXMServlet utility class.
Example 5-2 Skeleton Message Consumer
public class MyServlet extends JAXMServlet implements ReqRespListener { public SOAPMessage onMessage(SOAP Message msg) { //Process message here } }
Example 5-3 shows a simple ping message service:
Example 5-3 A Simple Ping Message Service
public class SOAPEchoServlet extends JAXMServlet implements ReqRespListener{ public SOAPMessage onMessage(SOAPMessage mySoapMessage) { return mySoapMessage } }
Table 5-2 describes the methods that the JAXM servlet uses. If you were to write your own servlet, you would need to provide methods that performed similar work. In extending JAXMServlet , you may need to override the Init method and the SetMessageFactory method; you must implement the onMessage method.
Table 5-2 JAXMServlet Methods
|
The onMessage method needs to disassemble the SOAP message that is passed to it by the servlet and process its contents in an appropriate manner. If there are problems in the processing of the message, the service needs to create a SOAP fault object and send it back to the client as described in Handling SOAP Faults.
Processing the SOAP message may involve working with the headers as well as locating the body elements and dealing with their contents. The following code sample shows how you might disassemble a SOAP message in the body of your onMessage method. Basically, you need to use a Document Object Model (DOM) API to parse through the SOAP message.
See http://xml.coverpages.org/dom.html for more information about the DOM API.
Example 5-4 Processing a SOAP Message
{http://xml.coverpages.org/dom.html SOAPEnvelope env = reply.getSOAPPart().getEnvelope(); SOAPBody sb = env.getBody(); // create Name object for XElement that we are searching for Name ElName = env.createName("XElement"); //Get child elements with the name XElement Iterator it = sb.getChildElements(ElName); //Get the first matched child element. //We know there is only one. SOAPBodyElement sbe = (SOAPBodyElement) it.next(); //Get the value for XElement MyValue = sbe.getValue(); }
A SOAP message may have attachments. For sample code that shows you how to create and add an attachment, see Code Samples. For sample code that shows you how to receive and process an attachment, see Code Samples.
In handling attachments, you will need to use the Java Activation Framework API. See http://java.sun.com/products/javabeans/glasgow/jaf.html for more information.
In replying to messages, you are simply taking on the client role, now from the server side.
Server-side code must use a SOAP fault object to handle errors that occur on the server side when unmarshalling the request, processing the message, or marshalling the response. The SOAPFault interface extends the SOAPBodyElement interface.
SOAP messages have a specific element and format for error reporting on the server side: a SOAP message body can include a SOAP fault element to report errors that happen during the processing of a request. Created on the server side and sent from the server back to the client, the SOAP message containing the SOAPFault object reports any unexpected behavior to the originator of the message.
Within a SOAP message object, the SOAP fault object is a child of the SOAP body, as shown in the figure below. Detail and detail entry objects are only needed if one needs to report that the body of the received message was malformed or contained inappropriate data. In such a case, the detail entry object is used to describe the malformed data.
Figure 5-8 SOAP Fault Element
The SOAP Fault element defines the following four sub-elements:
faultcode
A code (qualified name) that identifies the error. The code is intended for use by software to provide an algorithmic mechanism for identifying the fault. Predefined fault codes are listed in Table 5-3. This element is required.
faultstring
A string that describes the fault identified by the fault code. This element is intended to provide an explanation of the error that is understandable to a human. This element is required.
faultactor
A URI specifying the source of the fault: the actor that caused the fault along the message path. This element is not required if the message is sent to its final destination without going through any intermediaries. If a fault occurs at an intermediary, then that fault must include a faultactor element.
detail
This element carries specific information related to the Body element. It must be present if the contents of the Body element could not be successfully processed. Thus, if this element is missing, the client should infer that the body element was processed. While this element is not required for any error except a malformed payload, you can use it in other cases to supply additional information to the client.
The SOAP specification lists four predefined faultcode values. The namespace identifier for these is http://schemas.xmlsoap.org/soap/envelope/.
Table 5-3 SOAP Faultcode Values
|
These standard fault codes represent classes of faults. You can extend these by appending a period to the code and adding an additional name. For example, you could define a Server.OutOfMemory code, a Server.Down code, and so forth.
Using SAAJ you can specify the value for faultcode, faultstring, and faultactor using methods of the SOAPFault object. The following code creates a SOAP fault object and sets the faultcode, faultstring, and faultactor attributes:
SOAPFault fault; reply = factory.createMessage(); envp = reply.getSOAPPart().getEnvelope(true); someBody = envp.getBody(); fault = someBody.addFault(): fault.setFaultCode("Server"); fault.setFaultString("Some Server Error"); fault.setFaultActor(http://xxx.me.com/list/endpoint.esp/) reply.saveChanges();
The server can return this object in its reply to an incoming SOAP message in case of a server error.
The next code sample shows how to define a detail and detail entry object. Note that you must create a name for the detail entry object.
SOAPFault fault = someBody.addFault(); fault.setFaultCode("Server"); fault.setFaultActor("http://foo.com/uri"); fault.setFaultString ("Unkown error"); Detail myDetail = fault.addDetail(); detail.addDetailEntry(envelope.createName("125detail", "m", "Someuri")).addTextNode("the message cannot contain the string //"); reply.saveChanges();