Dynamic Endpoint Address Resolution in Spring Integration (SOAP and ReST)

Every now and then I get a bit lazy. I’ll be working on a task and realize I’ve done something one time too many. It’s in those “this nonsense must stop” moments that I tend to do a bit of soul (read web) searching and find easier ways to do stuff.

One such moment came last year when I was working on a Spring Integration based Enterprise Service Bus (or ESB) for an internal project. I had two problems:

  1. I wasn’t too keen on the idea of restarting our service anytime we wanted to go live with a new connection (this is mainly because I haven’t yet figured out how to get a new flow dynamically loaded. I’ll write about it when I do ;)). I mean, an ESB is supposed to help you AVOID such integration challenges.
  2. I really didn’t want to have to create a new flow every time we needed to integrate a new web service.

So, with these coding pains nibbling away at me I decided to get some first aid.

The simple solution, of course, would have been to use a Spring Integration router to determine the destination endpoint based on a parameter (preferably passed in the message header). However, this presupposes that you know all the possible endpoints you will ever want to connect to, which isn’t very practical! Luckily for me (and with thanks to Google and Stack Overflow) I found some gateway attributes that made this possible. The only thing I needed to make it work was to upgrade to Spring Integration 4.1+.

ReST Endpoint Resolution

So the first scenario was dynamically resolving a ReSTful endpoint address. This was pretty simple: I just needed to determine the URL in code (load from a DB, construct based on user input, etc) and pass it to the flow as a header parameter. So assuming your parameter was called serviceURL, you would add the mapped-request-headers attribute to your inbound gateway like so:

and then on the outbound gateway use url-expression instead of url to fetch the service endpoint address from the header:

Aaaand we’re done! Notice that although my header was called “serviceURL”, I referred to it as “headers.serviceurl”. This is NOT because it’s case insensitive. On the contrary, Spring Integration converts all inbound header names to lower case so it will actually fail if you use “headers.serviceURL” in the URL expression. I had to find that out the hard way, eventually logging my message header to see what was going on.

As some added sugar, if you’re connecting to various services or even a single service using different HTTP verbs for different functions, you can also pass the verb along in the header, include it in the mapped headers and add the following attribute to the outbound gateway:

And just in case you’re wondering how to pass these headers, they’re added as regular HTTP headers in your call to the inbound gateway.

That’s it for ReST.


SOAP Endpoint Resolution

Routing SOAP requests isn’t any more difficult that ReSTful ones. Once again, the inbound gateway should have the needed headers mapped. Afterwards, just make sure you set the following three attributes accordingly

I’ll explain this a little.

  • A URI variable was added so that it could be used in building the endpoint URI. Normally you could do something like “http://api.remote.com/soap/service/{version} “ with “version” being a uri parameter. In the code snippet above, I just passed the entire URI as the URI variable.
  • Encode – uri was set to false because I was passing the entire URI. I didn’t want it URL encoding my slashes and colons!
  • As mentioned already, the URI was just set to the previously declared variable.

That’s all there is to it!

Other Thoughts

This is obviously not the only way to go about it but it worked fine for my purposes. In my case I had two flows: one for ReST and one for SOAP. For those who want a single flow, they could just as easily use a parameter router to switch between the ReST and SOAP gateways and then have the actual endpoint address determined as mentioned above. In addition, some services may have additional requirements such as a security header, etc.

These can all be worked into a single (extremely complex) flow or broken down into a number of separate flows, each handling distinct requirements. However, that’s a topic for another day. For now, I’m out!

1 Comment

  1. Pingback: Dynamic SOAP Header Injection With Spring Integration – My Coding Pains

Leave a Comment

Your email address will not be published. Required fields are marked *

captcha * Time limit is exhausted. Please reload the CAPTCHA.