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:
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:
- Set up the project using Maven.
- 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.xmlto make it easier to deal with setting attributes of large data structures.
- Create two classes: A
Client.javafile for interfacing with the generated SOAP client, and a
Proxy.javafile for setting up Spark routes that accept JSON as input. The input is converted to a POJO and passed along to the
Client, in turn, contains methods that return
Objects. Endpoints in the
Proxythat invoke methods on the
Clientalways return the corresponding
Clientmethod’s output. Jackson takes care of serializing the object to JSON.
- Create a subpackage to house any input POJOs used by the Jackson deserializer. Take note of the
@JsonPropertyannotation, useful for defining optional items for input.
- Create a subpackage to house any custom CXF interceptors to handle weird things about the API you happen to be integrating with.
- Use Mockito and PowerMock in conjunction with JUnit to help with unit testing.
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.
Senior Software Engineer