Connecting to multiple ActiveMQ Servers using Spring Integration XML Configuration - spring-boot

I have been trying for couple days to set up multiple ActiveMQ connections in Spring Integration using XML configuration.
I am using spring boot, SI looks for a bean called jmsConnectionFactory in the context and uses it. But what if I have to send/listen to jms messages from/to different ActiveMQ servers?
What I have right now is this:
<bean id="jmsConnectionFactory1"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
</property>
<property name="sessionCacheSize" value="10" />
<property name="cacheConsumers" value="false" />
</bean>
<bean id="jmsConnectionFactory2"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.1.59:61616" />
</bean>
</property>
<property name="sessionCacheSize" value="10" />
<property name="cacheConsumers" value="false" />
</bean>
...
<jms:message-driven-channel-adapter channel="jmsInChannel" destination-name="queue.demo" />
<int:channel id="jmsInChannel" />
...
When trying to start the spring boot app I get this error:
***************************
APPLICATION FAILED TO START
***************************
Description:
A component required a bean named 'jmsConnectionFactory' that could not be found.
The following candidates were found but could not be injected:
- Bean method 'jmsConnectionFactory' in 'ActiveMQXAConnectionFactoryConfiguration' not loaded because #ConditionalOnClass did not find required class 'javax.transaction.TransactionManager'
Action:
Consider revisiting the entries above or defining a bean named 'jmsConnectionFactory' in your configuration.
I came across this solution, https://stackoverflow.com/a/43401330/3367392 it's a java configuration. Also I looked into this but it's using camel https://stackoverflow.com/a/13288312/3367392
Is there a way to achieve the same for Spring Integration using XML configuration?

Ok so I got it, for a simple case I just had to add the right connectionFactory to the adapters like this
<jms:message-driven-channel-adapter channel="jmsInChannel"
destination-name="queue.demo"
connection-factory="jmsConnectionFactory1" />

Related

ActiveMQ 5.15.5, Camel ActiveMQ component brokerURL to connect two standalone brokers

I have two standalone broker consuming message from another system.
The client consumer uses Camel to consume messages, below is the part of the configuration where it used camel-activemq component.
I am trying to provide both the host information within the borkerURL but throwing some exception.
using jars of
spring-core 4.2.4,
spring-boot: 1.3.1,
activemq-camel: 5.12.1,
activemq-broker: 5.12.1, etc.
...
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="(tcp://host1:61616,tcp://host2:61616)?wireFormat.maxInactivityDuration=500000" />
</bean>
<bean id="jmsPooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
<property name="maxConnections" value="10" />
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="jmsPooledConnectionFactory" />
<property name="concurrentConsumers" value="1" />
<property name="maxConcurrentConsumers" value="1" />
</bean>
<bean id="jms" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig" />
<property name="transacted" value="true" />
</bean>
...
The process throw exception, when i run the camel main with the context.
:PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'brokerURL' threw exception; nested exception is java.lang.IllegalArgumentException: Invalid broker URI: (tcp://host1:61616,tcp://host2:61616)?wireFormat.maxInactivityDuration=500000
Is there any way to pass in the borker URL of two standalone brokers?
If the brokers are part of a failover system, use the "failover" protocol of the ActiveMQ client.
If the brokers have different queues, create two different commponents with different configurations and broker URLs.
refer to jms1 or jms2 in your route.

javax.naming.NameNotFoundException: java:jboss/jms/exampleApp/SampleQueueIn

We are migrating from JBoss EAP 6.4 to JBoss EAP 7.0. Our earlier JMS configuration is not working with JBoss 7.0 where it is throwing NameNotFoundException for my JMS beans
my jms.xml
<beans profile="jboss">
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/jms/exampleApp/ConnectionFactory" />
<property name="resourceRef" value="true" />
</bean>
<bean id="SampleQueueIn" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/jms/exampleApp/SampleQueueIn" />
<property name="resourceRef" value="true" />
</bean>
</beans>
My messageListener.xml
<beans profile="jboss">
<!-- Abstract MessageListener -->
<bean id="messageListener" abstract="true" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="transactionManager" ref="transactionManager" />
<property name="sessionTransacted" value="true" />
<!-- Receive timeout determines the duration of JMS session. Increase from default 1sec to 5sec, to lower the traffic to Queue managers -->
<property name="receiveTimeout" value="5000" />
</bean>
</beans>
my proxy-domain componentContext.xml which has listener beans
<beans profile="jboss">
<bean id="jmsContainer" parent="messageListener">
<property name="destination" ref="SampleQueueIn" />
<property name="messageListener" ref="sampleInformationListenerImpl" />
</bean>
</beans>
commands.cli part for adding admin objects for wmq
/subsystem=resource-adapters/resource-adapter=${wmq_deploy_name}:activate
/subsystem=resource-adapters/resource-adapter=${wmq_deploy_name}/admin-objects=SampleQueueIn:add(class-name=com.ibm.mq.connector.outbound.MQQueueProxy,jndi-name=java:jboss/jms/exampleApp/SampleQueueIn)
/subsystem=resource-adapters/resource-adapter=${wmq_deploy_name}/admin-objects=SampleQueueIn/config-properties=baseQueueName/:add(value=${filter_jms_queue_config_SampleQueueIn_basequeuename})
/subsystem=resource-adapters/resource-adapter=${wmq_deploy_name}/admin-objects=SampleQueueIn/config-properties=baseQueueManagerName/:add(value=${filter_jms_queue_config_basequeuemanager})
I can see my admin objects in the JBoss for wmq under sub resources with correct jndi-name also.
I am using IBM wmq v9.1.0.2.
[EDIT]
Once I deploy my WAR file, I am getting the below exception
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'SampleQueueIn' defined in class path resource [jms.xml]: Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: jms/exampleApp/SampleQueueIn-- service jboss.naming.context.java.jboss.jms.exampleApp.SampleQueueIn
This configuration was working(still working) in jboss eap 6.4.
I have scourged jboss developer sites & stackoverflow sites but no avail till now!
I can see that my
I resolved the error with reload of JBoss server after running the CLI commands. I automated the execution of both jboss cli commands & reload commands to make sure that the JNDI objects lookup is successful.

Bean definition example for JndiDestinationResolver using jndi look up

I'm working on sending and receiving messages to/from an IBM MQ queue using JmsTemplate. My application is installed on a WebSphere application server 8.0 and, in order to retrieve the connection, I use a jndi lookup.
I have 6 queues from where I need to pick/drop xmls depending on scenarios. Also I have added these queue in WAS. I need help to understand two things:
I should use DynamicDestinationResolver or JndiDestinationResolver?
As per my understanding I should use JndiDestinationResolver; if that is right how I can define that in my context file and refer jndi-lookup for each queue so that I can retrieve it from my code while using jmsTemplate send/receive?
Please see below my application context file:
<bean id="jmsQueueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jms/CPC.TapQueueConnCPC" />
<property name="lookupOnStartup" value="false" />
<property name="cache" value="true" />
<property name="proxyInterface" value="javax.jms.QueueConnectionFactory" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsQueueConnectionFactory" />
<property name="receiveTimeout" value="10000" />
<property name="sessionAcknowledgeMode" value="1" />
<property name="destinationResolver" ref="jmsDestResolver"/>
</bean>
<bean id="fileTransferServiceImpl" class="org.kp.cpc.service.FileTransferServiceImpl" >
<constructor-arg name="jmsTemplate" ref="jmsTemplate" />
</bean>
<bean id="jmsDestResolver" class=" org.springframework.jms.support.destination.JndiDestinationResolver"/>
<jee:jndi-lookup id="drop278" jndi-name="jms/CPC.SEND.AUTHREQ278" />
<jee:jndi-lookup id="drop275" jndi-name="jms/CPC.SEND.AUTHREQ275" />
<jee:jndi-lookup id="recev278" jndi-name="jms/CPC.RECE.AUTHREQ278" />
<jee:jndi-lookup id="recev275" jndi-name="jms/CPC.RECE.AUTHREQ275" />
<jee:jndi-lookup id="preAuthStatus" jndi-name="jms/CPC.RECE.PREAUTH.STSUPD278"/>
<jee:jndi-lookup id="succ278" jndi-name="jms/CPC.RECE.SUCC.AUTHRESP278" />
The whole point of the JndiDestinationResolver is that you don't need to do manual lookups. In other words when using the JndiDestinationResolver you don't need the <jee:jndi-lookup /> as that is al handled by the DestinationResolver.
The name of the destination would be the JNDI name. So in your JMS code you would use the following.
jmsTemplate.convertAndSend("jms/CPC.SEND.AUTHREQ278", "Your-Message-Here");
The JndiDestinationResolver will use the name of the destination to do a JNDI lookup.
If you really want to keep the JNDI names out of your code and want to use the <jee:jndi-lookup /> then use the [BeanFactoryDestinationResolver]. This will use the name of the destination to lookup a bean from the BeanFactory (in this case the ApplicationContext). Your JMS code would then point to the bean name instead of the JNDI name.
jmsTemplate.convertAndSend("drop278", "Your-Message-Here");
So which one to use depends on your preferences.

Spring WorkManagerTaskExecutor cannot initialize in websphere

i want use Websphere work manager for executing async jobs in jee context but i have problem with creating spring WorkManager.
bean definition:
<bean id="taskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor"> <property name="workManagerName" value="wm/default" /> </bean>
this definition i found in websphere help. But problem is this ends with noClassDefFound. I noticed pckg org.springframework.scheduling.commonj is missing from spring-context since version 2.x.x
Is it replaced with org.springframework.jca.work.WorkManagerTaskExecutor ?
when i use this other spring class, i get error:
Caused by: org.springframework.jndi.TypeMismatchNamingException:
Object of type [class com.ibm.ws.asynchbeans.WorkManagerImpl]
available at JNDI location [wm/default] is not assignable to
[javax.resource.spi.work.WorkManager]
so whats deal here? thx
was - 7.0.0.23
spring - 3.1.2
Class org.springframework.scheduling.commonj.WorkManagerTaskExecutor resides in spring-context-support-3.1.2.RELEASE.jar
Configuration succeeds with javax.resource.spi.work.WorkManager in applicationContext-service.xml in deployment.....
In my case deployment fails for bean injection org.springframework.scheduling.commonj.WorkManagerTaskExecutor as it fails to take WorkManager JNDI Configured in Application Server.... I just replaced javax.resource.spi.work.WorkManager. And so far it is success deployment.
I yet to see application works fine with it.
<bean id="taskExecutor" class="javax.resource.spi.work.WorkManager">
<property name="workManagerName" value="wm/default" />
</bean>
In our scenario we were managed it by ThreadPoolTaskExecutor instead of WorkManagerTaskExecutor
Here is configuration that comes in ApplicationContext.xml
<!--
<bean id="rtSenderTaskExecutor"
class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName">
<value>${org.quartz.threadPool.jndi}</value>
</property>
</bean> -->
<!-- Local Thread Pool -->
<bean id="rtSenderTaskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="${org.quartz.threadPool.corePoolSize}" />
<property name="maxPoolSize" value="${org.quartz.threadPool.maxPoolSize}" />
<property name="queueCapacity" value="${org.quartz.threadPool.queueCapacity}" />
<property name="keepAliveSeconds" value="${org.quartz.threadPool.keepAliveSeconds}"></property>
</bean>

Spring "XStreamMarshaller" is failing to identify the Java class for mapping to XML while unmarshalling

Recently facing an issue with XStream which i'm using with Spring. We have a REST application where we are using XStream for marshalling & unmarshalling XML.
We have configured as shown below,
<bean id="xStreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="annotatedClasses">
<list><value>com.bestbuy.commerce.repobjects.OfflineOrderRepresentation</value></list>
</property>
<property name="autodetectAnnotations" value="true" />
</bean>
And this XStreamMarshaller is configured to HttpMessageconverter as shown,
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<util:list>
<bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<property name="marshaller" ref="xStreamMarshaller" />
<property name="unmarshaller" ref="xStreamMarshaller" />
</bean>
</util:list>
</property>
</bean>
The issue here is when i post proper XML it should match to it's corresponding XStream annotated class "OfflineOrderRepresentation",
but that is happening randomly, some times i'm getting syntactically incorrect message, and issue is getting fixed randomly if i restart the server.
Below is the error logs i'm getting,
[org.springframework.http.converter.xml.MarshallingHttpMessageConverter#712625b0]
[org.springframework.web.bind.annotation.support.HandlerMethodInvoker]
Reading [com.bestbuy.commerce.repobjects.OfflineOrderRepresentation]
[org.springframework.http.converter.xml.MarshallingHttpMessageConverter#712625b0]
[org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver]
[com.bestbuy.commerce.controllers.OrderController#799a92d1]:
org.springframework.http.converter.HttpMessageNotReadableException: Could not read [class com.bestbuy.commerce.repobjects.OfflineOrderRepresentation];

Resources