I have two app servers. One sends messages to the other using JMS. The sender runs on Tomcat, with ActiveMQ used inside a Spring Framework template method call. The receiver runs on Jetty.
The problem is that when I restart one of the servers-- the receiver of the messages-- after it restarts it doesn't get any more JMS messages until the other server is also restarted. I'm not sure why this is happening. Is there a way to only require a reboot of one server?
The sender XML configuration:
<bean id="producerJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<bean
class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="jmsFactory"/>
</bean>
</property>
</bean>
<bean id="simulationMessageSender" class="com.forio.simulate.activemq.SimulationMessageSenderImpl">
<constructor-arg ref="producerJmsTemplate"/>
</bean>
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue"
autowire="constructor">
<constructor-arg value="com.forio.simulate.activemq"/>
</bean>
The sender java code:
public void send(final SimulationMessage simulationMessage) throws JMSException
{
jmsTemplate.send(destination, new MessageCreator()
{
public Message createMessage(Session session) throws JMSException
{
Log.debug("Sending message: " + simulationMessage);
ObjectMessage message = session.createObjectMessage(simulationMessage);
message.setStringProperty("simulationMessage", "true");
return message;
}
});
}
The receiver XML configuration:
<bean id="brokerContainer" class="org.apache.activemq.xbean.BrokerFactoryBean">
<property name="config" value="classpath:activemq.xml" />
</bean>
<bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="${jms.url}" />
</bean>
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue"
autowire="constructor">
<constructor-arg>
<value>com.forio.simulate.activemq</value>
</constructor-arg>
</bean>
<bean id="messageListener"
class="com.forio.simulate.activemq.SimulationMessageListener">
<property name="messageConverter">
<bean
class="com.forio.simulate.activemq.converter.SimulationMessageConverter" />
</property>
<property name="simulationMessageService" ref="simulationMessageService"/>
</bean>
<bean
class="org.springframework.jms.listener.SimpleMessageListenerContainer" init-method="start">
<property name="connectionFactory" ref="jmsFactory" />
<property name="destination" ref="destination" />
<property name="concurrentConsumers" value="3" />
<property name="messageListener" ref="messageListener" />
</bean>
<bean id="consumerJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsFactory" />
</bean>
It is because you are using SingleConnectionFactory. each time SingleConnectionFactory.createConnection() is called, it returns the same connection, even after it is closed by restarting your receiving server.
Maybe CachingConnectionFactory will suite your needs as it has some recover on exception mechanism.
Related
I am using Apache Camel(with Spring) and ActiveMQ in project. Here are the settings related to JMS/ActiveMQ:
Camel version: activemq-camel-5.15.3.jar (all ActiveMQ related jars)
ActiveMQ version : 5.15.0
<!-- language: lang-xml -->
<bean id="defaultActiveMQRedeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
</bean>
<util:list id="redeliveryPolicyEntries">
<bean id="activeMQRedeliveryPolicy1" class="org.apache.activemq.RedeliveryPolicy">
<property name="queue" value="inbox"></property>
</bean>
</util:list>
<bean id="amqRedeliveryPolicyMap"
class="org.apache.activemq.broker.region.policy.RedeliveryPolicyMap">
<property name="defaultEntry" ref="defaultActiveMQRedeliveryPolicy"></property>
<property name="redeliveryPolicyEntries" ref="redeliveryPolicyEntries"></property>
</bean>
<bean id="amqPrefetchPolicy" class="org.apache.activemq.ActiveMQPrefetchPolicy">
</bean>
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
<property name="maxConnections" value="20" />
<property name="maximumActiveSessionPerConnection" value="40" />
<property name="connectionFactory" ref="jmsConnectionFactory">
</property>
</bean>
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="${jmsConnectionFactory.brokerURL}" />
<property name="userName" value="admin" />
<property name="password" value="admin" />
<property name="prefetchPolicy" ref="amqPrefetchPolicy" />
<property name="redeliveryPolicyMap" ref="amqRedeliveryPolicyMap" />
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory" />
<property name="concurrentConsumers" value="15" />
<property name="maxConcurrentConsumers" value="30" />
<property name="asyncConsumer" value="false" />
<property name="cacheLevelName" value="CACHE_CONSUMER" />
</bean>
<!-- this bean actually represents a jms component to be used in our camel-integration
setup.make endpoints by using name(id) of this bean. -->
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig" />
<property name="transacted" value="false" />
<property name="transactionManager">
<bean class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
</property>
</bean>
As you see I am using PooledConnectionFactory so I am expecting a fixed no of connections to connect with ActiveMQ. But unexpectedly I see a large no of TCP connections being opened in TIME_WAIT even when my application is idle and no messages are being produced/consumed at time. I confirmed this situation with infra team that confirmed all the Operating System level configuration are fine.
Here I tried debugging the doReceiveAndExecute method in AbstractPollingMessageListenerContainer- sessionToUse is not null, consumerToUse is also not null and code flows through receiveMessage(line number 304).I could not find the problem in debug trace as attached in debug screenshots:
and
and my actual problem
Is it a problem with MessageListenerContainer or with ConnectionFactory?? Am I missing some configuration which would prevent this from happening or is this an existing issue? If so is there a workaround?
Just spotted in your configuration that you configured the jmsConnectionFactory (not the pooled factory) in your transaction manager. Not sure if this could raise the issue because the pooled factory is simply not used.
<property name="transactionManager">
<bean class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
</property>
I have written a Spring application for consuming messages using MDP which uses DefaultMessageListnerContainer. I wrote a messageListner and passed it to the property of messageListener to DMLC.
My Spring configuration is below
<!-- ConnectionFactory Definition -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="amqConnectionFactory" />
</bean>
<!-- Message Receiver Definition -->
<bean id="messageReceiver" class="com.practice.MessageReceiver.MyMessageConsumer">
</bean>
<bean id="actualQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="ActualQueue" />
</bean>
<bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="actualQueue" />
<property name="messageListener" ref="messageReceiver" />
</bean>
I want to know how to start this DMLC? I deployed it in Jboss 6.1. But its not consuming messages. I am missing something which I am not able to get by searching for an answer.
I want to use messageSelector String which is inside the class AbstractMessageListenerContainer.class and here is the XML Configurations that i am giving.
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="autoStartup" value="${listener.setup}" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="paymentResponseQueue" />
<property name="messageListener" ref="myAbstractListener" />
</bean>
<bean id="myAbstractListener"
class="org.springframework.jms.listener.AbstractMessageListenerContainer">
<property name="autoStartup" value="${listener.setup}" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="paymentResponseQueue" />
<property name="messageListener" ref="authorisationResponseHandler" />
<property name="messageSelector" value="JMSCorelationId = 'AMM--AS1-6e07c3092bc94f77a183889ababeabc2'" />
</bean>
After giving this configuration, when i start tomcat, my application is not getting started.
Where as when i give the config as below and start tomcat, i am able to start my application and working as expected. xyzResponseHandler is referencing to Class file where i am implementing
public class xyzResponseHandler implements MessageListener{
}
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="autoStartup" value="${listener.setup}" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="paymentResponseQueue" />
<property name="messageListener" ref="xyzResponseHandler" />
</bean>
What wrong i am doing in the First Config. Can you please correct me if i am going in wrong direction. Basically i want to filter the message using messageSelector.
In DefaultMessageListenerContainer the property messageListener should be either a standard JMS MessageListener object or a Spring SessionAwareMessageListener object.
Refer the below spring doc
http://docs.spring.io/spring-framework/docs/3.0.5.RELEASE/api/org/springframework/jms/listener/AbstractMessageListenerContainer.html#setMessageListener(java.lang.Object)
But you are referring to a bean of another ListenerContainer.
So my use case is this:
I have a set of Camel (2.14) routes, which polls a couple of data base tables, does some transformations and then puts messages on different ActiveMQ (5.10.0) queues. For this I've set up a connection pool like described in the Camel wiki:
<!-- ActiveMQ Connection Pooling-->
<bean id="pooledConnectionFactory"
class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
<property name="maxConnections" value="8" />
<property name="connectionFactory" ref="activeMQConnectionFactory" />
</bean>
<bean id="activemqConfig"
class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
<property name="concurrentConsumers" value="10"/>
</bean>
<bean id="activemq"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="activemqConfig"/>
</bean>
I'm currently developing an additional set of Camel components, which will fetch data from some of the ActiveMQ queues, and push the messages forward to some JMS Topics. These topics are based on OracleAQ, and my current setup is this:
<!-- AQ JMS -->
<bean id="connectionFactoryOracleAQ" class="oracle.jms.AQjmsFactory"
factory-method="getQueueConnectionFactory">
<constructor-arg index="0">
<value>${rib.host}</value>
</constructor-arg>
<constructor-arg index="1" type="java.lang.String">
<value>${rib.sid}</value>
</constructor-arg>
<constructor-arg index="2" type="int">
<value>${rib.port}</value>
</constructor-arg>
<constructor-arg index="3">
<value>${rib.driverType}</value>
</constructor-arg>
</bean>
<bean id="credentials"
class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory">
<ref bean="connectionFactoryOracleAQ"/>
</property>
<property name="username">
<value>${aq.user}</value>
</property>
<property name="password">
<value>${aq.pass}</value>
</property>
</bean>
<bean id="jms" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="connectionFactory" ref="credentials"/>
</bean>
Unfortunately the sending to OracleAQ is painfully slow. The to() step in my camel routes takes roughly 2,5 seconds, which is not good enough. So I thought I'd set up a second connection pool to see if things improved, so I changed to setup for the connection factory to this::
<!-- AQ JMS -->
<bean id="connectionFactoryOracleAQ" class="oracle.jms.AQjmsFactory"
factory-method="getQueueConnectionFactory">
<constructor-arg index="0">
<value>${rib.host}</value>
</constructor-arg>
<constructor-arg index="1" type="java.lang.String">
<value>${rib.sid}</value>
</constructor-arg>
<constructor-arg index="2" type="int">
<value>${rib.port}</value>
</constructor-arg>
<constructor-arg index="3">
<value>${rib.driverType}</value>
</constructor-arg>
</bean>
<bean id="credentials"
class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory">
<ref bean="connectionFactoryOracleAQ"/>
</property>
<property name="username">
<value>${aq.user}</value>
</property>
<property name="password">
<value>${aq.pass}</value>
</property>
</bean>
<!-- ActiveMQ Connection Pooling for AQ -->
<bean id="pooledConnectionFactoryAq"
class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
<property name="maxConnections" value="8" />
<property name="connectionFactory" ref="credentials" />
</bean>
<bean id="activemqConfigAq"
class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactoryAq"/>
<property name="concurrentConsumers" value="10"/>
</bean>
<bean id="activemqAq"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="activemqConfigAq"/>
</bean>
However when starting my routes with ActiveMQ, I'm now seeing the exception below. I'm doing anything wrong here? The log says that the exception will be ignored, but I don't feel like ignoring it without atleast understanding why it's being thrown:
2014-10-09 20:50:43,783 | INFO | Connector vm://localhost started | org.apache.activemq.broker.TransportConnector | WrapperSimpleAppMain
2014-10-09 20:50:44,760 | WARN | Create pooled connection during start failed. This exception will be ignored. | org.apache.activemq.jms.pool.PooledConnectionFactory | WrapperSimpleAppMain
javax.jms.JMSException: Error while attempting to add new Connection to the pool
at org.apache.activemq.jms.pool.PooledConnectionFactory.createJmsException(PooledConnectionFactory.java:247)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.apache.activemq.jms.pool.PooledConnectionFactory.createConnection(PooledConnectionFactory.java:202)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.apache.activemq.jms.pool.PooledConnectionFactory.createConnection(PooledConnectionFactory.java:181)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.apache.activemq.jms.pool.PooledConnectionFactory.start(PooledConnectionFactory.java:267)[integration-routes-1.0-jar-with-dependencies.jar:]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.7.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)[:1.7.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.7.0_45]
at java.lang.reflect.Method.invoke(Method.java:606)[:1.7.0_45]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1640)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1581)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1511)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:636)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:934)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.apache.xbean.spring.context.ResourceXmlApplicationContext.<init>(ResourceXmlApplicationContext.java:64)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.apache.xbean.spring.context.ResourceXmlApplicationContext.<init>(ResourceXmlApplicationContext.java:52)[integration-routes-1.0-jar-with-dependencies.jar:]
at org.apache.activemq.xbean.XBeanBrokerFactory$1.<init>(XBeanBrokerFactory.java:104)[activemq-spring-5.10.0.jar:5.10.0]
at org.apache.activemq.xbean.XBeanBrokerFactory.createApplicationContext(XBeanBrokerFactory.java:104)[activemq-spring-5.10.0.jar:5.10.0]
at org.apache.activemq.xbean.XBeanBrokerFactory.createBroker(XBeanBrokerFactory.java:67)[activemq-spring-5.10.0.jar:5.10.0]
at org.apache.activemq.broker.BrokerFactory.createBroker(BrokerFactory.java:71)[activemq-broker-5.10.0.jar:5.10.0]
at org.apache.activemq.broker.BrokerFactory.createBroker(BrokerFactory.java:54)[activemq-broker-5.10.0.jar:5.10.0]
at org.apache.activemq.console.command.StartCommand.runTask(StartCommand.java:87)[activemq-console-5.10.0.jar:5.10.0]
at org.apache.activemq.console.command.AbstractCommand.execute(AbstractCommand.java:57)[activemq-console-5.10.0.jar:5.10.0]
at org.apache.activemq.console.command.ShellCommand.runTask(ShellCommand.java:150)[activemq-console-5.10.0.jar:5.10.0]
at org.apache.activemq.console.command.AbstractCommand.execute(AbstractCommand.java:57)[activemq-console-5.10.0.jar:5.10.0]
at org.apache.activemq.console.command.ShellCommand.main(ShellCommand.java:104)[activemq-console-5.10.0.jar:5.10.0]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.7.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)[:1.7.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.7.0_45]
at java.lang.reflect.Method.invoke(Method.java:606)[:1.7.0_45]
at org.apache.activemq.console.Main.runTaskClass(Main.java:262)[activemq.jar:5.10.0]
at org.apache.activemq.console.Main.main(Main.java:115)[activemq.jar:5.10.0]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.7.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)[:1.7.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.7.0_45]
at java.lang.reflect.Method.invoke(Method.java:606)[:1.7.0_45]
at org.tanukisoftware.wrapper.WrapperSimpleApp.run(WrapperSimpleApp.java:240)[wrapper.jar:3.2.3]
at java.lang.Thread.run(Thread.java:744)[:1.7.0_45]
I have a component which reads messages from a queue and meanwhile sends the processed messages to another queue. Therefore, this component is both a message consumer and producer. For configuring them, I need a connection factory for consuming and another connection factory for the producing. Here is part of the spring configuration.
<!-- Configuration for listener -->
<bean id="mdc.TargetConnectionFactory4Listener" class="com.tibco.tibjms.TibjmsConnectionFactory">
<property name="serverUrl" value="tcp://localhost:7222"/>
</bean>
<bean id="mdc.ConnectionFactory4Listener" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="mdc.TargetConnectionFactory"/>
<property name="username" value="admin" />
<property name="password" value="test" />
</bean>
<bean id="mdc.InputQueue" class="com.tibco.tibjms.TibjmsQueue">
<constructor-arg>
<value>INPUT_QUEUE</value>
</constructor-arg>
</bean>
<bean id="mdc.JmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="mdc.ConnectionFactory4Listener" />
<property name="destination" ref="mdc.InputQueue" />
<property name="messageListener" ref="mdc.MessageReceiver" />
......
</bean>
<!-- Configuration for sender -->
<bean id="mdc.TargetConnectionFactory4Sender" class="com.tibco.tibjms.TibjmsQueue">
<property name="serverUrl" value="tcp://localhost:7222"/>
</bean>
<bean id="mdc.CachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="mdc.TargetConnectionFactory4Sender" />
<property name="sessionCacheSize" value="50" />
</bean>
<bean id="mdc.OutputQueue" class="com.tibco.tibjms.TibjmsQueue">
<constructor-arg>
<value>DISCOVERY_QUEUE</value>
</constructor-arg>
</bean>
<bean id="mdc.JmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="mdc.CachingConnectionFactory" />
</bean>
<bean id="mdc.MessageReceiver" class="net.siemens.discovery.queue.QueueMessageListener">
<property name="jmsTemplate" ref="mdc.JmsTemplate" />
<property name="destination" ref="mdc.OutputQueue" />
......
</bean>
The two queues are running on the same EMS server. Some has opinions about this configurations: they can be configured by using only one ConnectionFactory and two instances are not necessary. However, if I use one ConnectionFactory instance, then the instance is used both in the DefaultMessageListenerContainer and the CachingConnectionFactory (further used in JmsTemplate). I don't know whether they have impact on each other.
It is perfectly normal to use a single connection factory; it is very unusual to use 2 factories in this case.
In fact, if you want to perform JmsTemplate operations on the container thread and you want the interactions to run in a transaction (sessionTransacted = true in the container), then you must use the same connection factory. This allows everything to roll back if there's an exception.
When using a caching connection factory in the listener container you should set the connection factory cacheConsumers to false. (See this answer for more information.