Send JMS Message with Spring JmsTemplate - spring

I have a server that needs to send messages to a separate application. I'm using Spring JmsTemplate, however, I'm having some issues with getting the configuration up and running.
Right now, I'm getting the following exception:
Error creating bean with name 'connectionFactory' defined in ServletContext resource [/WEB-INF/config/application-context.xml]: Invocation of init method failed; nested exception is javax.naming.CommunicationException: Receive timed out [Root exception is java.net.SocketTimeoutException: Receive timed out]
(I can post the full stack trace if you like, but it's just the long version of those nested exceptions.)
The "receive timed out" part makes it sound like it's trying to receive messages, which I don't want to do. Everything here has been pulled together from a couple different examples and SO posts, and I'm having trouble wrapping my head around all of the different parts and what they're doing. In addition to whatever might be causing the error, is there anything I don't need if I'm not receiving messages?
In my JmsQueueSender class (which sends messages):
private JmsTemplate jmsTemplate;
private Destination destination;
public void setConnectionFactory(ConnectionFactory cf) {
jmsTemplate = new JmsTemplate(cf);
}
public void setQueue(Queue queue) {
this.destination = queue;
}
In my application context:
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
<!-- <prop key="java.naming.provider.url">jnp://address.com:port</prop> -->
<prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</prop>
</props>
</property>
</bean>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="jndiName" value="ConnectionFactory" />
</bean>
<bean id="jmsQueueConnectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="connectionFactory"/>
<property name="pubSubDomain" value="false" />
</bean>
<bean id="jmsDestinationResolver"
class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="cache">
<value>true</value>
</property>
</bean>
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate102">
<property name="connectionFactory" ref="jmsQueueConnectionFactory" />
<property name="destinationResolver" ref="jmsDestinationResolver" />
<property name="pubSubDomain" value="false" />
</bean>
<bean id="jmsSender" class="package.JmsQueueSender">
<property name="queue" value="queue/AlertQueueGIAfterSent" />
<property name="connectionFactory" ref="jmsQueueTemplate" />
</bean>

Related

Message driven POJO with spring. Can't receive the message

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.

WebLogic 10.3.6 throws JMSClientExceptions:055142 when configured with lookupOnStartup false

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" />

Spring MDP not Consuming Message

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>

Spring transactions doesn't work with Oracle Express

I have a simple standalone application to test transaction management with Spring.
Have Oracle Express Edition.
Run the following to enable XA
grant select on sys.dba_pending_transactions to user_test;
grant select on sys.pending_trans$ to user_test;
grant select on sys.dba_2pc_pending to user_test;
grant execute on sys.dbms_system to user_test;
My Java code is pretty much as follow:
public class DbUpdater
{
private static final ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"spring_transactions.xml"});
private static Logger log = LoggerFactory.getLogger(DbUpdater.class);
#Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public void updateData() {
IMasterDAO ds1 = context.getBean("masterDao", IMasterDAO.class);
log.info("Insert using ds1");
ds1.insert("insert into users values(?,?)", "user1", "John Hamilton");
log.info("Insert using ds1 finished successfully");
throw new RuntimeException("A runtime exception");
}
}
So all the idea is too see transaction rolling back.
I run with several configuration examples and record is committed all the time.
No rollback is performed. No errors nothing, only expected
Exception in thread "main" java.lang.RuntimeException: A runtime exception
at com.test.spring.transation.DbUpdater.updateData(DbUpdater.java:22)
My last config is this:
<bean id="txManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="bitronixTransactionManager" />
<property name="userTransaction" ref="bitronixTransactionManager" />
</bean>
<bean id="btmConfig" factory-method="getConfiguration"
class="bitronix.tm.TransactionManagerServices">
<property name="serverId" value="spring-btm" />
</bean>
<bean id="bitronixTransactionManager" factory-method="getTransactionManager"
class="bitronix.tm.TransactionManagerServices"
depends-on="btmConfig,dataSource"
destroy-method="shutdown" />
<bean id="dataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource"
init-method="init" destroy-method="close">
<property name="className" value="oracle.jdbc.xa.client.OracleXADataSource"/>
<property name="uniqueName" value="myOracleDataSource"/>
<property name="minPoolSize" value="0"/>
<property name="maxPoolSize" value="5"/>
<property name="allowLocalTransactions" value="true"/>
<property name="testQuery" value="select sysdate from dual"/>
<property name="driverProperties">
<props>
<prop key="user">${jdbc.username}</prop>
<prop key="password">${jdbc.password}</prop>
<prop key="URL">${jdbc.url}</prop>
</props>
</property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="masterDao" class="com.test.spring.transation.MasterDAO">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
</beans>
The JDBC template being instantiated via supplied data source, seems to work with its own transaction [there by the automatic begin and commit transaction]. The exception is thrown after that which operates in seperate commit/rollback cycle and hence you see that the writes persisted. To verify it, you can move the code to throw exception in MasterDAO class and examine rollback.

how to invoke multiple http webservice in mule flow in transaction?

I am new to mule.
I have a spring-hibernate mule setup. Suppose there are 3 webservice.Aim is to invoke all those webservice in a mule flow so that all 3 will be in a transaction. so that suppose if 3rd webservice fails then the previous 2 will be rolled back automatically.
Here is my code snippet what I tried.
my mule-flow.xml(currently I have only one webservice,kindly let me know how can I add multipe webservice call in flow?)
<spring:beans>
<spring:import resource="classpath:spring-mule.xml"/>
<spring:import resource="classpath:applicationContext-persistence.xml"/>
</spring:beans>
<flow name="addCustomer" doc:name="addCustomer">
<http:inbound-endpoint exchange-pattern="request-response"
address="http://localhost:8081/pos/addCustomer" doc:name="HTTP" />
<cxf:simple-service serviceClass="com.proj.pos.webservice.interfac.CustomerService" doc:name="SOAP"/>
<component ><spring-object bean="customerService"/></component>
</flow>
</mule>
My spring-mule.xml
<bean id="customerService" class="com.proj.pos.webservice.implementation.CustomerServiceImpl">
<property name="cusDao" >
<ref local="customerDao"/>
</property>
</bean>
My:applicationContext-persistence.xml
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#localhost:1521:xe" />
<property name="username" value="xyz" />
<property name="password" value="xyz" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="datasource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="hibernate.connection.release_mode">auto</prop>
</props>
</property>
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="customerDao" class="com.proj.pos.dao.implementation.CustomerDaoImpl">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
my CustomerServiceImpl
#WebService(endpointInterface = "com.proj.pos.webservice.interfac.CustomerService",
serviceName = "CustomerService")
public class CustomerServiceImpl implements CustomerService {
#Autowired
private CustomerDao cusDao;
#Transactional //NOTE:USING THIS ANNOTATION I AM ABLE TO ACHIEVE THE BELOW METHOD //IN TRANSACTION,BUT I BELEIVE THIS FEATURE WILL NOT WORK IF WE HAVE MULTIPLE WEBSERVICE CALL
#Override
public Customer addCustomer(CustomerDto dto) {
Customer customer=new Customer(dto.getCustomerId(), dto.getFname(), dto.getLname(), dto.getAge(), dto.getDateOfBirth(), dto.getAddress());
customer.setCustomerId(cusDao.persist(customer));
return customer;
}
public CustomerDao getCusDao() {
return cusDao;
}
public void setCusDao(CustomerDao cusDao) {
this.cusDao = cusDao;
}
}
Please let me know any solution.Thanks
By seeing your question what I understood is your trying to make 3 web-service calls and you want to make all three calls in a single transaction.
As you are making a call to another system (Web-service in your case) you don't have control to maintain the transaction.
In your case you can use a Scatter gather router to call three web-services if any route(web-service call) is failed it will throw CompositeRoutingException, you can very well catch this exception in your catch exception strategy.
In your catch exception strategy you need to do the roll back activities (make another web-service call or db call which will fulfill your rollback requirement ).
As per my understanding, you have a three or more webservices calls and some db operations. you want to rollback if any service call fails.
Write a spring bean as below for SpringTransactionFactory and set transationManager property (ref from your applicationContext-persistence.xml)
<spring:beans>
<spring:import resource="classpath:spring-mule.xml"/>
<spring:import resource="classpath:applicationContext-persistence.xml"/>
<spring:bean id = "transactionFactory" class = "org.mule.module.spring.transaction.SpringTransactionFactory">
<spring:property ref="transactionManager" name=""></spring:property>
</spring:bean>
</spring:beans>
And add a tansactionfactory ref to inboundEndpoint as below
<http:inbound-endpoint exchange-pattern="request-response"
address="http://localhost:8081/pos/addCustomer" doc:name="HTTP" >
<custom-transaction action="ALWAYS_BEGIN" factory-ref="transactionFactory"/>
</http:inbound-endpoint>
Complete flow will be in single transaction and inclouding dao classes

Resources