The JavaTM Web Services Tutorial
Home
TOC
Index
PREV TOP NEXT
Divider

Code Examples

The first part of this tutorial used code fragments to walk you through the fundamentals of using the JAXM API. In this section, you will use some of those code fragments to create applications. First, you will see the program Request.java. Then you will see how to create and run the application MyUddiPing.java. Finally, you will see how to create and run SOAPFaultTest.java.


Note: <JWSDP_HOME> is the directory where you unpacked the Java Web Services Developer Pack.

Request.java

The class Request.java puts together the code fragments used in the section Client without a Messaging Provider and adds what is needed to make it a complete example of a client sending a request-response message. In addition to putting all the code together, it adds import statements, a main method, and a try/catch block with exception handling. The file Request.java, shown here in its entirety, is a standalone client application that uses the SAAJ API (the javax.xml.soap package). It does not need to use the javax.xml.messaging package because it does not use a messaging provider.

import javax.xml.soap.*;
import java.util.*;
import java.net.URL;
 
public class Request {
  public static void main(String[] args)  {
    try {
      SOAPConnectionFactory scFactory =
          SOAPConnectionFactory.newInstance();
      SOAPConnection con = scFactory.createConnection();
 
      MessageFactory factory =
          MessageFactory.newInstance();
      SOAPMessage message = factory.createMessage();
 
      SOAPPart soapPart = message.getSOAPPart();
      SOAPEnvelope envelope = soapPart.getEnvelope();
      SOAPHeader header = envelope.getHeader();
      SOAPBody body = envelope.getBody();
      header.detachNode();
 
      Name bodyName = envelope.createName(
              "GetLastTradePrice", "m",
              "http://wombats.ztrade.com");
      SOAPBodyElement gltp =
              body.addBodyElement(bodyName);
 
      Name name = envelope.createName("symbol");
      SOAPElement symbol = gltp.addChildElement(name);
      symbol.addTextNode("SUNW");
 
      URL endpoint = new URL
                ("http://wombat.ztrade.com/quotes";
      SOAPMessage response = con.call(message, endpoint);
 
      con.close();
 
      SOAPPart sp = response.getSOAPPart();
      SOAPEnvelope se = sp.getEnvelope();
      SOAPBody sb = se.getBody();
 
      Iterator it = sb.getChildElements(bodyName);
      SOAPBodyElement bodyElement =
              (SOAPBodyElement)it.next();
      String lastPrice = bodyElement.getValue();
 
      System.out.print("The last price for SUNW is ");
      System.out.println(lastPrice);
 
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
}
 

In order for Request.java to be runnable, the second argument supplied to the method call has to be a valid existing URI, which is not true in this case. See the JAXM code in the case study for similar code that you can run (JAXM Client). Also, the application in the next section is one that you can run.

UddiPing.java and MyUddiPing.java

The sample program UddiPing.java is another example of a standalone application. A Universal Description, Discovery and Integration (UDDI) service is a business registry and repository from which you can get information about businesses that have registered themselves with the registry service. For this example, the UddiPing application is not actually accessing a UDDI service registry but rather a test (demo) version. Because of this, the number of businesses you can get information about is limited. Nevertheless, UddiPing demonstrates a request being sent and a response being received. The application prints out the complete message that is returned, that is, the complete XML document as it looks when it comes over the wire. Later in this section you will see how to rewrite UddiPing.java so that in addition to printing out the entire XML document, it also prints out just the text content of the response, making it much easier to see the information you want.

In order to get a better idea of how to run the UddiPing example, take a look at the directory <JWSDP_HOME>/samples/jaxm/uddiping. This directory contains the subdirectory src and the files run.sh (or run.bat), uddi.properties, UddiPing.class, and README. The README file tells you what you need to do to run the application, which is explained more fully here.

The README file directs you to modify the file uddi.properties, which contains the URL of the destination (the UDDI test registry) and the proxy host and proxy port of the sender. If you are in the uddiping directory when you call the run.sh (or run.bat) script, the information in uddi.properties should be correct already. If you are outside Sun Microsystem's firewall, however, you need to supply your proxy host and proxy port. If you are not sure what the values for these are, you need to consult your system administrator or other person with that information.

The main job of the run script is to execute UddiPing. Once the file uddi.properties has the correct proxy host and proxy port, you can call the appropriate run script as shown here. Note that you must supply two arguments, uddi.properties and the name of the business you want to look up.

Unix:

cd <JWSDP_HOME>/samples/jaxm/uddiping
run.sh uddi.properties Microsoft
 

Windows:

cd <JWSDP_HOME>\samples\jaxm\uddiping
run.bat uddi.properties Microsoft
 

What appears on your screen will look something like this:

Received replyfrom: 
http://www3.ibm.com/services/uddi/testregistry/inquiryapi<?xml 
version="1.0" encoding="UTF-8" ?><Envelope 
xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body><busin
essList generic="1.0" xmlns="urn:uddi-org:api" 
operator="www.ibm.com/services/uddi" 
truncated="false"><businessInfos><businessInfo 
businessKey="D7475060-BF58-11D5-A432-
0004AC49CC1E"><name>Microsoft Corporation</name><description 
xml:lang="en">Computer Software and Hardware 
Manufacturer</description><serviceInfos></serviceInfos></busin
essInfo></businessInfos></businessList></Body></Envelope>
 

If the business name you specified is in the test registry, the output is an XML document with the name and description of that business. However, these are embedded in the XML document, which makes them difficult to see. The next section adds code to UddiPing.java that extracts the content so that it is readily visible.

Creating MyUddiPing.java

To make the response to UddiPing.java easier to read, you will create a new file called MyUddiPing.java, which extracts the content and prints it out. You will see how to write the new file later in this section after setting up a new directory with the necessary subdirectories and files.

Setting Up

Because the name of the new file is MyUddiPing.java, create the directory myuddiping under the <JWSDP_HOME>/samples/jaxm directory.

cd <JWSDP_HOME>/samples/jaxm
mkdir myuddiping
 

This new myuddiping directory will be the base directory for all future commands relating to MyUddiPing.java.

In place of the run.sh or run.bat script used for running UddiPing, you will be using an Ant file, build.xml, for setting up directories and files and for running MyUddiPing. The advantage of using an Ant file is that it is cross-platform and can thus be used for both Unix and Windows platforms. Accordingly, you need to copy the build.xml file in the examples/jaxm directory of the tutorial to your new myuddiping directory. (The command for copying should be all on one line. Note that there is no space between "myuddiping/" "and "build", and there is a "." at the end of the command line.)

Unix:

cd myuddiping
cp <JWSDP_HOME>/docs/tutorial/examples/jaxm/myuddiping/
                                      build.xml .
 

Windows:

cd myuddiping
copy <JWSDP_HOME>\docs\tutorial\examples\jaxm\myuddiping\
                                      build.xml .
 

Once you have the file build.xml in your myuddiping directory, you can call it to do the rest of the setup and also to run MyUddiPing. An Ant build file is an XML file that is sectioned into targets, with each target being an element that contains attributes and one or more tasks. For example, the target element whose name attribute is prepare creates the directories build and src and copies the file MyUddiPing.java from the <JWSDP_HOME>/docs/tutorial/examples/jaxm/myuddiping/src directory to the new src directory. Then it copies the file uddi.properties from the uddiping directory to the myuddiping directory that you created.

To accomplish these tasks, you type the following at the command line:

ant prepare
 

The target named build compiles the source file MyUddiPing.java and puts the resulting .class file in the build directory. So to do these tasks, you type the following at the command line:

ant build
 

Now that you are set up for running MyUddiPing, let's take a closer look at the code.

Examining MyUddiPing

We will go through the file MyUddiPing.java a few lines at a time. Note that most of the class MyUddiPing.java is based on UddiPing.java. We will be adding a section at the end of MyUddiPing.java that accesses only the content you want from the response that is returned by the method call.

The first four lines of code import the packages used in the application.

import javax.xml.soap.*;
import javax.xml.messaging.*;
import java.util.*;
import java.io.*;
 

The next few lines begin the definition of the class MyUddiPing, which starts with the definition of its main method. The first thing it does is check to see if two arguments were supplied. If not, it prints a usage message and exits.

public class MyUddiPing {
  public static void main(String[] args) {
    try {
      if (args.length != 2) {
        System.err.println("Usage: MyUddiPing " +
          "properties-file business-name");
        System.exit(1);
      }
 

The following lines create a java.util.Properties file that contains the system properties and the properties from the file uddi.properties that is in the myuddiping directory.

      Properties myprops = new Properties();
      myprops.load(new FileInputStream(args[0]));
      Properties props = System.getProperties();
      Enumeration it = myprops.propertyNames();
      while (it.hasMoreElements()) {
        String s = (String) it.nextElement(); 
        props.put(s, myprops.getProperty(s));
      } 
 

The next four lines create a SOAPMessage object. First, the code gets an instance of SOAPConnectionFactory and uses it to create a connection. Then it gets an instance of MessageFactory and uses it to create a message.

      SOAPConnectionFactory scf =
          SOAPConnectionFactory.newInstance();
      SOAPConnection connection =
          scf.createConnection();
      MessageFactory msgFactory =
          MessageFactory.newInstance();
      SOAPMessage msg = msgFactory.createMessage(); 
 

The new SOAPMessage object msg automatically contains a SOAPPart object that contains a SOAPEnvelope object. The SOAPEnvelope object contains a SOAPBody object, which is the element you want to access in order to add content to it. The next lines of code get the SOAPPart object, the SOAPEnvelope object, and the SOAPBody object.

      SOAPEnvelope envelope =
            msg.getSOAPPart().getEnvelope();
      SOAPBody body = envelope.getBody();
 

The following lines of code add an element with a fully-qualified name and then add two attributes to the new element. The first attribute has the name "generic" and the value "1.0". The second attribute has the name "maxRows" and the value "100". Then the code adds a child element with the name name and adds some text to it with the method addTextNode. The text added is the business name you will supply when you run the application.

      SOAPBodyElement findBusiness =
          body.addBodyElement(
          envelope.createName("find_business",
          "", "urn:uddi-org:api"));
      findBusiness.addAttribute(
          envelope.createName("generic", "1.0");
      findBusiness.addAttribute(
          envelope.createName("maxRows", "100");
      SOAPElement businessName =
          findBusiness.addChildElement(
          envelope.createName("name"));
      businessName.addTextNode(args[1]); 
 

The next line of code creates the Java Object that represents the destination for this message. It gets the value of the property named "URL" from the system property file.

      Object endpoint = 
        System.getProperties().getProperty("URL");
 

The following line of code saves the changes that have been made to the message. This method will be called automatically when the message is sent, but it does not hurt to call it explicitly.

      msg.saveChanges(); 
 

Next the message msg is sent to the destination that endpoint represents, which is the test UDDI registry. The method call will block until it gets a SOAPMessage object back, at which point it returns the reply.

      SOAPMessage reply = connection.call(msg, endpoint);
 

In the next two lines, the first prints out a line giving the URL of the sender (the test registry), and the second prints out the returned message as an XML document.

      System.out.println("Received reply from: " +  endpoint);
      reply.writeTo(System.out);
 

The code thus far has been based on UddiPing.java. The next section adds code to create MyUddiPing.java.

Adding New Code

The code we are going to add to UddiPing will make the reply more user-friendly. It will get the content from certain elements rather than printing out the whole XML document as it was sent over the wire. Because the content is in the SOAPBody object, the first thing you need to do is access it, as shown in the following line of code. You can access each element in separate method calls, as was done in earlier examples, or you can access the SOAPBody object using this shorthand version.

SOAPBody replyBody =
    reply.getSOAPPart().getEnvelope().getBody();
 

Next you might print out two blank lines to separate your results from the raw XML message and a third line that describes the text that follows.

      System.out.println("");
      System.out.println("");
      System.out.print(
       "Content extracted from the reply message: ");
 

Now you can begin the process of getting all of the child elements from an element, getting the child elements from each of those, and so on, until you arrive at a text element that you can print out. Unfortunately, the registry used for this example code, being just a test registry, is not always consistent. The number of subelements sometimes varies, making it difficult to know how many levels down the code needs to go. And in some cases, there are multiple entries for the same company name. Note that by contrast, the entries in a standard valid registry will be consistent.

The code you will be adding drills down through the subelements within the SOAP body and retrieves the name and description of the business. The method you use to retrieve child elements is the SOAPElement method getChildElements. When you give this method no arguments, it retrieves all of the child elements of the element on which it is called. If you know the Name object used to name an element, you can supply that to getChildElements and retrieve only the children with that name. In this example, however, you need to retrieve all elements and keep drilling down until you get to the elements that contain text content.

Here is the basic pattern that is repeated for drilling down:

      Iterator iter1 = replyBody.getChildElements();
      while (iter1.hasNext()) { 
        SOAPBodyElement bodyElement =
            (SOAPBodyElement)iter1.next();
        Iterator iter2 =
            bodyElement.getChildElements();
        while (iter2.hasNext()) {
 

The method getChildElements returns the elements in the form of a java.util.Iterator object. You access the child elements by calling the method next on the Iterator object. The method Iterator.hasNext can be used in a while loop because it returns true as long as the next call to the method next will return a child element. The loop ends when there are no more child elements to retrieve.

An immediate child of a SOAPBody object is a SOAPBodyElement object, which is why calling iter1.next returns a SOAPBodyElement object. Children of SOAPBodyElement objects and all child elements from there down are SOAPElement objects. For example, the call iter2.next returns the SOAPElement object child2. Note that the method Iterator.next returns an Object, which has to be narrowed (cast) to the specific kind of object you are retrieving. Thus, the result of calling iter1.next is cast to a SOAPBodyElement object, whereas the results of calling iter2.next, iter3.next, and so on, are all cast to a SOAPElement object.

Here is the code you add to access and print out the business name and description:

      Iterator iter1 = replyBody.getChildElements();
      while (iter1.hasNext()) { 
        SOAPBodyElement bodyElement =
            (SOAPBodyElement)iter1.next();
        Iterator iter2 =
            bodyElement.getChildElements();
        while (iter2.hasNext()) {
          SOAPElement child2 =
            (SOAPElement)iter2.next();
          Iterator iter3 =
            child2.getChildElements();
          String content = child2.getValue();
          System.out.println(content);
          while (iter3.hasNext()) {
            SOAPElement child3 =
              (SOAPElement)iter3.next();
            Iterator iter4 =
                child3.getChildElements();
            content = child3.getValue();
            System.out.println(content);
            while (iter4.hasNext()) {
              SOAPElement child4 =
                (SOAPElement)iter4.next();
              content = child4.getValue();
              System.out.println(content);
            }
          }
        }  
      }
      connection.close();
    } catch (Exception ex) { 
      ex.printStackTrace(); 
    }
  }
}
 

You have already compiled MyUddiPing.java by calling the following at the command line:

ant build
 

With the code compiled, you are ready to run MyUddiPing. The following command will call java on the .class file for MyUddiPing, which takes two arguments. The first argument is the file uddi.properties, which is supplied by a property set in build.xml. The second argument is the name of the business for which you want to get a description, and you need to supply this argument on the command line. Note that any property set on the command line overrides the value set for that property in the build.xml file. The last argument supplied to Ant is always the target, which in this case is run.

cd <JWSDP_HOME>/samples/jaxm/myuddiping
ant -Dbusiness-name="Oracle" run
 

Here is the output that will appear after the full XML message. It is produced by the code added in MyUddiPing.java.

Content extracted from the reply message: 
 
Oracle
oracle powers the internet
 
Oracle Corporation
Oracle Corporation provides the software and services for e-
business.
 

Running Ant with Microsoft as the business-name property instead of Oracle produces the following output:

Received reply from: http://www-
3.ibm.com/services/uddi/testregistry/inquiryapi
<?xml version="1.0" encoding="UTF-8" ?><Envelope 
xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body><busin
essList generic="1.0" xmlns="urn:uddi-org:api" 
operator="www.ibm.com/services/uddi" 
truncated="false"><businessInfos><businessInfo 
businessKey="D7475060-BF58-11D5-A432-
0004AC49CC1E"><name>Microsoft Corporation</name><description 
xml:lang="en">Computer Software and Hardware 
Manufacturer</description><serviceInfos></serviceInfos></busin
essInfo></businessInfos></businessList></Body></Envelope>
 
Content extracted from the reply message: 
 
Microsoft Corporation
Computer Software and Hardware Manufacturer
 

SOAPFaultTest.java

The code SOAPFaultTest.java, based on the code fragments in a preceding section (SOAP Faults) creates a message with a SOAPFault object. It then retrieves the contents of the SOAPFault object and prints them out. You will find the code for SOAPFaultTest in the following directory:

<JWSDP_HOME>/docs/tutorial/examples/jaxm/fault/src 
 

Here is the file SOAPFaultTest.java.

import javax.xml.soap.*;
import java.util.*;
 
public class SOAPFaultTest {

  public static void main(String[] args) { 
    try {
       MessageFactory msgFactory =
                        MessageFactory.newInstance();
      SOAPMessage msg = msgFactory.createMessage();         
      SOAPEnvelope envelope =
                      msg.getSOAPPart().getEnvelope();
      SOAPBody body = envelope.getBody(); 
      SOAPFault fault = body.addFault();
 
      fault.setFaultCode("Client"); 
      fault.setFaultString(
              "Message does not have necessary info"); 
      fault.setFaultActor("http://gizmos.com/order");
 
      Detail detail = fault.addDetail();
 
      Name entryName = envelope.createName("order", "PO", 
                     "http://gizmos.com/orders/"); 
      DetailEntry entry = detail.addDetailEntry(entryName); 
      entry.addTextNode(
          "quantity element does not have a value");
 
      Name entryName2 = envelope.createName("confirmation",
                "PO",   "http://gizmos.com/confirm");
      DetailEntry entry2 = detail.addDetailEntry(entryName2); 
      entry2.addTextNode("Incomplete address: no zip code");
 
      msg.saveChanges();

      // Now retrieve the SOAPFault object and its contents
      //after checking to see that there is one

      if ( body.hasFault() ) { 
        fault = body.getFault();
        String code = fault.getFaultCode();
        String string = fault.getFaultString(); 
        String actor = fault.getFaultActor();

        System.out.println("SOAP fault contains: ");
        System.out.println("    fault code = " + code);
        System.out.println("    fault string = " + string);
        if ( actor != null) { 
          System.out.println("    fault actor = " + actor);
        }

      detail = fault.getDetail();
      if ( detail != null) {
        Iterator it = detail.getDetailEntries();
        while ( it.hasNext() ) {
          entry = (DetailEntry)it.next();
          String value = entry.getValue();
          System.out.println("    Detail entry = " + value);
        }
      }
    } catch (Exception ex) { 
      ex.printStackTrace(); 
    } 
  } 
} 
 

Running SOAPFaultTest

To run SOAPFaultTest, you use the Ant file build.xml that is in the directory <JWSDP_HOME>/docs/tutorial/examples/jaxm/fault.

This Ant file does many things for you, including creating a build directory where class files will go, creating the classpath needed to run SOAPFaultTest, compiling SOAPFaulTest.java, putting the resulting .class file in the build directory, and running SOAPFaultTest.

To run SOAPFaultTest, do the following:

  1. Go to the directory where the appropriate build.xml file is located.
      cd <JWSDP_HOME>/docs/tutorial/examples/jaxm/fault
     
    
  2. At the command line, type the following:
      ant prepare
     
    
    This will create the build directory, the directory where class files will be put.
  3. At the command line, type
      ant build
     
    
    This will run javac on SOAPFaultTest.java using the classpath that has been set up in the build.xml file. The resulting .class file will be put in the build directory created by the prepare target.
  4. At the command line, type
      ant run
     
    
    This will execute the command java SOAPFaultTest.

Note that as a shortcut, you can simply type ant run. The necessary targets will be executed in the proper order because if a target indicates that it depends on one or more other targets, those will be executed before the specified target is executed. In this case, the run target depends on the build target, which in turn depends on the prepare target, so the prepare, build, and run targets will be executed in that order. As an even faster shortcut, you can type just ant. The default target for this build.xml file is run, so it has the same effect as typing ant run.

If you want to run SOAPFaultTest again, it is a good idea to start over by deleting the build directory and the .class file it contains. You can do this by typing the following at the command line:

ant clean
 

After running SOAPFaultTest, you will see something like this:

Here is what the XML message looks like:
 
<?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><soap-env:
Fault><soap-env:faultcode>Client</soap-env:faultcode><soap-
env:faultstring>Message does not have necessary info</soap-
env:faultstring><soap-env:faultactor>http://gizmos.com/order
</soap-env:faultactor><soap-env:Detail><PO:order xmlns:PO=
"http://gizmos.com/orders/">quantity element does not have a 
value</PO:order><PO:confirmation xmlns:PO="http://gizmos.com/
confirm">Incomplete address: no zip code</PO:confirmation>
</soap-env:Detail></soap-env:Fault></soap-env:Body></soap-env:
Envelope>
 
Here is what the SOAP fault contains: 
  fault code = Client
  fault string = Message does not have necessary info
  fault actor = http://gizmos.com/order
  Detail entry = quantity element does not have a value
  Detail entry = Incomplete address: no zip code
 

Conclusion

JAXM provides a Java API that simplifies writing and sending XML messages. You have seen how to use this API to write client code for JAXM request-response messages and one-way messages. You have also seen how to get the content from a reply message. This knowledge was applied in writing and running the MyUddiPing and SOAPFaultTest examples. In addition, the case study (The Coffee Break Application) provides detailed examples of JAXM code for both the client and server.

You now have first-hand experience of how JAXM makes it easier to do XML messaging.

Divider
Home
TOC
Index
PREV TOP NEXT
Divider

This tutorial contains information on the 1.0 version of the Java Web Services Developer Pack.

All of the material in The Java Web Services Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.