Priority with activemq - java

We're currentyly developping an application using JMS and activemq (5.5.1).
We would like to define a higher priority for some messages, which would make them consumed first.
After setting the producer and the consumer (through spring (3.1) JMSTemplate), the priority does not fully work.
Indeed, when we "turn off" the consumer, and send some messages, the priority is respected, but when we add messages while the consumer is on, the messages are received in the same order they were sent.
The configuration is quite simple:
Priority was activated in the activemq config file:
<policyEntries>
<policyEntry queue=">" prioritizedMessages="true"/>
...
</policyEntries>
And QoS was enabled in the producer template configuration:
<bean id="jmsOCRTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="defaultDestination" ref="destination_ocr" />
<property name="explicitQosEnabled" value="true" />
</bean>
To send a message with a high priority, we just change the template priority property on the producer side:
template.setPriority(9);
Any idea? Is this the normal behaviour, or is there some configuration we would have forgotten?

If my opinion you are not missing anything, I had a similar issue a couple of weeks ago (but with TTL and QPid).
First the JMS is not Strict about this :
JMS does not require that a provider strictly implement priority ordering of messages; however, it should do its best to deliver expedited messages ahead of normal messages.
Second, ActiveMQ does not YET implement priority queues, they say it will somewhere in 6.x version.
So, what you see is actually normal.
As a work-around you can use the Resequencer pattern if it fits your case.
http://camel.apache.org/resequencer.html
Here is another discussion on this subject:
http://activemq.2283324.n4.nabble.com/Priority-message-td2352179.html

I know it is late but this answers may help somebody.
If you want your consumer to consume message based on priority (Priority Queue) then you can use client side message priority. This means, when messages are being sent to your consumer (even before your consumer is receiving them, using prefetch), they will be cached on the consumer side and prioritized by default. This is regardless of whether you’re using priority support on the broker side. This could impact the ordering you see on the consumer so just keep this in mind.
To enable it, set the following configuration option on your broker URL, e.g.,
tcp://0.0.0.0:61616?jms.messagePrioritySupported=true
To disable it, tcp://0.0.0.0:61616?jms.messagePrioritySupported=false
So you do not require to use Camel (if you want to avoid complication)

Related

on-demand/trigger based camel route

I'm trying to implement the following JMS message flow using camel routes:
there is a topic published on external message broker. My program is listening for messages on this topic. Each incoming message triggers specific route to be executed - ONE TIME ONLY (some kind of ad-hoc, disposable route). This route is supposed to move messages between queues within my internal message broker based on some selector (get all messages from queue A matching given selector and move them to queue B). I'm only starting with camel and so far I figured out just the first part - listening for messages on topic:
<bean id="somebroker" class="org.apache.camel.component.jms.JmsComponent"
p:connectionFactory-ref="rmAdvisoriesConnectionFactory"/>
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<endpoint id="jms" uri="somebroker:topic:sometopic"/>
<route id="routeAdvisories">
<from ref="jms"/>
<to>???</to>
</route>
</camelContext>
Can you suggest a destination for these advisory messages? I need to read some of their JMS properties and use these values to construct JMS selector that will be used for the "move messages" operation. But I have no idea how to declare and trigger this ad-hoc route. It would be ideal if I could define it within the same camelContext using only Spring DSL. Or alternatively, I could route advisories to some java method, which would be creating and executing this ad-hoc routes. But if this isn't possible, I'll be grateful for any suggestion.
Thanks.
As far as I understand, it will be useful to use the 'selector' option, in your JMS consumer route, for example:
from("activemq:queue:test?selector=key='value1'").to("mock:a");
from("activemq:queue:test?selector=key='value2'").to("mock:b");
Maybe, another option is to implement some routes based on 'Content Based Router Pattern" through "choice" option. You can find more info here: http://camel.apache.org/content-based-router.html
I hope it helps.
I couldn't get it working the way I intended, so I had to abandon my original approach. Instead of using camel routes to move messages between queues (now I'm not sure camel routes are even intended to be used this way) I ended up using ManagedRegionBroker - the way JMX operation "moveMatchingMessagesTo" is implemented - to move messages matching given selector.

How to write camel route that handles request concurrently

I am trying to write a camel route that consumes incoming message from a JMS queue and handles them concurrently in different threads. The camel route I have got is like this:
<camel:endpoint id="requestQueue" uri="jms:queue.request" camelContextId="camel"/>
<camel:endpoint id="responseQueue" uri="jms:queue.response" camelContextId="camel"/>
<camel:camelContext id="camel">
<camel:threadPool id="serviceThreadPool" poolSize="10" threadName="workerThread" maxPoolSize="20"/>
<camel:route id="requestServingRoute">
<camel:from ref="requestQueue"/>
<camel:threads executorServiceRef="serviceThreadPool">
<camel:to uri="bean:doSomething"/>
<camel:to ref="responseQueue"/>
</camel:threads>
</camel:route>
</camel:camelContext>
However, what I can observe is that the incoming message is indeed handled by separate threads, but they are handled in a sequential order.
What I tried to achieve is that camel handles each request in the doSomething bean in separate threads for each incoming request.
How can I achieve this?
Thank you very much.
You need to specify the number of concurrent consumers for the JMS request queue. See http://camel.apache.org/jms.html. You don't need to message around with the thread pools. eg in Java DSL syntax you would write something like:
from("jms:queue.request?concurrentConsumers=10")
.beanRef("bean", "doSomething")
.to("jms:queue.response)

Asynchronous send to a queue using Spring Jms issue

I have a requirement when I need to write asynchronously to a queue in activemq. I am using Spring Jms to do it. This is the wiring in my spring context file
<bean id="amqProducerConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="${activemq.broker}"/>
</bean>
<bean id="pooledProducerConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop" lazy-init="true">
<property name="connectionFactory" ref="amqProducerConnectionFactory" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="pooledProducerConnectionFactory" />
</bean>
And in my code...i do..
void sendMessage(JmsTemplate jmsTemplate, String message, String requestQueue) {
def messageCreator = { session ->
session.createTextMessage(message)
} as MessageCreator
jmsTemplate.send(requestQueue, messageCreator)
}
But the above seems to be working synchronously, not asynchrously. Is there anything that I need to add here that makes the process asynchronous(I mean, App 'A' writes to a queue. It should write to the queue and forget, not wait until App 'B' picks it up from the queue and processes it.)
The JmsTemplate send is never synchronous in terms of waiting for a consumer to take a Message of the Queue in the normal case. The send can however be synchronous in that it waits for a response from the Broker indicating that it has received and stored the Message. This is so that you have an indication of success as Queues must ensure that they are reliable. You can configure many things in the ActiveMQConnectionFactory to control this. Setting the options useAsyncSend will enforce that your send don't wait for a Broker ACK if that is what you want. These options are all documented.
You configure these on the connection URI like so: tcp://localhost:61616?jms.useAsyncSend=true
A send can however block if the ActiveMQ Broker's producer flow control kicks in to prevent a Producer from flooding the Broker with messages. This is configurable as well both in terms of disabling it altogether and also in that you can increase the memory limits on the Broker for when this might kick in.
Finally a Producer send could block if the Connection to the broker is lost and you are using the Failover Transport to have your client automatically reconnect.

Topic creation in ActiveMQ

http://docs.oracle.com/javaee/1.4/api/javax/jms/Session.html#createTopic(java.lang.String)
This API says that session.createTopic(topicname) is not for creating the physical topic. What does this mean?
If I want one group of user which has authority of "admin" is responsible for creating topics and another group of user which has authority of "write" is responsible for publishing messages to this topic, how can I implement this? It seems that the latter group must also have the authority of "admin" because they have to use this method: session.createTopic(topicname).
How can I separate the "admin" and "write" authority?
What the JMS spec means is that createTopic(String) is used to give you a logical handle (javax.jms.Topic, a subtype of Destination) which you can subsequently use in other calls such as createProducer(Destination) or createConsumer(Destination). It just so happens in ActiveMQ that a physical destination will be created at the same time.
If you want to make sure that users can only publish to already created destinations, assign that group read and write permissions, but not admin. Obviously that assumes that those topics already exist - if they do not, then you'll get an exception thrown.
You haven't said exactly how you would like to administer topic creation, but if you are OK with doing that in the ActiveMQ config for them to be created at startup, then define those topics in a destinations block:
<broker xmlns="http://activemq.apache.org/schema/core">
<destinations>
<topic physicalName="topic.1" />
<topic physicalName="topic.2" />
</destinations>
</broker>
The JMS api is not for administration, only for using existing topics and queues. In ActiveMQ, default is that the physical queue/topic does is auto-created once needed (someone is sending to it/consuming from it).
How to create physical objects in a JMS implementation is vendor specific and you should checkout how this is handled in ActiveMQ.
How this is treated in AMQ

Spring - Async Queue for sending mail

I have this:
<si:poller max-messages-per-poll="10" id="defaultPoller" default="true">
<si:interval-trigger interval="5000"/>
</si:poller>
<si:channel id="emailIn"/>
<si:channel id="emailOut"/>
<si:service-activator input-channel="emailIn" output-channel="emailOut" ref="mailService" method="recieveMessage"/>
<si:gateway id="gateway" service-interface="com.blah.MailSender" default-request-channel="emailIn"/>
<si:outbound-channel-adapter channel="emailOut" ref="mailService" method="recieveMessage" />
And I thought what I was configuring was an async Queue. I want to be able to drop messages onto it, and have a nother thread pick them up and process then later. However, at the momment it seems to do it in a synchronous way.
Am i doing it wrong (obvioulsy yes), but wondering if there is something i'm missing in this config, or whether i just have the wrong approach?
Cheers
By default all channels in Spring Integration are synchronous. This is a conscious design decision that will help you keep transaction boundaries and security contexts for example. When you want to do asynchronous hand-off you should add a task executor to your dispatcher or a queue to your channel:
<channel>
<dispatcher task-executor="pool"/>
</channel>
<channel>
<queue capacity="10"/>
</channel>
Look at channel configurations in the reference guide for some details on dispatchers and queues. See also the section on DirectChannel and the section on ExecutorChannel below that one.

Categories