Home
TOC Index |
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 applicationMyUddiPing.java
. Finally, you will see how to create and runSOAPFaultTest.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 addsimport
statements, amain
method, and atry
/catch
block with exception handling. The fileRequest.java
, shown here in its entirety, is a standalone client application that uses the SAAJ API (thejavax.xml.soap
package). It does not need to use thejavax.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 methodcall
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, theUddiPing
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 rewriteUddiPing.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 subdirectorysrc
and the filesrun.sh
(orrun.bat
),uddi.properties
,UddiPing.class
, andREADME
. TheREADME
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 fileuddi.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 theuddiping
directory when you call therun.sh
(orrun.bat
) script, the information inuddi.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 executeUddiPing
. Once the fileuddi.properties
has the correct proxy host and proxy port, you can call the appropriaterun
script as shown here. Note that you must supply two arguments,uddi.properties
and the name of the business you want to look up.cd <JWSDP_HOME
>/samples/jaxm/uddiping run.sh uddi.properties Microsoftcd <JWSDP_HOME
>\samples\jaxm\uddiping run.bat uddi.properties MicrosoftWhat 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 calledMyUddiPing.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 directorymyuddiping
under the<
JWSDP_HOME>
/samples/jaxm
directory.cd <JWSDP_HOME
>/samples/jaxm mkdir myuddipingThis new
myuddiping
directory will be the base directory for all future commands relating toMyUddiPing.java
.In place of the
run.sh
orrun.bat
script used for runningUddiPing
, you will be using anAnt
file,build.xml
, for setting up directories and files and for runningMyUddiPing
. The advantage of using anAnt
file is that it is cross-platform and can thus be used for both Unix and Windows platforms. Accordingly, you need to copy thebuild.xml
file in theexamples/jaxm
directory of the tutorial to your newmyuddiping
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.)cd myuddiping cp <JWSDP_HOME
>/docs/tutorial/examples/jaxm/myuddiping/ build.xml .cd myuddiping copy <JWSDP_HOME
>\docs\tutorial\examples\jaxm\myuddiping\ build.xml .Once you have the file
build.xml
in yourmyuddiping
directory, you can call it to do the rest of the setup and also to runMyUddiPing
. AnAnt
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 isprepare
creates the directoriesbuild
andsrc
and copies the fileMyUddiPing.java
from the<
JWSDP_HOME
>/docs/tutorial/examples/jaxm/myuddiping/src
directory to the newsrc
directory. Then it copies the fileuddi.properties
from theuddiping
directory to themyuddiping
directory that you created.To accomplish these tasks, you type the following at the command line:
ant prepareThe target named
build
compiles the source fileMyUddiPing.java
and puts the resulting.class
file in thebuild
directory. So to do these tasks, you type the following at the command line:ant buildNow 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 classMyUddiPing.java
is based onUddiPing.java
. We will be adding a section at the end ofMyUddiPing.java
that accesses only the content you want from the response that is returned by the methodcall
.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 itsmain
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 fileuddi.properties
that is in themyuddiping
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 ofSOAPConnectionFactory
and uses it to create a connection. Then it gets an instance ofMessageFactory
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
objectmsg
automatically contains aSOAPPart
object that contains aSOAPEnvelope
object. TheSOAPEnvelope
object contains aSOAPBody
object, which is the element you want to access in order to add content to it. The next lines of code get theSOAPPart
object, theSOAPEnvelope
object, and theSOAPBody
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 namename
and adds some text to it with the methodaddTextNode
. 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 thatendpoint
represents, which is the test UDDI registry. The methodcall
will block until it gets aSOAPMessage
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 createMyUddiPing.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 theSOAPBody
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 theSOAPBody
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
methodgetChildElements
. 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 theName
object used to name an element, you can supply that togetChildElements
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 ajava.util.Iterator
object. You access the child elements by calling the methodnext
on theIterator
object. The methodIterator.hasNext
can be used in awhile
loop because it returnstrue
as long as the next call to the methodnext
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 aSOAPBodyElement
object, which is why callingiter1.next
returns aSOAPBodyElement
object. Children ofSOAPBodyElement
objects and all child elements from there down areSOAPElement
objects. For example, the calliter2.next
returns theSOAPElement
objectchild2
. Note that the methodIterator.next
returns anObject
, which has to be narrowed (cast) to the specific kind of object you are retrieving. Thus, the result of callingiter1.next
is cast to aSOAPBodyElement
object, whereas the results of callingiter2.next
,iter3.next
, and so on, are all
cast to aSOAPElement
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 buildWith the code compiled, you are ready to run
MyUddiPing
. The following command will calljava
on the.class
file forMyUddiPing
, which takes two arguments. The first argument is the fileuddi.properties
, which is supplied by a property set inbuild.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 thebuild.xml
file. The last argument supplied toAnt
is always the target, which in this case isrun
.cd <JWSDP_HOME
>/samples/jaxm/myuddiping ant -Dbusiness-name="Oracle" runHere 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 thebusiness-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 ManufacturerSOAPFaultTest.java
The code
SOAPFaultTest.java
, based on the code fragments in a preceding section (SOAP Faults) creates a message with aSOAPFault
object. It then retrieves the contents of theSOAPFault
object and prints them out. You will find the code forSOAPFaultTest
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 filebuild.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 runSOAPFaultTest
, compilingSOAPFaulTest.java
, putting the resulting.class
file in thebuild
directory, and runningSOAPFaultTest
.To run
SOAPFaultTest
, do the following:
- Go to the directory where the appropriate
build.xml
file is located.cd <
JWSDP_HOME
>/docs/tutorial/examples/jaxm/fault
- At the command line, type the following:
ant prepare
- This will create the
build
directory, the directory where class files will be put.- At the command line, type
ant build
- This will run
javac
onSOAPFaultTest.java
using the classpath that has been set up in thebuild.xml
file. The resulting.class
file will be put in thebuild
directory created by the prepare target.- 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, therun
target depends on thebuild
target, which in turn depends on theprepare
target, so theprepare
,build
, andrun
targets will be executed in that order. As an even faster shortcut, you can type justant
. The default target for thisbuild.xml file
isrun
, so it has the same effect as typingant run
.If you want to run
SOAPFaultTest
again, it is a good idea to start over by deleting thebuild
directory and the.class
file it contains. You can do this by typing the following at the command line:ant cleanAfter 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 codeConclusion
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
andSOAPFaultTest
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.
Home
TOC Index |
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.