Finding the clarity beyond SOAP noise

03:22 reading time

Often we don’t have a choice over the systems we integrate with. Not everything can be a simple, self-documented, “RESTful” API.

Consider a SOAP API that requires a standard but uncommonly used feature. The average library in your programming language of choice may not support every SOAP feature under the sun. Even Leapfrog’s own SOAP library for Python is far from feature-complete.

Now consider a diverse stack made up of multiple distinct systems, written in multiple programming languages, for both consumer-facing and internal business procedures.

The promise of SOA through SOAP solutions becomes less and less appealing. At Leapfrog, we’ve found adopting JSON as a lightweight alternative to SOAP in a SOA-inspired platform meets the best of all worlds.

So what about all your vendors that use SOAP?

Fear not! There’s a recipe to solve all your problems:

  1. Apache CXF
  2. The Spark web framework
  3. FasterXML’s Jackson

As much as you may like or dislike Java, a very simple JSON-SOAP “proxy” can be construted with these tools, enabling your stack to pass messages to the SOAP API using JSON. Chances are high that CXF will support the obscure SOAP feature that your API happens to require. If not, it provides an architecture that makes it (relatively) easy to support the feature.

The pattern I usually follow when using these tools to integrate with SOAP services follows:

  1. Set up the project using Maven.
  2. Create a Makefile that fetches the WSDL and (indirectly) uses wsdl2java to generate a static SOAP client. Use the jaxb fluent api plugin in the project’s pom.xml to make it easier to deal with setting attributes of large data structures.
  3. Create two classes: A file for interfacing with the generated SOAP client, and a file for setting up Spark routes that accept JSON as input. The input is converted to a POJO and passed along to the Client. The Client, in turn, contains methods that return Objects. Endpoints in the Proxy that invoke methods on the Client always return the corresponding Client method’s output. Jackson takes care of serializing the object to JSON.
  4. Create a subpackage to house any input POJOs used by the Jackson deserializer. Take note of the @JsonProperty annotation, useful for defining optional items for input.
  5. Create a subpackage to house any custom CXF interceptors to handle weird things about the API you happen to be integrating with.
  6. Use Mockito and PowerMock in conjunction with JUnit to help with unit testing.

The Spark service can be daemonized through daemontools or an alternative, and internal nginx or apache web servers can be configured to proxy to it.

The end result is a web service with HTTP endpoints that accepts JSON, invokes a SOAP service, and returns results in JSON. Now everything that knows how to speak JSON can speak to your SOAP service!

See the next part to prepare for reality.


Ian Melnick
Senior Software Engineer