Announcement Announcement Module
No announcement yet.
1 Outbound Webservice Gateway, Multiple Credentials Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • 1 Outbound Webservice Gateway, Multiple Credentials

    Can anyone help, I can't decide the best way to do this.

    I have a web service that I'm consuming and it's secured via HTTP Basic so I have an outbound web service gateway wired up with Apache http client (with usernamepassword credentials set) as the message sender. All works fine. The problem is that depending on a message header I need to provide different credentials. So one message might be with user A's credentials and another with user B's. I can't seem to dynamically set these at runtime so I thought about having multiple outbound gateways configured with the different credentials and then routing accordingly. Whilst this is fine in development I'm not sure how this will work in production because I don't want the production support team to have to modify Spring config files every time a new set of credentials needs to be added. They're happy changing property files across environments or having different database scripts but don't seem happy changing config files. Any suggestions??

    edit: I'm thinking of maybe writing a custom namespace handler to do this with a comma separated property of "headervalue,username,password,headervalue,usernam e,password,......" and then creating the required gateways
    Last edited by rhart; Nov 15th, 2010, 05:10 AM.

  • #2
    My initial reaction is that this would be a good case for custom implementation of the requestFactory. You could create one that delegates to the same httpclient-based one you are using now but only after determining the given user from something in the context (e.g. a ThreadLocal). This would be similar to the way AbstractRoutingDataSource works in Spring:

    I would imagine that a common solution would be to rely on Spring Security as well, since the SecurityContext would then be available as a ThreadLocal already.

    Let me know if this idea makes any sense.


    • #3
      I think I understand what you mean. Are you basically saying that the dynamic lookup of credentials is the way to go and I could achieve this by creating my own implementation of a MessageSender that delegates to CommonsHttpMessageSender to do the work. It would create a new instance of CommonsHttpMessageSender for each web service call and set the correct credentials to use based on something set in the context to look them up?


      • #4
        Yes. That's basically what I'm saying. If you look at the way AbstractRoutingDataSource works, it is actually using a Map so that they key is based on something determined at runtime (usually a ThreadLocal), and the values in that map would be the actual DataSource instances. If you were to follow a similar approach, the values in your Map would be the MessageSender instances. If you need to create new ones on demand at runtime, that would probably not be too difficult to do... just add to that same Map so that the instance only has to be created once.


        • #5
          Ahhh yes, caching instances created at runtime in the map is a good idea. I'm gonna give this a go.


          • #6
            Great! Keep us posted. It sounds like a potentially valuable contribution, and it would not only be useful for Spring Integration but for any Spring-based HTTP client code.



            • #7
              So far my quick POC looks like this

              public class DelegatingMessageSender implements WebServiceMessageSender {
              	private ThreadLocal<String> lookupValue;
              	public void setLookupValue(String value) {
              	private Map<String, WebServiceMessageSender> messagerSenders;
              	public void setMessagerSenders(
              			Map<String, WebServiceMessageSender> messagerSenders) {
              		this.messagerSenders = messagerSenders;
              	public DelegatingMessageSender() {
              		lookupValue = new ThreadLocal<String>();
              		messagerSenders = new HashMap<String, WebServiceMessageSender>();
              	public WebServiceConnection createConnection(URI uri) throws IOException {
              		WebServiceMessageSender messageSender = messagerSenders.get(lookupValue.get());
              		return messageSender.createConnection(uri);
              	public boolean supports(URI uri) {
              		WebServiceMessageSender messageSender = messagerSenders.get(lookupValue.get());
              		return messageSender.supports(uri);
              And I have a service activator with this DelegatingMessageSender injected so I can set the thread local variable.