![]() ![]() |
SOAP with Attachments API for Java (SAAJ) is defined to enable applications to take advantage of the SOAP protocol. It defines a Java API for producing, consuming, and manipulating SOAP messages that conform to the SOAP 1.1 specification and SOAP with Attachments note. SAAJ was created as part of the Java API for XML messaging (JAXM) under JSR-67 but was refactored into its own specification, because all the other JAX APIs used it. It made sense to have this common API stand on its own. Let us now take a closer look at SAAJ.
SAAJ provides a level of abstraction that insulates developers from low-level manipulation of angle brackets. Developers create and work with Java classes in the javax.xml.soap package that model different XML elements in a SOAP message and the semantics of connecting and sending SOAP messages.
The API relevant to modeling the SOAP message is shown in Figure 4.7 and explained in Table 4.1.
AttachmentPart |
Models the attachment in a SOAP message. |
MimeHeader |
An object that stores a MIME header name and its value. |
MimeHeaders |
A container for MimeHeader objects, which represent the MIME headers present in a MIME part of a message. |
Node |
The base interface that represents an XML element. Though it is analogous to the Node in the W3C DOM discussed in Chapter 9, it is not the same. |
SOAPBody |
Models the body from a SOAP message. |
SOAPBodyElement |
Represents the contents in a SOAPBody object. |
SOAPElement |
Subclasses Node to provide the base functionality for all classes that represent SOAP objects defined in the SOAP specification. |
SOAPEnvelope |
Models the envelope in a SOAP message. |
SOAPFault |
Models a fault and is contained in a SOAPBody object. |
SOAPFaultElement |
A representation of the contents in a SOAPFault object. |
SOAPHeader |
Models the header element of the SOAP message |
SOAPHeaderElement |
Models individual header elements in a SOAPHeader. |
SOAPMessage |
The root class for all SOAP messages. |
SOAPPart |
The container for the SOAP-specific portion of a SOAPMessage object. |
Each part of the SOAP message discussed in this chapter is modeled in SAAJ as a Java class or interface developers can work with in their code. Though Figure 4.7 is self-explanatory, there are two other classes in SAAJ are important. Like the rest of the API that abstracts the SOAP message, these classes abstract the semantics relating to a request-response-based transmission of the message:
MessageFactory. This class is responsible for creating empty SOAPMessage objects.
SOAPConnection. This class abstracts a connection between two nodes. A SOAP client can create a SOAPConnection object from a SOAPConnection-Factory and dispatch the SOAPMessage using the call() method, which takes two arguments: the SOAPMessage to send and a destination for the message. The destination is abstracted by the javax.xml.messaging.URLEndpoint class.
SOAPConnectionFactory: This is a factory for creating SOAPConnection objects.
To understand how SAAJ works, let us put everything together with an example of this API in action. The BillPay service exposes a Java method with the following syntax:
PaymentConfirmation schedulePayment(Date date, String nickName, doubleamount);
Listing 4.6 shows the SOAP request this Web service expects. We will put aside the part about how the service is implemented until Chapter 11. Listing 4.7 shows the SAAJ code, and Listing 4.8 shows the SOAP response that the service returns. The client code takes the following sequence:
Instantiate the MessageFactory.
Create an empty SOAPMessage from the factory.
Access the SOAPEnvelope from the message.
Access the SOAPBody from the envelope.
Create the elements in the body and save the changes to the message.
Create a SOAPConnection object from a SOAPConnectionFactory.
Send the SOAPMessage to the endpoint, using the connection.
![]() |
<?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns0="http://www.flutebank.com/xml" env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <env:Body> <ns0:schedulePayment> <Date_1 xsi:type="xsd:dateTime">2002-10-05T04:49:26.769Z</Date_1> <String_2 xsi:type="xsd:string">my account at sprint</String_2> <double_3 xsi:type="xsd:double">190.0</double_3> </ns0:schedulePayment> </env:Body> </env:Envelope>
![]() |
![]() |
import javax.xml.soap.*; import java.util.Iterator; import java.util.Date; import java.text.SimpleDateFormat; import javax.xml.messaging.URLEndpoint; public class SAAJClient{ /** Class to demonstrate how to send a soap message synchronously with SAAJ API. */ public static void main(String args[]) throws Exception { String url = "http://127.0.0.1:9090/billpayservice/jaxrpc/BillPay"; if (args.length > 0) url = args[0]; // Construct a default SOAP message factory. MessageFactory mfactory = MessageFactory.newInstance(); // Create an empty message SOAPMessage message = mfactory.createMessage(); SOAPPart soap = message.getSOAPPart(); // Access the envelope SOAPEnvelope envelope = soap.getEnvelope(); envelope.addNamespaceDeclaration("xmlns:xsd"," http://www.w3.org/2001/ XMLSchema"); envelope.addNamespaceDeclaration("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" ); envelope.addNamespaceDeclaration("xmlns:ns0"," http://www.flutebank.com/xml" ); envelope.setEncodingStyle("http://schemas.xmlsoap.org/soap/encoding/"); // Access the body SOAPBody body = envelope.getBody(); Name name = envelope.createName("schedulePayment", "ns0", "http://www.flutebank.com/xml"); SOAPBodyElement element = body.addBodyElement(name); // create a name for the attribute name that can be reused Name xsitype = envelope.createName("xsi:type"); // create the Date_1 element Name dateelement = envelope.createName("Date_1"); SOAPElement date = element.addChildElement(dateelement); date.addAttribute(xsitype," xsd:dateTime"); // Format the Java Date object in the syntax that is compliant with the XML schema SimpleDateFormat dateFormatter new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); String xmldate=dateFormatter.format(new Date()).toString(); date.addTextNode(xmldate); // create the String_2 element Name strelement = envelope.createName("String_2"); SOAPElement str = element.addChildElement(strelement); str.addAttribute(xsitype," xsd:string"); str.addTextNode("my account at string"); // create the double_3 element name dblelement = envelope.createName("double_3"); SOAPElement dbl = element.addChildElement(dblelement); dbl.addAttribute(xsitype," xsd:double"); dbl.addTextNode("190.0"); // save changes to the message message.saveChanges(); // Construct a default SOAP connection factory. SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance(); // Get SOAP connection. SOAPConnection connection = factory.createConnection(); // Construct endpoint object. URLEndpoint endpoint = new URLEndpoint(url); // Send SOAP message. SOAPMessage response = connection.call(message, endpoint); // process the return message SOAPPart sp = response.getSOAPPart(); SOAPEnvelope se = sp.getEnvelope(); SOAPBody sb = se.getBody(); Iterator it = sb.getChildElements(); while (it.hasNext()) { SOAPBodyElement bodyElement = (SOAPBodyElement)it.next(); System.out.println(bodyElement.getElementName().getQualifiedName() + " namepace uri="+bodyElement.getElementName().getURI()); Iterator it2 = bodyElement.getChildElements(); while (it2.hasNext()) { SOAPElement element2 = (SOAPElement)it2.next(); System.out.print(element2.getElementName().getQualifiedName() +" = "); System.out.println(element2.getValue()); } } //Debug method, Print response to the std output System.out.println("\n\n\n Dumping complete message \n\n---------------\n\n"); response.writeTo(System.out); // close the connection connection.close(); } }
![]() |
![]() |
<?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns0="http://www.flutebank.com/xml" env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <env:Body> <ns0:schedulePaymentResponse> <result href="#ID1"/> </ns0:schedulePaymentResponse> <ns0:PaymentConfirmation id="ID1" xsi:type="ns0:PaymentConfirmation"> <confirmationNum xsi:type="xsd:int">81263767</confirmationNum> <payee xsi:type="xsd:string">Sprint PCS</payee> <amt xsi:type="xsd:double">190.0</amt> </ns0:PaymentConfirmation> </env:Body> </env:Envelope>
![]() |
Though we have seen how a SOAP request and response can be constructed and sent using SAAJ, the preceding example was meant more as an insight into the workings of SAAJ. We don't envision direct use of this API by developers, because it is unlikely visual inspection of a SOAP request would be necessary. Other APIs, such as JAXM and JAX-RPC, abstract away this usage with higher-level constructs and with tools to interpret the SOAP service descriptions in a WSDL file. SAAJ is more likely to form the underpinnings of these high-level constructs in different vendor implementations. We will talk more about SAAJ and this type of request-response communication in Chapter 11.
![]() ![]() |