Because SOAP relies on Web services, this Java example is going to be significantly more advanced than the Java examples we've already seen. You can use Java on the Internet in the form of Java servlets or JavaServer Pages, and it'll be easier to use servlets here.
A servlet is a Java application that runs on a Web serversort of the analog of an applet that runs in the client browser. Our example will have two servlets, one that sends the SOAP message and one that receives that message. The receiving servlet will decode the data in the SOAP message and return a new SOAP message indicating that it has understood . Usually you don't see the actual SOAP message directly, but in this case, both the sent and returned SOAP messages will be stored to files so we can take a look at them directly. You'll need a Web server that can run Java servlets for this example. You might not have access to such a Web server on the Internet, but that's not a problemyou can run one right on your own computer: the Tomcat server. Tomcat is the premier Web server for JavaServer Pages and servlets, and you can download it from http://jakarta.apache.org/tomcat/. The current version is version 4. Downloading and installing Tomcat is really not as hard as it sounds, even though you're installing a full Web server on your computer. Take a look at the installation directions that come with Tomcat. After you've gotten Tomcat installed and running (all the information you need comes with the Tomcat documentation), navigate to http://localhost:8080/index.html . (Tomcat uses port 8080, so it won't conflict with other local servers.) You should see Tomcat running, something like in Figure 18-1. Figure 18-1. Running the Tomcat server.
In addition, you'll need some added support from Java. As we've seen, Java 1.4 comes with considerable XML support. However, the standard edition doesn't come with support to create XML Web services. A considerable amount of Java support exists for Web services, howevertake a look at http://java.sun.com/ webservices / for the details. You have two options to start using SOAP with Java: You can download the Java XML Pack, which is currently at http://java.sun.com/xml/downloads/javaxmlpack.html, or you can download the Java Web Services Developer's Pack, which is currently at http://java.sun.com/webservices/webservicespack.html. The Java XML Pack is the smaller of these two and is a simple zipped file that holds the JAR files you'll need: jaxm-api.jar, saaj-api.jar, and activation.jar. You'll also need servlet.jar to create servlets, and it comes with Tomcat (in the Tomcat lib directory). You'll need to set up Tomcat to work with Java XML Messaging, or JAXM. Stop Tomcat if it's running and copy jaxm-docs.war, which comes with the Java XML Pack or the Java Web Services Developer's Pack, to the Tomcat webapps directory. Then restart Tomcat and navigate to http://localhost:8080/jaxm-docs/tomcat.html for directions (which just involves copying Java Archive [JAR] and Web Archive [WAR] files). And that's it. You've set up the needed environment; it's time to start writing some code. There will be two servlets here: the ch18_01 servlet will create a SOAP message and send it to a servlet named ch18_02, which will read it and send another SOAP message back to ch18_01. I'll start with the ch18_01 servlet. This is the servlet that creates and sends the SOAP message in the first place. It begins by declaring itself part of a Java package that I'll call soapExample . It includes the other packages we'll need: package soapExample; import java.io.*; import java.net.*; import javax.servlet.*; import javax.xml.soap.*; import javax.activation.*; import javax.servlet.http.*; . . . Next , we'll create the actual SOAP connection that we'll use to send the SOAP message. The base class for servlets is HttpServlet , so this new class, ch18_01 , is based on that class. When a new servlet starts, its init method is called first. We can use a SOAPConnectionFactory object to create a SOAPConnection object like this (the call to super.init(servletConfig) makes sure that the HttpServlet class's constructor is called): public class ch18_01 extends HttpServlet { private SOAPConnection connection; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); try { SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance(); connection = factory.createConnection(); } catch(Exception e) {} } . . . This new SOAPConnection object, connection , is the object we'll use to send a SOAP message to the other servlet, ch18_02. You can see the methods of the SOAPConnectionFactory class in Table 18-1 and the methods of the SOAPConnection class in Table 18-2. Table 18-1. Methods of the javax.xml. soap.SOAP Connection Factory Class
Table 18-2. Methods of the javax.xml. soap.SOAP Connection Class
When you call this servlet using the GET Http method, the servlet's doGet method is called. In that method, we want to create the new SOAP message, which you can do with a MessageFactory object. You use this object's createMessage method to create a new SOAPMessage object. Note that we're also creating the text string that will display the progress of this servlet to the user: public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { String outString ="<HTML><H1>Sent and Received SOAP Message</H1><P>"; try { MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage message = messageFactory.createMessage(); . . . You can see the methods of the MessageFactory class in Table 18-3 and the methods of the SOAPMessage class in Table 18-4. Table 18-3. Methods of the javax.xml. soap.MessageFactory Class
Table 18-4. Methods of the javax.xml. soap.SOAP Message Class
Now that we have a SOAPMessage object, we need to customize the message we want to send. You do that by getting access to the SOAP message's body. In this case, we might send a SOAP message informing the other servlet that there are 125 writing pens in stock at the current time, for example. To get access to the SOAP message's body, you first use the SOAPMessage object's getSOAPPart method to get the SOAP part of the message (as opposed to attachments). Then you can use the getEnvelope method to get the SOAP envelope. Finally, you can use the envelope's getHeader and getBody methods to get the message's header and body (we won't use the header herethis code just shows how to get access to it): public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { String outString ="<HTML><H1>Sent and Received SOAP Message</H1><P>"; try { MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage message = messageFactory.createMessage(); SOAPPart soappart = message.getSOAPPart(); SOAPEnvelope envelope = soappart.getEnvelope(); SOAPHeader header = envelope.getHeader(); SOAPBody body = envelope.getBody(); . . . You can see the methods of the SOAPPart class in Table 18-5, the methods of the SOAPEnvelope interface in Table 18-6, the methods of the SOAPHeader interface in Table 18-7, and the methods of the SOAPBody interface in Table 18-8. Table 18-5. Methods of the javax.xml. soap.SOAP Part Class
Table 18-6. Methods of the javax.xml. soap.SOAP Envelope Interface
Table 18-7. Methods of the javax.xml. soap.SOAP Header Interface
Table 18-8. Methods of the javax.xml. soap.SOAP Body Interface
We can insert a new element into the body of our SOAP message, creating an element named <pens:NumberInStock> with the value 125 like this: <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/ envelope/"> <soap-env:Header/> <soap-env:Body> <pens:NumberInStock xmlns:pens="http://www.starpowder.com">125</pens: NumberInStock> </soap-env:Body> </soap-env:Envelope> Here's how you create that element and add it to the SOAP message's bodywith the SOAPBody object's addBodyElement method and the addText method to add the text 125 : public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { String outString ="<HTML><H1>Sent and Received SOAP Message</H1><P>"; try { MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage message = messageFactory.createMessage(); SOAPPart soappart = message.getSOAPPart(); SOAPEnvelope envelope = soappart.getEnvelope(); SOAPHeader header = envelope.getHeader(); SOAPBody body = envelope.getBody(); body.addBodyElement(envelope.createName("NumberInStock", "pens", "http://www.starpowder.com")).addTextNode("125"); . . . We can also add an attachment to our SOAP message. Attachments hold the text of a file that you want to pass along with the SOAP message (and a receiving servlet can read a SOAP message's attachments with the getAttachments method). In this example, we'll use an HTML page, ch18_03.html (which will be developed in a few pages), to call the ch18_01 servlet and make that servlet run. Let's attach the text of that HTML page to our SOAP message as an example attachment. We start by going through a little work to find the actual URL of that document: public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { String outString ="<HTML><H1>Sent and Received SOAP Message</H1><P>"; try { MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage message = messageFactory.createMessage(); SOAPPart soappart = message.getSOAPPart(); SOAPEnvelope envelope = soappart.getEnvelope(); SOAPHeader header = envelope.getHeader(); SOAPBody body = envelope.getBody(); body.addBodyElement(envelope.createName("NumberInStock", "pens", "http://www.starpowder.com")).addTextNode("125"); StringBuffer urlServer = new StringBuffer(); urlServer.append(request.getScheme()).append("://") .append(request.getServerName()); urlServer.append(":").append(request.getServerPort()).append\(request.getContextPath()); String requestBase = urlServer.toString(); URL url = new URL(requestBase + "/ch18_03.html"); . . . Then we can add that document as an attachment to our SOAP message with an AttachmentPart object, like this: public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { String outString ="<HTML><H1>Sent and Received SOAP Message</H1><P>"; try { MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage message = messageFactory.createMessage(); SOAPPart soappart = message.getSOAPPart(); SOAPEnvelope envelope = soappart.getEnvelope(); SOAPHeader header = envelope.getHeader(); SOAPBody body = envelope.getBody(); body.addBodyElement(envelope.createName("NumberInStock", "pens", "http://www.starpowder.com")).addTextNode("125"); StringBuffer urlServer = new StringBuffer(); urlServer.append(request.getScheme()).append("://").append (request.getServerName()); urlServer.append(":").append(request.getServerPort()).append (request.getContextPath()); String requestBase = urlServer.toString(); URL url = new URL(requestBase + "/ch18_03.html"); AttachmentPart attachmentpart = message.createAttachmentPart (new DataHandler( url)); attachmentpart.setContentType("text/html"); message.addAttachmentPart(attachmentpart); . . . Now ch18_03.html will be sent to the target servlet as an attachment to our SOAP message. You can see the methods of the AttachmentPart class in Table 18-9. Table 18-9. Methods of the javax.xml. soap. Attachment Part Class
Now that we have the base location of the application, we can get the URL of the target servlet, which I'll call getter : StringBuffer urlServer = new StringBuffer(); urlServer.append(request.getScheme()).append("://").append(request. getServerName( )); urlServer.append(":").append(request.getServerPort()).append (request. getContextPath()); String requestBase = urlServer.toString(); URL url = new URL(requestBase + "/ch18_03.html"); AttachmentPart attachmentpart = message.createAttachmentPart(new DataHandler( url)); attachmentpart.setContentType("text/html"); message.addAttachmentPart(attachmentpart); URL getter = new URL(requestBase + "/ch18_02"); . . . This URL is the URL we'll send the SOAP message to. Before sending that message, let's store it in a file so we can take a look at it afterward; in this case, I'll store our SOAP message in a file named put.msg. You can do that with the Java FileOutputStream class and the SOAP message's writeTo method this way: StringBuffer urlServer = new StringBuffer(); urlServer.append(request.getScheme()).append("://").append (request.getServerName()); urlServer.append(":").append(request.getServerPort()).append (request.getContextPath()); String requestBase = urlServer.toString(); URL url = new URL(requestBase + "/ch18_03.html"); AttachmentPart attachmentpart = message.createAttachmentPart (new DataHandler( url)); attachmentpart.setContentType("text/html"); message.addAttachmentPart(attachmentpart); URL getter = new URL(requestBase + "/ch18_02"); FileOutputStream sentFile = new FileOutputStream("put.msg"); message.writeTo(sentFile); sentFile.close(); . . . Now we'll be able to examine the SOAP message even after it has been sent. You can send the message using the connection object's call method, passing that method the message and the target URL like this (note that I also add the message " Sent SOAP message stored in put.msg. <p> " to the text this servlet will display in the user's browser): StringBuffer urlServer = new StringBuffer(); urlServer.append(request.getScheme()).append("://").append (request.getServerName()); urlServer.append(":").append(request.getServerPort()).append (request.getContextPath()); String requestBase = urlServer.toString(); URL url = new URL(requestBase + "/ch18_03.html"); . . . URL getter = new URL(requestBase + "/ch18_02"); . . . outString += "Sent SOAP message stored in put.msg. <p>"; SOAPMessage receivedMessage = connection.call(message, getter); . . . The call method returns the SOAP message that the other servlet sent back to us. We can save that SOAP message in a new file, get.msg: SOAPMessage receivedMessage = connection.call(message, getter); if (receivedMessage != null) { FileOutputStream receivedFile = new FileOutputStream("get.msg"); receivedMessage.writeTo(receivedFile); receivedFile.close(); outString += "Received SOAP message stored in get.msg.</HTML>"; } And that's it. We've sent a SOAP message, gotten one back, and stored them both in files for later examination. All that remains is to send the notification text stored in the outString variable (which tells the user Sent SOAP message stored in put.msg . and Received SOAP message stored in get.msg .) back to the user's browser. You can do that in a servlet using an OutputStream object. You can create this using the response object's getOutputStream method (the response object is passed to the servlet's doGet method): SOAPMessage receivedMessage = connection.call(message, getter); if (receivedMessage != null) { FileOutputStream receivedFile = new FileOutputStream("get.msg"); receivedMessage.writeTo(receivedFile); receivedFile.close(); outString += "Received SOAP message stored in get.msg.</HTML>"; } } catch(Throwable e) {} try { OutputStream outputStream = response.getOutputStream(); outputStream.write(outString.getBytes()); outputStream.flush(); outputStream.close(); } catch (IOException e) {} And that's it. We've passed the text back to the user's browser, and that completes the ch18_01 servlet. Here's the full code: Listing ch18_01.javapackage soapExample; import java.io.*; import java.net.*; import javax.servlet.*; import javax.xml.soap.*; import javax.activation.*; import javax.servlet.http.*; public class ch18_01 extends HttpServlet { private SOAPConnection connection; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); try { SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance(); connection = factory.createConnection(); } catch(Exception e) {} } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { String outString ="<HTML><H1>Sent and Received SOAP Message</H1><P>"; try { MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage message = messageFactory.createMessage(); SOAPPart soappart = message.getSOAPPart(); SOAPEnvelope envelope = soappart.getEnvelope(); SOAPHeader header = envelope.getHeader(); SOAPBody body = envelope.getBody(); body.addBodyElement(envelope.createName("NumberInStock", "pens", "http://www.starpowder.com")).addTextNode("125"); StringBuffer urlServer = new StringBuffer(); urlServer.append(request.getScheme()).append("://").append (request.getServerName()); urlServer.append(":").append(request.getServerPort()).append (request.getContextPath()); String requestBase = urlServer.toString(); URL url = new URL(requestBase + "/ch18_03.html"); AttachmentPart attachmentpart = message.createAttachmentPart (new DataHandler( url)); attachmentpart.setContentType("text/html"); message.addAttachmentPart(attachmentpart); URL getter = new URL(requestBase + "/ch18_02"); FileOutputStream sentFile = new FileOutputStream("put.msg"); message.writeTo(sentFile); sentFile.close(); outString += "Sent SOAP message stored in put.msg. <p>"; SOAPMessage receivedMessage = connection.call(message, getter); if (receivedMessage != null) { FileOutputStream receivedFile = new FileOutputStream("get.msg"); receivedMessage.writeTo(receivedFile); receivedFile.close(); outString += "Received SOAP message stored in get.msg.</HTML>"; } } catch(Throwable e) {} try { OutputStream outputStream = response.getOutputStream(); outputStream.write(outString.getBytes()); outputStream.flush(); outputStream.close(); } catch (IOException e) {} } } The next step is to develop the ch18_02 servlet, which is the target of our SOAP message. This servlet will read the incoming SOAP message, interpret it, and send a message back indicating that it has understood that incoming message. This servlet, which "listens" for incoming SOAP messages, is based on the JAXMServlet class and implements the ReqRespListener interface: public class ch18_02 extends JAXMServlet implements ReqRespListener { . . . The JAXMServlet class lets you handle XML messages like SOAP messages. The ReqRespListener interface has only one method, the onMessage method that is called when a message is read. When that message is read, we will create and send back a new SOAP message, which means we'll need a new message factory object. I'll create that object when the servlet is first initialized : public class ch18_02 extends JAXMServlet implements ReqRespListener { static MessageFactory factory = null; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); try { factory = MessageFactory.newInstance(); } catch (Exception ex) {} } . . . Now, in the onMessage method, we can handle the incoming SOAP message, which is passed to this method. We handle that message by getting the data in it (that there are 125 pens in stock). The code begins by getting the SOAP message's body: public SOAPMessage onMessage(SOAPMessage msg) { try { SOAPPart soappart = msg.getSOAPPart(); SOAPEnvelope incomingEnvelope = soappart.getEnvelope(); SOAPBody body = incomingEnvelope.getBody(); . . . To access the elements in the SOAP message's body, you can use the body object's getChildElements method. You pass this method a Name object for the element you want, which includes the name of the element as well as the element's namespace and namespace URI. You can create that Name object with the SOAP envelope object's createName method like this: public SOAPMessage onMessage(SOAPMessage msg) { try { SOAPPart soappart = msg.getSOAPPart(); SOAPEnvelope incomingEnvelope = soappart.getEnvelope(); SOAPBody body = incomingEnvelope.getBody(); Iterator it = body.getChildElements( incomingEnvelope.createName("NumberInStock", "pens","http://www.starpowder.com")); . . . The getChildElements method returns a Java Iterator object, which lets you access all the returned elements with Iterator 's next method. To get the body element's first (and only, in this case), elementthe <pens:NumberInStock> elementyou can use the Iterator 's next method like this: public SOAPMessage onMessage(SOAPMessage msg) { try { SOAPPart soappart = msg.getSOAPPart(); SOAPEnvelope incomingEnvelope = soappart.getEnvelope(); SOAPBody body = incomingEnvelope.getBody(); Iterator it = body.getChildElements( incomingEnvelope.createName("NumberInStock", "pens", "http://www.starpowder. com")); SOAPElement element; element = (SOAPElement) it.next(); . . . Now we have the <pens:NumberInStock> element in a SOAPElement object. You can see the methods of the SOAPElement interface in Table 18-10. This interface is based on the SOAP Node interface, and you can see the methods of the Node interface in Table 18-11. Note in particular the getValue method of the Node interface in Table 18-11that's the method we'll use to extract the value of the <pens:NumberInStock> element. Table 18-10. Methods of the javax.xml. soap.SOAP Element Interface
Table 18-11. Methods of the javax.xml. soap.Node Interface
To send a SOAP message back to the ch18_01 servlet, we can use the message factory's createMessage method. Then we can use the new message's getEnvelope method to get the message's envelope, which is the first step in customizing that message: public SOAPMessage onMessage(SOAPMessage msg) { try { SOAPPart soappart = msg.getSOAPPart(); SOAPEnvelope incomingEnvelope = soappart.getEnvelope(); SOAPBody body = incomingEnvelope.getBody(); Iterator it = body.getChildElements( incomingEnvelope.createName("NumberInStock", "pens", "http://www.starpowder. com")); SOAPElement element; element = (SOAPElement) it.next(); SOAPMessage message = factory.createMessage(); SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); . . . All that's left is to add a new element to hold the data we want to send to the return message. I'll call this new element <Response> , and I'll add a text node to that element with text indicating that we've read how many pens are left in stock (the element.getValue method here returns the number of pens from the incoming SOAP message): public SOAPMessage onMessage(SOAPMessage msg) { try { SOAPPart soappart = msg.getSOAPPart(); SOAPEnvelope incomingEnvelope = soappart.getEnvelope(); SOAPBody body = incomingEnvelope.getBody(); Iterator it = body.getChildElements( incomingEnvelope.createName("NumberInStock", "pens", "http://www.starpowder. com")); SOAPElement element; element = (SOAPElement) it.next(); SOAPMessage message = factory.createMessage(); SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); envelope.getBody().addChildElement(envelope.createName("Response")).addTextNode( "Thanks for the SOAP message telling me there are " + element.getValue() + " pens in stock" ); return message; } catch(Exception e) { return null; } At the end of this code, we return the completed message, which automatically sends it back to the original servlet, ch18_01. Here's the full code for the ch18_02 servlet: Listing ch18_02.javapackage soapExample; import java.util.*; import javax.servlet.*; import javax.xml.soap.*; import javax.servlet.http.*; import javax.xml.messaging.*; public class ch18_02 extends JAXMServlet implements ReqRespListener { static MessageFactory factory = null; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); try { factory = MessageFactory.newInstance(); } catch (Exception ex) {} } public SOAPMessage onMessage(SOAPMessage msg) { try { SOAPPart soappart = msg.getSOAPPart(); SOAPEnvelope incomingEnvelope = soappart.getEnvelope(); SOAPBody body = incomingEnvelope.getBody(); Iterator it = body.getChildElements( incomingEnvelope.createName("NumberInStock", "pens", "http://www.starpowder. com")); SOAPElement element; element = (SOAPElement) it.next(); SOAPMessage message = factory.createMessage(); SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); envelope.getBody().addChildElement(envelope.createName ("Response")). addTextNode( "Thanks for the SOAP message telling me there are " + element.getValue() + " pens in stock" ); return message; } catch(Exception e) { return null; } } } And that's it. To compile these servlets, ch18_01.java and ch18_02.java, you'll need servlet.jar, jaxm-api.jar, saaj-api.jar, and activation.jar in your classpath environment variable. Here's what that looks like (this assumes that the .jar files are in the same directory as the .java files; if that's not so, make sure you preface every .jar filename with its correct path ): %set classpath=servlet.jar;jaxm-api.jar;saaj-api.jar;activation.jar %javac ch18_01.java %javac ch18_02.java How do we get the first servlet, ch18_01, to run? In this example, I'll use an HTML page, ch18_03.html, to call that servlet. The user can open this HTML page and click a hyperlink to run ch18_01, which will send a SOAP message to ch18_02: Listing ch18_03.html <HTML> <HEAD> <TITLE>Using SOAP</TITLE> </HEAD> <BODY> <CENTER> <H1>Using SOAP</H1> </CENTER> <A HREF="ch18_01">Click me</a> to send and receive a SOAP message. </BODY> </HTML> And we're almost set. We also need to create a file named web.xml that will let Tomcat connect the class files ch18_01.class and ch18_02.class to URLs that you can enter into a browser. Here's what web.xml looks like (this file is included in the downloadable code for this book): <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app> <servlet> <servlet-name> ch18_01 </servlet-name> <servlet-class> soapExample.ch18_01 </servlet-class> </servlet> <servlet> <servlet-name> ch18_02 </servlet-name> <servlet-class> soapExample.ch18_02 </servlet-class> </servlet> <servlet-mapping> <servlet-name> ch18_01 </servlet-name> <url-pattern> /ch18_01 </url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name> ch18_02 </servlet-name> <url-pattern> /ch18_02 </url-pattern> </servlet-mapping> </web-app> And that's it. Now we have the files we'll need, ch18_01.class, ch18_02.class, ch18_03.html, and web.xml. To install them in Tomcat, stop Tomcat and add a directory named soap to the Tomcat webapps directory with these files and subdirectories: webapps (directory) __soap (directory) __ch18_03.html __WEB-INF (directory) __web.xml __classes (directory) __soapExample (directory) __ch18_01.class __ch18_02.class Then (re)start Tomcat. The whole application is ready to go. Navigate to http://localhost:8080/soap/ch18_03.html in your browser, as you see in Figure 18-2. Figure 18-2. Starting our SOAP example.
Click the link you see in Figure 18-2 to call the ch18_01 servlet, which will send a SOAP message to the ch18_02 servlet. This servlet, in turn , sends another SOAP message back to ch18_01. You can see the results that ch18_01 reports back to the user in Figure 18-3. Figure 18-3. The status report by the SOAP example.
As you can see in Figure 18-3, a SOAP message was sent and another SOAP message was returned. What did those messages look like? We wrote this application to store the actual SOAP messages in the files put.msg and get.msg, which will be stored in the Tomcat bin directory. Here's the first SOAP message, as sent by ch18_01 and stored in put.msg. You can see the SOAP message here, including the <pens:NumberInStock> element that holds the number of pens in stock, as well as the attachment that holds ch18_03.html: ------=_Part_0_13526686.1026338101718 Content-Type: text/xml <?xml version="1.0" encoding="UTF-8"?> <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/ envelope/"> <soap-env:Header/> <soap-env:Body> <pens:NumberInStock xmlns:pens="http://www.starpowder.com">125< /pens: NumberInStock> </soap-env:Body> </soap-env:Envelope> ------=_Part_0_13526686.1026338101718 Content-Type: text/html <HTML> <HEAD> <TITLE>Using SOAP</TITLE> </HEAD> <BODY> <CENTER> <H1>Using SOAP</H1> </CENTER> <A HREF="ch18_01">Click me</a> to send and receive a SOAP message. </BODY> </HTML> ------=_Part_0_13526686.1026338101718-- Here's the returned SOAP message, as stored in get.msg, indicating that the second servlet, ch18_02, understood that 125 pens were in stock: <?xml version="1.0" encoding="UTF-8"?> <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/ envelope/"> <soap-env:Header/> <soap-env:Body> <Response>Thanks for the SOAP message telling me there are 125 pens in stock</ Response> </soap-env:Body> </soap-env:Envelope> Congratulations, you've sent and received SOAP messages in code now. As you can see, SOAP can form the communications backbone for a distributed application. And you don't need to program SOAP applications in Java, either. There are many other options these days, including Microsoft's Visual Studio .NET, which creates Web services that use SOAP. In fact, because SOAP is language- and platform-independent, you can use SOAP to communicate among various parts of a Web application that are written in different languages. |