Skip to main content

How to debug SOAP on Mac with tcpdump

I’ve been using several tools to debug SOAP on Mac and Windows. I would like to share my experience in using some of the tools and show some examples.

So far I found four major categories of tools that are useful in debugging SOAP:
  1. Interface listeners such as tcpdump and others
  2. Proxy tools such as TCPMonitor
  3. Servlet filters
  4. Application server logging. For example, Weblogic has a special logging option that dumps SOAP requests and responses to the sever log.
All of these tools have their own advantages and disadvantages. In this article, I will describe the first type - an interface listener tool called tcpdump. I am planning to describe other three categories in the future posts.

The tcpdump is a tool that sniffs IP traffic and dumps it to a file or a standard output stream. It was originally developed by Van Jacobson, Craig Leres and Steven McCanne from the Lawrence Berkeley National Laboratory, University of California, Berkeley, CA. It is open source. The tcpdump documentation and source code is available at http://www.tcpdump.org/. The tcpdump has been ported to many platforms. The version for Mac comes with MacPorts ( http://www.macports.org/).

Here is an example of capturing SOAP traffic where the service is deployed on the local host:

$ sudo tcpdump -i lo0 -A -s 1024 -l 'dst host localhost and port 8080' | tee dump.log

I use sudo because tcpdump requires root privileges to run. In this example, the tcpdump listens to the loopback interface defined on my Mac as lo0 and pipes out the data to dump.log file. To see all available interfaces, run ifconfig or tcpdump with –D option.

The Web service I use in this example is deployed on an instance of Glassfish Open Source Application Server for J2EE 5 (https://glassfish.dev.java.net/). It has a couple of methods:


/**
* Coffee Shop service.
*
* @author mykola
*/
@WebService()
public class CoffeeShop {
@WebMethod
public String getName() {
return "CoffeeShop, Inc.";
}

@WebMethod
@WebResult(name="price")
public int placeOrder(
@WebParam(name="product")
String product) {
int price = -1;
if ("coffee".equalsIgnoreCase(product)) {
price = 2;
} else if ("cake".equalsIgnoreCase(product)) {
price = 5;
}
return price;
}
}


I created a client application and once I call getName() Web service method I’ve got these SOAP request and response in the dump.log file:


Request:



Response:


The tcpdump logs lots of data. For SOAP debugging, we are interested in the <S:Envelope> content and HTTP headers.

This is a quick and dirty way of getting raw SOAP on the wire. The advantage of this approach is that it is not intrusive, i.e. no special client or service configuration is required. It does not affect performance of the web service or the client. It logs every byte in the message, even control symbols, which could be a disadvantage in some cases. The tcpdump would be very hard to use for debugging SOAP over HTTPS. Also, this approach is hard to use in cases where automated SOAP validation is required. I use filters for that. This is a topic for a future post.

I hope this post was helpful. Please let me know if you have any questions or comments. Thank you for reading.


Comments

Popular posts from this blog

Building a Flex project with Ant

Here is a quick sample on how to build a simple Flex "hello world" project with Ant. The "hello world" project contains a src folder with one Flex application file and an Ant build.xml file: ./project_home/ ./src/ app.mxml build.xml The app.mxml is the main module of the project. It simply has a label with a "Hello World!" text: <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Label text="Hello World!"/> </mx:Application> Here is the build.xml source: <?xml version="1.0"?> <project name="fx_practice7" default="all"> <!-- Init the build process --> <target name="init" unless="initialized"> <!-- Name of project and version --> <property name="FLEX_HOME" location="/Users/mykola/java/flex"/>

cucumber-jvm and Android Studio

During this Winter holidays, I've been exploring a Behavior Driven Development and experimented with a couple of testing frameworks: Calabash and cucumber-jvm . In this post, I would like to describe setting up cucumber-jvm for Android Studio projects. I've extended cucumber-jvm examples with a version for Android Studio. Here is a copy in my github branch: https://github.com/mdzyuba/cucumber-jvm/tree/add_android_studio_example/examples/android/android-studio/Cukeulator . In addition to the example code, here is some details on how it was created. Dependencies The cucumber-jvm requires several libraries to be added to a project:  https://github.com/cucumber/cucumber-jvm/tree/master/android I've found it's easier to add those dependencies with the Android Studio project setup dialog because it takes care of the jar versions for you. File > Project Structure > Modules > app > Dependencies > + > Library dependency   > type "cuc

Using FlexUnit for Stress Testing

I saw quite a few questions in the forums on how to stress test a Flex application. I thought about it and came up with an idea that I want to share here. I think FlexUnit can be used for stress testing. It is not that difficult. I simply add multiple test runners for each client application and run all of them asynchronously. Here is the example of the FlexUnit runner: <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" xmlns:flexunit="flexunit.flexui.*" creationComplete="onCreationComplete()"> <mx:Script> <![CDATA[ import flexunit.framework.TestSuite; import test.TemperatureConverterTest; import test.ArrayUtilTest; import mx.collections.ArrayCollection; import flexunit.flexui.TestRunnerBase; [Bindable] public var testClients:ArrayCollection; public var NUMBER_OF_TESTS:int = 100; private function onCreationComple