I have simple Java Spring application which looks up JMS objects using JNDI and publishes a message to a JMS Topic. JNDI and JMS configured on WebLogic 10.3.6. All this works fine as long as the WebLogic server is up and running.
I need to get the application to start up even when the WebLogic server is down. I have configured the JNDI objects with "lookupOnStartup" as "false".
Below is my Spring configuration.
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${jndi.initialFactory}</prop>
<prop key="java.naming.provider.url">${jndi.providerurl}</prop>
</props>
</property>
</bean>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>${jms.connectionFactory}</value>
</property>
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.ConnectionFactory" />
</bean>
<bean id="myTopic" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>${jms.mytopic}</value>
</property>
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.Destination" />
</bean>
<bean id="jmsDestinationResolver"
class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="cache" value="true" />
</bean>
<bean id="myTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="defaultDestination" ref="myTopic" />
<property name="destinationResolver" ref="jmsDestinationResolver" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="sessionAcknowledgeModeName" value="AUTO_ACKNOWLEDGE" />
<property name="sessionTransacted" value="false" />
</bean>
At runtime I get the following exception:
Exception in thread "main" org.springframework.jms.InvalidDestinationException: [JMSClientExceptions:055142]Foreign destination, jmsserver-module!my-topic; nested exception is weblogic.jms.common.InvalidDestinationException: [JMSClientExceptions:055142]Foreign destination, jmsserver-module!my-topic
at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:285)
at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:169)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:497)
at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:569)
...
Caused by: weblogic.jms.common.InvalidDestinationException: [JMSClientExceptions:055142]Foreign destination, jmsserver-module!my-topic
at weblogic.jms.common.Destination.checkDestinationType(Destination.java:105)
at weblogic.jms.client.JMSSession.setupJMSProducer(JMSSession.java:2830)
at weblogic.jms.client.JMSSession.createProducer(JMSSession.java:2858)
at weblogic.jms.client.JMSSession.createProducer(JMSSession.java:2822)
at weblogic.jms.client.WLSessionImpl.createProducer(WLSessionImpl.java:827)
at org.springframework.jms.core.JmsTemplate.doCreateProducer(JmsTemplate.java:1143)
at org.springframework.jms.core.JmsTemplate.createProducer(JmsTemplate.java:1124)
at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:601)
at org.springframework.jms.core.JmsTemplate$3.doInJms(JmsTemplate.java:572)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:494)
... 3 more
Any help is much appreciated. Thank you!
In Destination.java:
if(!(destination instanceof DestinationImpl))
throw new InvalidDestinationException
The proxied connectionFactory is not able to resolve the the destination type. I was able to resolve this issue by providing only the destination name to the JmsTemplate and using a JNDI destinationResolver to resolve the destination type on demand. So the modified Spring configuration looks like:
<bean id="myTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="defaultDestinationName">
<value>${jms.mytopic}</value>
</property>
<property name="destinationResolver" ref="jmsDestinationResolver" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="sessionAcknowledgeModeName" value="AUTO_ACKNOWLEDGE" />
<property name="sessionTransacted" value="false" />
Related
I have following configuration in the application that works perfectly fine with queues and redelivers the messages when a RuntimeException occurs with transaction rollback as expected.
But the same configuration fails to redeliver message with topics and emits following warning message:
WARN DefaultMessageListenerContainer - Setup of JMS message listener invoker failed for destination 'XXX_TOPIC' - trying to recover. Cause: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: One or more resources refused to commit (possibly because of a timeout in the resource - see the log for details). This transaction has been rolled back instead.
Configuration:
<bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
<!-- <property name="sendTimeout" value="1000"/> -->
<property name="redeliveryPolicy" ref="redeliveryPolicy"/>
</bean>
<!-- Atomikos Connection Factory Wrapper For Gobal Tx -->
<bean id="queueConnectionFactoryBean" class="com.atomikos.jms.AtomikosConnectionFactoryBean">
<property name="uniqueResourceName" value="amq1" />
<property name="xaConnectionFactory" ref="amqConnectionFactory" />
</bean>
<bean id="jmsConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<ref bean="queueConnectionFactoryBean"/>
</property>
<property name="sessionCacheSize" value="20"/>
<property name="cacheConsumers" value="false"/>
</bean>
<bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init"
destroy-method="close">
<property name="forceShutdown" value="false" />
</bean>
</property>
<property name="userTransaction">
<bean class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
</property>
</bean>
<!-- Topic configuration -->
<bean id="messageListener1" class="com.x.y.impl.JmsMessageListener"></bean>
<bean id="container1" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="destinationName" value="XXX_TOPIC"/>
<property name="messageListener" ref="messageListener1" />
<property name="pubSubDomain" value="true" />
<property name="transactionManager" ref="jtaTransactionManager" />
<property name="concurrency" value="1" />
<property name="receiveTimeout" value="3000" />
<!-- For local session and Atomikos-->
<property name="sessionTransacted" value="true"/>
</bean>
<!-- Bean configuration -->
<bean id="messageListener2" class="com.x.y.impl.JmsMessageListener"></bean>
<bean id="container2" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="destinationName" value="XXX_QUEUE"/>
<property name="messageListener" ref="messageListener2" />
<property name="pubSubDomain" value="false" />
<property name="transactionManager" ref="jtaTransactionManager" />
<property name="concurrency" value="1" />
<!-- For local session and Atomikos-->
<property name="sessionTransacted" value="true"/>
</bean>
The Spring version used is 3.1, ActiveMQ 5.14, Atomikos 4.0.6.
Please let me know if i missed any configuration for topic DMLC.
my application deployed on Tomcat am I am trying to send and receive message from remote queue.
I already have succeeded to send few messages to remote queue. Now I am trying to build message listener container, however my onMessage(method is never called), don't understand what I am missing.
This is my configuration
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destinationResolver" ref="destinationResolver" />
</bean>
<bean id="connectionFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
<property name="username" value="user"/>
<property name="password" value="pass"/>
</bean>
<bean id="targetConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="jndiName" value="MY_TEST_QUEUE" />
<property name="proxyInterface" value="javax.jms.ConnectionFactory"/>
</bean>
<bean id="destinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="cache" value="true" />
</bean>
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">t3://host:port</prop>
</props>
</property>
</bean>
<bean id="messageListener" class="com.package.MyCustomMDB" />
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destinationName" value="MY_TEST_QUEUE"/>
<property name="destinationResolver" ref="destinationResolver" />
<property name="messageListener" ref="messageListener" />
</bean>
And implementation of mdb
public class MyCustomMDB implements MessageListener {
#Override
public void onMessage(Message message) {
System.out.println(message.toString());
}}
Could you please advise me where I am doing something wrong?
You are using MY_TEST_QUEUE for the both the jndiName of targetConnectionFactory and destinationName of jmsContainer. The the jndiName of targetConnectionFactory should refer to the name of a connection factory rather than a queue.
I am implementing Spring MDP + JMSTemplate to send and receive the message. The message send mechanism is working fine, however the MDP is not getting invoked. I tried testing the via plain receiver, and was able to retrieve the message, but not via MDP. What could be the problem? I can see the messages getting accumulated in the request queue, but somehow the MDP is not getting trigger. Am I missing anything here in configurations or something else needs to be taken care of?
Here's the Spring Config. The Java class to send and received are pretty much standard ones.
<bean id="cookieRequestListener" class="com.text.jms.mq.mdp.RequestQueueMDP">
<property name="logger" ref="mqLogger" />
<property name="scoringEngine" ref="scoringEngine" />
<property name="mqSender" ref="jmsMQSender" />
</bean>
<bean id="CookieRequestContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="cachedConnectionFactory" />
<property name="destination" ref="jmsRequestQueue" />
<property name="messageListener" ref="cookieRequestListener" />
</bean>
<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>java:/jms/queueCF</value>
</property>
</bean>
<!-- A cached connection to wrap the Queue connection -->
<bean id="cachedConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="jmsConnectionFactory"/>
<property name="sessionCacheSize" value="10" />
</bean>
<!-- jms Request Queue Configuration -->
<bean id="jmsRequestQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>java:/jms/cookieReqQ</value>
</property>
</bean>
<!-- jms Response Queue Configuration -->
<bean id="jmsResponseQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>java:/jms/cookieResQ</value>
</property>
</bean>
<bean id="jmsJMSTemplate" class="org.springframework.jms.core.JmsTemplate" >
<property name="connectionFactory" ref="cachedConnectionFactory" />
</bean>
<!-- jms MQ Utility -->
<bean id="jmsMQSender" class="com.text.jms.util.MQSender">
<property name="jmsTemplate">
<ref bean="jmsJMSTemplate"></ref>
</property>
<property name="defaultDestination">
<ref bean="jmsRequestQueue" />
</property>
<property name="logger" ref="mqLogger" />
</bean>
I'm having some issues create a connection to (and reading from) a Tibco EMS JMS queue.
<beans>
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">com.tibco.tibjms.naming.TibjmsInitialContextFactory</prop>
<prop key="java.naming.provider.url">tcp://ems-dit-am-uat-1.app.xxx.net:30055</prop>
</props>
</property>
</bean>
<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" /> <property name="jndiName"
value="DRDRFIQueueConnectionFactory" /> </bean>
<bean id="jmsDestinationResolver"
class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="cache" value="true" />
</bean>
<bean id="destination" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="jndiName" value="Q.NY.DERIV.DRD.RFI" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsConnectionFactory" />
<property name="destinationResolver" ref="jmsDestinationResolver" />
<property name="defaultDestination" ref="destination" />
</bean>
<bean id="jmsReceiver" class="com.csfb.fao.rds.rfi.application.DRDReceiverTst">
<property name="jmsTemplate">
<ref bean="jmsTemplate" />
</property>
</bean>
</beans>
The exception I'm getting is:
javax.naming.AuthenticationException: Not permitted: invalid name or
password [Root exception is javax.jms.JMSSecurityException: invalid
name or password] at
com.tibco.tibjms.naming.TibjmsContext.lookup(TibjmsContext.java:668)
at
com.tibco.tibjms.naming.TibjmsContext.lookup(TibjmsContext.java:489)
at javax.naming.InitialContext.lookup(InitialContext.java:392) at
org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:154)
at
org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
at
org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)
at
org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178)
at
org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:95)
at
org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:105)
at
org.springframework.jndi.JndiObjectFactoryBean.lookupWithFallback(JndiObjectFactoryBean.java:201)
at
org.springframework.jndi.JndiObjectFactoryBean.afterPropertiesSet(JndiObjectFactoryBean.java:187)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
... 12 more
The only user/password I've been given is for the JMS queue itself - where do I set that?
Thanks
Chris
Got it - needed to wrap the connection factory in a UserCredentialsConnectionFactory:
<bean id="authenticationConnectionFactory"
class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="jmsConnectionFactory" />
<property name="username" value="yyyyy" />
<property name="password" value="xxxx" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="authenticationConnectionFactory" />
<property name="destinationResolver" ref="jmsDestinationResolver" />
<property name="defaultDestination" ref="destination" />
I had some similar problem , solution was to add (besides solution from this question)
<prop key="java.naming.security.principal">username</prop>
<prop key="java.naming.security.credentials">password</prop>
to jndiTemplate bean configuration
I don't have any experience with EMS, but user and password are typically set on the connection factory, so you'd want to configure that on the object being provided by JNDI.
as my question title, how to configure jms template at spring for weblogic?
i follow an example at some website, but spring always complain about defaultDestination at JmsTemplate
how to configure it correctly ?
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">t3://localhost:7001</prop>
</props>
</property>
</bean>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="jndiName" value="jms/confactory" />
</bean>
<bean id="jmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="cache" value="true" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destinationResolver" ref="jmsDestinationResolver" />
</bean>
nb : i use weblogic 9.2 for jms & web server, spring 2.5.6
i find out, that destination should contain jms destination
<bean id="destination" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jms/queue" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destinationResolver" ref="jmsDestinationResolver" />
<property name="defaultDestination" ref="destination" />
<property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE"/>
<property name="sessionTransacted" value="true" />
</bean>