Dynamic JMS endpoints

In an earlier post I promised an example of where service integration bus mediations still have a role to play in a WebSphere ESB environment. WebSphere ESB currently only supports dynamic endpoints on an import or callout (those that can be changed at runtime by a mediation flow) for SCA and web service bindings. In this post I’ll show how a service integration bus mediation can be used to add dynamic behaviour to a JMS binding.

Before continuing, I should say that there is more than one way to implement this behaviour. You could, for example, remove the import completely and replace it with a Java component that simply makes the appropriate JMS calls to send the message to a destination selected dynamically. I prefer the approach outlined here though as it means you maximise the use of the normal WebSphere ESB functionality such as serializing the business object in to the JMS message.

At a high level, what I’m going to suggest is that you use a regular JMS binding defined to use a static destination and then you apply a service integration bus mediation to that destination to perform the dynamic routing. The first issue to resolve is how the mediation module indicates to the service integration bus mediation where the message should be routed. I’m going to use a JMS user property to pass the destination name. The following shows how a custom Java primitive can be used to set a JMS property via the service message object header properties.

In this example, the destination name is pulled directly out the body of the request but you might, for example, obtain it from a registry lookup. Note that I explicitly create the JMS header although I don’t appear to use it. This is important as it is the presence of this header that causes the header properties to be written out as JMS properties in the message.

I won’t go in to the details of creating the service integration bus mediation – you can read all about that in Dan Murphy’s series of developerWorks articles. The important part is the handler code that retrieves the JMS user property from the message and uses it to reroute the message:

The only real thing to note here is that the forward routing path returned from the getter method is a copy of the list so that you need to set it back again once you have added the new destination.

For the simple case, that’s all there is to it. The particular scenario I was interested in though was using publish/subscribe and it was the topic that I wanted to dynamically route to, not the destination. I used the same approach as outlined above, passing the topic name as a JMS user property instead. The code in the mediation handler then looked as follows:

The discriminator is what the service integration bus programming model calls the topic name within a topic space. I had the mediation module send the request to a particular topic within the required topic space and then, when applying the service integration bus mediation to that topic space, I specified that topic name as the discriminator. This ensured that the mediation is only driven when a message arrives at that particular topic.

It was at this point that I realized a flaw in this approach. The destination name contained in the JMS message is not altered by the modifications made in the mediation handler. Generally this isn’t a problem as the receiving client either doesn’t care or knows what destination it connected to in order to receive the message. However, in my case the consumer is using a topic wildcard to receive messages and it is important that it knows what topic the message was actually received on as it is then going to republish them to the corresponding topic in another publish/subscribe system. (For the curious, the client is the JMS bridge in MicroBroker.)

At this point I threw away my service integration bus mediation and wrote a message-driven bean to receive the messages from the mediation module and republish them to the required topic. The JMS destination for the send was simply created using Session.createTopic(). In my case I just needed to pass this the topic name but, if you need to redirect to something other than the default topic space, then you need to be aware of the URI syntax outlined in the InfoCenter. Note that, in a point-to-point scenario, this approach might not be appropriate as it results in a change in the message identifier. In publish/subscribe the publisher and subscriber get different identifiers anyway.

12 Responses to “Dynamic JMS endpoints”

  1. Handy technique. Thanks for the write-up.

  2. harish says:

    Hi,

    I have a scenario in ESB, where currently i have configured three queues(Queue1,Queue2,Queue3)
    based on my routing logic the message will be routed to the respective queues.

    In future we might add more queues to the same routing logic, i.e for a single condition the message can be routed to more than one queues. This should be done without modifying the Mediation Module.

    The goal is to make the mediation process configurable, so that it can be used to route and filter incoming messages to multiple queues to help scale the message processing.

    My version of WID is 6.1.2

    Thanks in Advance for any kind of help

    • Dave says:

      I believe I’ve also replied to your question on one of the forums where I suggested the other approach (using a Java component). As of 6.2 there is still nothing out-of-the-box that will help you with this particular scenario.

      David

  3. harish says:

    Hi Dave,

    Using dynamic endpoints overridng the SMOHeader and update the Target address, we are able to send messages to any queue dynamically,

    syntax:
    jms:/queue?destination=jms/WSjmsExport&connectionFactory=jms/WSjmsExportQCF&targetService=JmsImPort

    The one problem i am facing here is, i want to send the message as Text message, but it sends the message as byte message. Also i have configured the target service as a JMSImport component, where i have specified the custom data binding to send the message as Text message

    But it doesn’t recognize the custom binding, when we override the SMOHeader.

    How to send text message using Dynamic Endpoint.

    Any idea?

    • Dave says:

      Harish,

      So, you are correct that a SOAP/JMS binding does allow you to dynamically override the endpoint which at least gives you the flexibility to chose between a set of preconfigured JMS destinations. A description of the SOAP/JMS protocol implemented by WebSphere can be found in the Application Server InfoCenter. As you will see, although WebSphere will accept both text and bytes messages, a WebSphere web service client will only ever send bytes messages.

      If you switch to use a JMS binding then you have control over the type of the message but you can’t use the dynamic endpoint support. That was the point of this blog posting!

      Regards,
      David

  4. Teja says:

    Hi Dave,
    I have a scenario in ESB, where we need to write a generic mediation flow to get dynamic endpoints using WSRR EndpointLookup node and invoke the service just by taking service name and version as dynamic input. So that i will have just one generic mediation flow to locate any service endpoint and invoke any service. Is it possible to write common WESB mediation module for this scenario? if so, please advise me with implement details.

  5. Vivek says:

    Hi Dave,

    I have a scenario, where we have to avoid custom java component in place of java import and to route the messages to a topic dynamically by picking up the topic name using DB lookup.

    Is there any way other than the above 2 apporaches of custum SIB handler and custom import component that I can modify the JMS headers and route it to the destination? If so could please advise me with the implementation details.

    Thanks,
    Regards,
    Vivek

    • Dave says:

      Hi Vivek,

      Sorry – I don’t believe dynamic routing to different topics is possible out of the box even in 6.2 although it is on the to-do list…

      Regards,
      David

  6. Vivek says:

    Hi,

    I am trying to use the ServiceManager api to invoke a service from the custom mediation using service.invoke. I need to set some JMS headers and end point reference in my code for calling this service. I did not understand how do we set the custom jms headers (set as propertyset in the smo) as we are sending the sdo in the invoke operation. I could notice that if we set in the property set it does not get set in the message that gets published to the queue.

    Could you please help me understand if there is any way where I can invoke a service in custom mediation after setting the jms headers.

    Thanks in advance.

  7. Ritesh says:

    Hi vivek,

    Is their is any way to modify the content of JMSReplyTo value which is in JMSHeader.

    I have a scenario where Provider send me the Queue information , but i have to ignore same and forced ESB to look up for JNDI name.

    Ritesh