O'Reilly logo

Java SOA Cookbook by Eben Hewitt

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Monitoring SOAP Traffic with Metro

Problem

You’re using Glassfish/Metro and you want to dump the transport-level traffic that your web service client sends and receives to the console.

Solution

Pass the flag -Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true to your JVM.

This dump technique shows you the bytes representing the message as it is sent and received on the wire. That means that you also get transport-specific information, such as all HTTP headers, which can be useful.

You can also do this in Ant with jvmarg:

<target name="run">
    <java classname="com.soacookbook.ch03.MyClient" fork="true">         
        <arg value="someArg"/>
        <classpath>
          <path refid="jaxws.classpath"/>
          <pathelement location="..."/>
        </classpath>
        <jvmarg value="-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=
         true"/>
    </java>
</target>

Note that the JUnit Ant task will accept the jvmarg element too, so you can easily add it to invocations that you test on your client as well. See Example 4-5.

Example 4-5. JUnit Ant task with SOAP message dumping enabled

<target name="run-test" depends="compile-test">
<echo message="-----Running Tests-----" />
<junit fork="true" printsummary="true" 
       errorProperty="test.failed" 
       failureProperty="test.failed">
    <classpath refid="cp.test" />

    <jvmarg 
    value="-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true"/>

    <formatter type="brief" usefile="false"/>
    <formatter type="xml"/>
    <batchtest todir="${test.report.dir}">
        <fileset dir="${test.classes.dir}" 
          includes="**/*Test.class" />
    </batchtest>
</junit>

<echo message="-----Creating JUnit Report-----" />
<junitreport todir="${test.report.dir}">
    <fileset dir="${test.report.dir}" includes="TEST-*.xml"/>
    <report format="frames" todir="${test.report.dir}"/>
</junitreport>

<fail if="test.failed" 
   message="Tests failed. Check log and/or reports."/>
</target>   

This is an easy way to get lots of information about what’s going on behind the scenes in your SOAP message invocation. If you have improperly constructed a message, for example, this can be a terrific aid in finding the issue.

Example 4-6 shows the output that the HttpTransportPipe dump operation gives you during a JUnit test invocation of a web service client talking to a credit authorizer web service (I added line breaks only for readability).

Example 4-6. Output of HttpTransportPipe during JUnit test

4/27/08-14:40 DEBUG  com.soacookbook.ch03.test.SchemaValidateTest.testCreditAuth - 
Invoking Credit Authorizer Service.
---[HTTP request]---
SOAPAction: ""
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Content-Type: text/xml;charset="utf-8"
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body><creditCard xmlns="http://ns.soacookbook.com/credit">
<cardNumber>4011111111111111</cardNumber>
<name>
<firstName>Phineas</firstName>
<middleInitial>J</middleInitial>
<lastName>Fogg</lastName>
</name>
<expirationDate>2015-04-27-07:00</expirationDate>
</creditCard>
</S:Body></S:Envelope>--------------------

---[HTTP response 200]---
Transfer-encoding: chunked
null: HTTP/1.1 200 OK
Content-type: text/xml;charset="utf-8"
Server: Sun Java System Application Server 9.1_01
X-powered-by: Servlet/2.5
Date: Sun, 27 Apr 2008 21:40:44 GMT
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<authorization xmlns="http://ns.soacookbook.com/credit">
<amount>2500.0</amount>
</authorization>
</S:Body></S:Envelope>--------------------

There is a corresponding class available on the server side that lets you dump messages for incoming traffic to the console.

Note

If you are invoking your web services through a web page, it is also convenient to use the Firefox plug-in called Live HTTP Headers, which shows the HTTP headers for every request and response in a window. You can get it at https://addons.mozilla.org/en-US/firefox/addon/3829.

Discussion

The disadvantage to using monitoring GUI tools, other than the fact that you need a GUI environment to run them, is that they use a man-in-the-middle strategy that requires rerouting the destination of your messages. Here’s how they work: the monitor receives your request, dumps the payload, and then forwards your request to its intended destination. So, you are forced to change your service client to point to the port on which the monitor listens. Setting HttpTransportPipe.dump=true allows you to see the content of your messages with less error-prone twiddling. It can be easier, quicker, and cleaner to set up a console dumper like this as you are getting started.

Note

Using the console dumper is not appropriate for production situations, but it can save you lots of time during development.

Dumping during a Maven unit test run

It is useful to see the SOAP messages being passed during an execution of unit tests. This is easy to do if you are running your build directly from the command line or from within an IDE, both of which offer a clear way to send arguments to the VM during execution.

But if you’re building from Maven 2, it may not be immediately apparent how to get this to work. All you have to do is add a system property to the Surefire plug-in, like this:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.4.3</version>
  <configuration>
    <systemProperties>
      <property>
        <name>wsdlLocation</name>
        <value>${my.wsdl.url}</value>
      </property>
      <property>
        <name>com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump</name>
        <value>true</value>
      </property>
    </systemProperties>
  </configuration>
</plugin>

This will create the same effect as passing the argument directly to the VM as you would with -D.

Transport-independent logging

The preceding examples work if you are using HTTP as the transport layer. If you are using a different protocol, you need a transport-agnostic class. Using basically the same mechanism just described, you can substitute this invocation instead:

com.sun.xml.ws.util.pipe.StandaloneTubeAssembler.dump=true

See Also

Other tools are available as well. Check out the WS Monitor tool at https://wsmonitor.dev.java.net, and for Axis, TCPMon at http://ws.apache.org/axis/java/user-guide.html.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required