I'm working on building a few JMS triggers in webMethods.
I would like to filter my messages based on certain conditions in the payload of the message which is part of JMS Message body string. As I understand JMS message selector will not do this filtering. I'm trying to see if Xquery is able to do this for me.
Any idea if Xquery can extract the value of a field hidden inside an XML (which is present inside the JMS Message body string)?
JMS triggers cannot filter on values other than those in the JMS message header.
To achieve what you want you can either:
Extract the value you want to filter on and add it to the JMS message header prior to enqueuing the message, or
Check the JMS message body yourself in your trigger service, and decide whether to process the message or ignore it depending on the result of your check.
By spec, that's not supported. I suppose some JMS impl might have a proprietary feature like this (ActiveMQ perhaps ?), but you should probably look at implementing a message router like Apache Camel or Spring Integration.
Related
I'm using Camel with JMS and Spring Boot and would like to build a route for next scenario:
User 1 (MQTT client) sends a message (topic) to ActiveMQ Artemis.
Camel (by using from) catch that message and print it out with a help of log.
Thing I would like to do is - create a new thread (asynchronous) for caught message. Send that message from Camel to microservice (python program) that should take message and insert some extra strings, and then send changed message back to Camel and ActiveMQ.
On the end, from ActiveMQ changed message will be sent to User 2.
Can you give me some directions or route examples of how to do something like that?
So, key points are to create new thread for every message and create route to and back from that microservice.
The route could look like this
from("jms:queue:inputQueue")
.log("${body}")
.to("http://oldhost")
.to("jms:queue:outputQueue")
Some notes:
You can call a downstream HTTP endpoint with .to(). The current message body is used as request body. The response of the service overwrites the message body.
I don't know why you want to create a new thread for a synchronous call. You can leverage parallel processing by consuming multiple messages from Artemis in parallel with multiple consumers. Like this, every message is processed in its own thread. If your motivation is resilience, there is also a Circuit Breaker EIP in Camel
If you use Camel 2.x, use the HTTP4 Component ("http4://") to use the newer HTTP client lib. In Camel 3.x the old one was dropped and the new one is simply called HTTP component
Spring Integration Dynamic Selector for JMS messages
I have a requirement to use dynamic selectors to retrieve messages from the queue. For example i need to get messages from the queue at regular intervals that are > then 1 hr old. It seems the message selector is initialized just once . Can it be changed everytime the poller is used? and how?
With the polled adapter, you can use a Smart Poller to change the selector expression before each poll; call setMessageSelector() on the JmsDestinationPollingSource.
You cannot dynamically change the selector on a message-driven adapter; you have to stop the adapter first.
In weblogic it is possible to create a message bridge between two JMS message queues. While configuring this bridge, a message filter can be applied so that the bridge will route messages that match the filter only.
Is it possible to achieve the same with Websphere?
Specifically I'm trying to achieve this scenario.
I have one source queue on which messages are received. Each message will have a custom JMS property set up. I would like to forward the messages on the source queue, to separate queues based on the JMS property and its value. This is easily configured in WLS using message bridges with filtering. How can I do the same in WAS?
Thanks
Savio
You need to use SIB Mediation.
The WAS info center have an example called writing a routing mediation which seems like what you need.
At the bottom of the example there is a link to what to do next which also explains how to configure WAS to use that mediation.
Without writing custom code (as per your comment on Aviram's answer), it is not possible to achieve the exact same thing, but nonetheless it is possible to achieve same effect;
You say that a 'source queue' distributes messages to other 'separate queues' according to a custom JMS property. I'm assume that you have MDBs (message driven beans) configured to process messages in these separate queues.
What you can do with WebSphere is distribute messages to these MDBs directly from the 'source queue', without having to filter/distribute them to separate queues.
This is managed by using JMS Message Selectors. You can point all your MDBs to the source queue using activation specification definitions, and for each (one for each type of message) MDB, define a JMS Message Selector that matches the ones you use in WLS. This way each message is only delivered the MDB whose filter matches the message's properties. This effectively filters/distributes messages to different MDB's as in WLS.
You may read details on configuring message selectors (during development in RAD, or at/after deploy time) at infocenter. Below is a quote to give you an idea about what it look like;
messageSelector
This attribute determines the JMS message selector
that is used to select which messages the message-driven bean
receives. For example:
JMSType='car' AND color='blue' AND weight>2500
The selector string can refer to fields in the JMS message header and
fields in the message properties. Message selectors cannot reference
message body values.
For the record, we finally ended up writing our own routing algorithm within the application to ensure that messages are sent to separate queues for each client. This way we are independent of app server implementations and the integration effort is the same across app servers, viz., adding custom queues per integrating client.
In brief, We published a JMS custom property that must be set. Using a published convention, we look up for a queue and send responses to the queue. If the property is not set, a default queue is created to route all messages. If the property is set, and the queue cannot be found an exception is raised and processing halted.
This suited our purpose. Hope it helps...
When sending (InOnly) JMS messages with Apache Camel, can I read back the different JMS headers that might have been set automatically on the message, when it was sent?
from("foo:bar")
.to(ExchangePattern.InOnly,"jms:queue:whatever")
.log("msg id set = ${in.header.JMSMessageId}");
I just can't figure out how to send the message "one way" but keeping the sent JMS message as "in" message in the route afterwards.
Background:
I know that I can present some values, but it would be easier if they where set by the actual JMS implementation. For instance, in this case, I want to work with WebSphere SIBus, WebSphere MQ and ActiveMQ. It's best to rely on WebSphere MQs internal message id format, because it will only index certain message formats. It might be similar aspects on the WebSphere SIBus implementation.
This feature is available starting at 2.10.3 and 2.11.0.
This is not totally on JMS Queue handler test. So, continue reading.
We have an architecture where spring channel listens to a queue from ActiveMQ. The listener of this queue will receive messages and has a static list of sub-listeners (identified by unique subjects). All the messages will have some parameters including the subject to which this message has to be delivered.
SMSService will drop its messages to the activemq with a subject SEND_SMS. It will be listened either by some HTTP Service or SMPP Service. You can even design your own Listener and wire that as a spring component with the required "subject".
Problem:
There is a better chance that this internal subject might change. This doesn't even throw an explicit Runtime Exception when there are no listeners. Is there a way to test this message being actually received by the intended listener?
`
As tim Bish siad, your problem statement is much too vague.
Have you tried to create your own ActivemMQ interceptor (I do not know if it could be usefull for your problem)