So I have used Spring integration to link JMS and ActiveMQ as under:-
<amq:broker useJmx="false" persistent="false">
<amq:transportConnectors>
<amq:transportConnector uri="tcp://localhost:0" />
</amq:transportConnectors>
</amq:broker>
<bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory" p:brokerURL="tcp://localhost:61616"/>
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue" c:name="destination"/>
<bean id="testTemplate" class="org.springframework.jms.core.JmsTemplate" depends-on="amqConnectionFactory" scope="prototype"
p:connectionFactory-ref="amqConnectionFactory"
p:pubSubDomain="false"
p:defaultDestination-ref="destination"
p:sessionTransacted="true"
p:receiveTimeout="5000"/>
Now, when I run the test by starting ActiveMQ and then running my application, I see that the messages are published to the "destination" queue from the logs. However, I am not able to retrieve any of these from the queue. Even in JConsole, it shows the queueSize and counts as 0.
How do I make it work so that I can send to and receives messages from this queue? Please help.
Why do you specify the transport connector to: tcp://localhost:0 and the ConnectionFactory URL to tcp://localhost:61616?
I would use the same URL for both.
Related
I am using JMS Connector to connect to IBM MQ. If I use IBM MQ Connector I have option (targetClient="NO_JMS_COMPLIANT") to disable RFH Header from the message. How can I achieve the same thing using the JMS Connector. My JMS config looks like below
<jms:config name="JMS_Config" doc:name="JMS Config" doc:id="b675becf-06f3-4847-bb95-4f468d5353ea" >
<jms:generic-connection specification="JMS_2_0" connectionFactory="WMQ_ConnectionFactory" />
</jms:config>
Connection Factory looks like this:
<bean id="WMQ_ConnectionFactory" class="com.ibm.mq.jms.MQConnectionFactory" name="WMQ_ConnectionFactory">
<property name="transportType" value="1" />
<property name="hostName" value="MQ-SLQ01"/>
<property name="port" value="1414"/>
<property name="queueManager" value="SLQ01"/>
<property name="channel" value="*******"/>
</bean>
JMS Connector config looks like this:
<jms:publish-consume doc:name="Publish consume" doc:id="b1d40cc6-deb0-42f0-aa50-4b230d843794" config-ref="JMS_Config" destination="P2.REQUEST" sendCorrelationId="ALWAYS">
<jms:message >
<jms:reply-to destination="P2.REPLY" />
</jms:message>
</jms:publish-consume>
I have tried adding request queue name with P2.REQUEST?targetClient=1. I could not see any changes.
I doubt the JMS connector allows to select a non-JMS compatible mode that is specific to a broker (IBM MQ). It a generic connector which provides no broker specific features. You should be using the IBM MQ connector for that that already provides that specific feature.
And alternate action you could take would be to disable the RFH2 header by using a setting on the queue.
ALTER QLOCAL(P2.REQUEST) PROPCTL(NONE)
This will strip all properties (RFH2 header) off the message before delivering it to any application that doesn't supply a message handle.
A spring quartz process runs every 15 minutes in my project i.e 96 times a day. This fetch certain records from database and POST it on a REST service (running on JBoss 7). These records are in general 50 to 100 in count.
On REST service there is jms event publisher that publishes this message on a topic. There are two consumers on this topic.
That process message and sends push notification messages on mobile
Talk to third party (generally takes 4 to 5 second to complete the call)
Since it is topic both consumers receive all messages but they filter them out based on some property, so few messages are processed by one and rest by another consumer.
My problem is; which is being observed recently since a week time; that consumer #1 receives response from APNS as invalid token multiple times; token is used to send push notification to mobile; after some time this consumer stops and do not respond at all while second one keeps running.
Below are configurations:
<amq:broker id="broker" useJmx="false" persistent="false">
<amq:transportConnectors>
<amq:transportConnector uri="tcp://localhost:0"/>
</amq:transportConnectors>
</amq:broker>
<!-- ActiveMQ Destination -->
<amq:topic id="topicName" physicalName="topicPhysicalName"/>
<!-- JMS ConnectionFactory to use, configuring the embedded broker using XML -->
<amq:connectionFactory id="jmsFactory" brokerURL="vm://localhost"/>
<!-- JMS Producer Configuration -->
<bean id="jmsProducerConnectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory"
depends-on="broker"
p:targetConnectionFactory-ref="jmsFactory"/>
<!-- JMS Templates-->
<bean id="jmsTemplate"
class="org.springframework.jms.core.JmsTemplate"
p:connectionFactory-ref="jmsProducerConnectionFactory"/>
<!-- Publisher-->
<bean name="jmsEventPublisher"
class="com.jhi.mhm.services.event.jms.publisher.JMSEventPublisher">
<property name="jmsTemplate" ref="jmsTemplate"/>
<property name="topic">
<map>
<entry key="keyname" value-ref="topicName"/>
</map>
</property>
</bean>
<!-- JMS Consumer Configuration -->
<bean name="consumer2" class="Consumer2"/>
<bean name="consumer1" class="Consumer1"/>
<bean id="jmsConsumerConnectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory"
depends-on="broker"
p:targetConnectionFactory-ref="jmsFactory"/>
<jms:listener-container container-type="default"
connection-factory="jmsConsumerConnectionFactory"
acknowledge="auto"
destination-type="topic">
<jms:listener destination="topicPhysicalName" ref="consumer1"/>
<jms:listener destination="topicPhysicalName" ref="consumer2"/>
</jms:listener-container>
I search another posted questions but could not find anything related.
Your thoughts would be really helpful.
shailu - I went through similar problem. What we did is upgrade the version of MQ. Although this did not solved the problem completely as MQ shows random behavior and at the end we simply merged our endpoint and call destination as per biz logic
In my program, I have two modules :- Publisher and Subscriber which communicate via Topic.
I understand that in order to receive messages by subscriber, it should be started before publisher. But there may be a scenario where the subscriber goes down for some reason and needs to be restarted. Is there any way, by which if I start the Subscriber after Publisher, then also it should be able to receive message?
Adding a code example by using spring DMLC and durable subscribers. It's harder to achieve this with a plain JMSTemplate (you tagged this, so I guess you are using JMS Templates to receive?), since you have to grab the session from the template and create the durable consumer yourself. This is automatically handled for you if you use the DMLC approach.
<bean id="myDurableConsumer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="myCf" />
<property name="sessionTransacted" value="true" />
<property name="subscriptionDurable" value="true"/>
<property name="durableSubscriberName" value="myDurableNameThatIsUniqueForThisInstance" />
<property name="destinationName" value="someTopic" />
<property name="messageListener" ref="myListener" />
< /bean>
If you are only interested in the disconnect-reconnect scenario, I think a durable subscriber is what you are looking for.
http://activemq.apache.org/how-do-durable-queues-and-topics-work.html
In general if you want to account for a subscriber going offline and returning without missing any messages you would use JMS Durable Subscriptions. This allows your subscriber to receive any messages it missed while offline. Note that the caveat here is that is needs to have subscribed once first before it will start to collect offline messages.
Besides the standard JMS Durable consumer model ActiveMQ also provides the retroactive consumer. Another possibility is Virtual destinations.
After trying to activate priority with activemq, I was told to try using camel (see here). But I can't get it working, and I'm not even sure how it should work.
I've added the following code, in my spring configuration:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="jms:queue:myqueue" />
<resequence>
<batch-config batchSize="200" batchTimeout="3000" allowDuplicates="true" reverse="true"/>
<header>JMSPriority</header>
<to uri="mock:result"/>
</resequence>
</route>
</camelContext>
<bean id="jmsConfig" class="org.apache.camel.component.activemq.ActiveMQConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
<property name="transacted" value="false"/>
<property name="concurrentConsumers" value="10"/>
</bean>
<bean id="activemq" class="org.apache.camel.component.activemq.ActiveMQComponent">
<property name="configuration" ref="jmsConfig"/>
</bean>
But this configuration doesn't work (nothing is ordered), and I have a few questions:
What does mock:result mean? I couldn't find it in the documentation.
How is camel supposed to re-order the queue, is it done after the messages were created, or when a message is added?
Can it be independent from the spring activemq basic configuration? (I use here the camel ActiveMQComponent)
First, a mock endpoint is for unit testing. You can use it to validate that the expected messages were received:
MockEndpoint resultEndpoint = context.resolveEndpoint("mock:result", MockEndpoint.class);
resultEndpoint.expectedMessageCount(3);
resultEndpoint.expectedBodiesReceived("firstMessageBody", "secondMessageBody", "thirdMessageBody");
resultEndpoint.message(0).header("foo").isEqualTo("bar");
Next, the resequencer is designed to order messages based on some attribute (the header "JMSPriority" in your case) and will perform this over all messages that flow through it over a given timeout period or batch size (by default, the batch size is 100 and the timeout is 1000 ms).
Long story short, you can use the resequencer to order messages (in batches) before they are sent to the queue, in between queues or in between a queue and a consumer...
I have a web application that runs text processing jobs in the background once a message is received on an ActiveMQ which is listened to by a Spring MessageListener....the problem I"m encountering is that once I process around 30 background jobs, ActiveMQ stops processing any messages, Spring message listener loses its JMS connection, and sometimes I get an error in the ActiveMQ log saying that there are too many open files.
I ran the 'lsof' (list open file) command on Linux against the ActiveMQ process and noticed that for almost each message queued/published/received by JmsTemplate, a new connection is opened. Is this normal?
here's my configuration:
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="amqConnectionFactory" />
<property name="exceptionListener" ref="jmsExceptionListener" />
<property name="sessionCacheSize" value="100" />
</bean>
You need to use the PooledConnectionFactory provided by ActiveMQ, you can see full configuration here. Make sure you read the JmsTemplate Gotchas as well.