Spring JMS not sending to queue in transaction - spring

I am trying to use Spring to send a message to a queue. It works fine when I don't try to enable transaction handling. However, when I add transaction handling the message doesn't seem to send to the appropriate queue. All i add is a #Transactional attribute on the method and the following to the application context.
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>

Related

JTA and Hibernate Transaction management

We have implemented a spring message listener service and the main operation exposed by this service is multiple event driven database update.
The context looks like as below.
<bean id="consumerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="${jms.consumerContainer.concurrentconsumers}"/>
<property name="maxConcurrentConsumers" value="${jms.consumerContainer.maxconcurrentconsumers}"/>
<property name="errorHandler" ref="errorHandler" />
<property name="connectionFactory" ref="jmsQueueConnectionFactory" />
<property name="destination" ref="listenerQueue" />
<property name="messageListener" ref="consumerContainer" />
<property name="receiveTimeout" value="10000" />
<property name="sessionTransacted" value="true" />
<property name="transactionManager" ref="txManager" />
</bean>
TX manager is hibernate.
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager" p:sessionFactory-ref="sessionFactory"/>
and annotated the concrete class with #Transactional.
We use Jboss application server support to integrate with MQ via jndi.
The problem here is if there are any exception at any layer in the listener, the overall transaction is not getting rolled back and the message does not move to back out queue. It's obvious that as we use Hibernate transaction manager, it's not aware of other resource like JMS transactions.
Can I replace this safely with JTA transaction as Jboss will handle overall transaction management? Is there any foreseen risk in doing so?
I believe its no longer needed to annotate the class with #Transactional if we are using JTA as below.
<bean id="jtatxManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
Thanks in advance.
Can I replace this safely with JTA transaction as Jboss will handle overall transaction management?
Yes, you can. You should just change your bean txManager definition.
I believe its no longer needed to annotate the class with #Transactional.
This is not true. You still need #Transactional. It allows spring to identify a transaction boundary.

Spring integration inbound jms adapter error-channel does not invoke

The scenario is inbound jms adapter -> service activators (db search, business logic, inserts or updates)
<int-jms:message-driven-channel-adapter id="swiftAdapterInput" channel="mt950"
connection-factory="connectionFactory" destination-name="${integration.swift.jms.queue.from}" pub-sub-domain="false"
auto-startup="false" error-channel="errorChannel" transaction-manager="transactionManager" acknowledge="transacted" />
<int:service-activator input-channel="errorChannel" ref="errorHandler" />
<bean id="errorHandler" class="nest.integration.utils.error.ErrorHandler" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
When the exception was thrown during my servcie activators my errorHandler works fine but the exception was at the end(after commit), for example db unique constrat exception the message does not go to error-channel but rollbacked to jms queue only.
But I need my errorHander in this case also because I need to send email exception etc.
Tanks at advance
Best wishes, Tamas
I think your issue that you must rallback TX in your errorHandler, but don't commit.
That's why you get egyediségre vonatkozó megszorítás nem tel from DefaultMessageListenerContainer, because that DB error is caused on commit.
See here: Exceptions in Spring Integration: How to log but not intercept

Huge latency observed while committing transacted persistent AMQ messages

I have the following AMQ consumer configuration file which tries to consume 'persistent' messages from the queue. Also, the messages are 'transacted' (as I need to rollback if a message can't be processed in an expected way).
I see a problem with this configuration:
Whenever the consumer calls session.commit() after consuming the message, I see the commit call taking ~8 seconds to come out. I believe this is not expected.
Can someone point me if I have any issues with the below config?
<bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
<bean id="simpleMessageListener" class="listener.StompSpringListener" scope="prototype" />
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
<property name="physicalName" value="JOBS.notifications"/>
</bean>
<bean id="poolMessageListener" class="org.springframework.aop.target.CommonsPoolTargetSource">
<property name="targetBeanName" value="simpleMessageListener"/>
<property name="maxSize" value="200"/>
</bean>
<bean id="messageListenerBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource" ref="poolMessageListener"/>
</bean>
<jms:listener-container
container-type="default"
connection-factory="amqConnectionFactory"
acknowledge="transacted"
concurrency="200-200"
cache="consumer"
prefetch="10">
<jms:listener destination="JOBS.notifications" ref="messageListenerBean" method="onMessage"/>
</jms:listener-container>
Take a look at the the ActiveMQ Spring support page. What I can see immediately is that you should be using a PoolingConnectionFactory instead of an ActiveMQConnectionFactory. This will ensure that only a single TCP connection is set up to the broker from your code, and will be shared between polling threads.

WebSphere Camel JMS, spring, taskExecutor, haninging Threads

I'm trying to integrate Camel with WebSphere. It is working fine, for all but one thing.
The scenario looks like:
JMS (WMQ) -> routing/transformation -> BEAN (which does a JPA (OpenJPA1.2/DB2) commit).
To be able to plug into WAS transaction manager and mangaed threads, I'm inserting the work manager as taskExecutor in camel:
<!-- Selected parts of the spring config -->
<tx:jta-transaction-manager/>
<bean id="wasTaskExecutor"
class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName" value="wm/default" />
</bean>
<bean id="camelTransactionRequired" class="org.apache.camel.spring.spi.SpringTransactionPolicy" depends-on="transactionManager">
<property name="transactionManager" ref="transactionManager"/>
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
</bean>
<bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="taskExecutor" ref="wasTaskExecutor"/>
<property name="transacted" value="true"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>
Then a route, something like:
from("jms:queue:MY.QUEUE")
.transacted("camelTransactionRequired")
.log(..)
.bean(storeJPA);
This wasTaskExecutor bean is used in one stand alone spring message listener (same jms provider, WMQ) in the application as well with expected behaviour.
When deployed/started, ONE message can be processed this way (first log line below) - then threads starts to hang.
[5/12/12 22:14:55:890 CEST] 00000055 SystemOut O INFO routeFromBackend - Message pulled from queue to message box
[5/12/12 22:27:00:638 CEST] 00000031 ThreadMonitor W WSVR0605W: Thread "Default : 1" (0000001e) has been active for 739306 milliseconds and may be hung. There is/are 1 thread(s) in total in the server that may be hung.
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:196)
at com.ibm.ws.util.BoundedBuffer.waitPut_(BoundedBuffer.java:214)
at com.ibm.ws.util.BoundedBuffer.put(BoundedBuffer.java:324)
at com.ibm.ws.util.ThreadPool.execute(ThreadPool.java:1296)
at com.ibm.ws.util.ThreadPool.execute(ThreadPool.java:1100)
at com.ibm.ws.asynchbeans.WorkItemImpl$PoolExecuteProxy.run(WorkItemImpl.java:198)
at com.ibm.ws.asynchbeans.WorkItemImpl.executeOnPool(WorkItemImpl.java:219)
at com.ibm.ws.asynchbeans.WorkManagerImpl.queueWorkItemForDispatch(WorkManagerImpl.java:433)
at com.ibm.ws.asynchbeans.WorkManagerImpl.schedule(WorkManagerImpl.java:1074)
at com.ibm.ws.asynchbeans.WorkManagerImpl.schedule(WorkManagerImpl.java:846)
at org.springframework.scheduling.commonj.WorkManagerTaskExecutor.execute(WorkManagerTaskExecutor.java:154)
at org.springframework.jms.listener.DefaultMessageListenerContainer.doRescheduleTask(DefaultMessageListenerContainer.java:669)
at org.springframework.jms.listener.AbstractJmsListeningContainer.resumePausedTasks(AbstractJmsListeningContainer.java:536)
at org.springframework.jms.listener.AbstractJmsListeningContainer.doStart(AbstractJmsListeningContainer.java:285)
at org.springframework.jms.listener.AbstractJmsListeningContainer.start(AbstractJmsListeningContainer.java:263)
at org.springframework.jms.listener.DefaultMessageListenerContainer.start(DefaultMessageListenerContainer.java:555)
at org.apache.camel.component.jms.JmsConsumer.startListenerContainer(JmsConsumer.java:84)
Has anyone seen this?
The thread is "hung" waiting to submit work to a full queue, and the work manager is configured to block rather than throw an error when the queue is full. To resolve the "hang", either increase the number of threads in the work manager thread pool, or change the queue full action to be "error" rather than "wait". Alternatively, investigate if the work items being submitted to the work manager are taking too long for some reason.

Spring, XA and WebSphere

I am trying to get XA transactions working in a Spring v3 application inside WebSphere v7.
My App Context reads:
<bean id="jmsConnectionFactory"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jms/MQConnectionFactory"/>
<property name="resourceRef" value="true"/>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
<jee:jndi-lookup id="myDB" jndi-name="jdbc/myDB"/>
<bean id="txManager"
class="org.springframework.transaction.jta.WebSphereUowTransactionManager" />
<tx:annotation-driven transaction-manager="txManager"/>
I'm referencing this article that says mix in the UOW txn manager and you'll be fine. But it doesn't work that way. Instead, in the following code, the message is destructively read and is not rolled back when an exception is thrown.
The transactional logic is (in scala):
#Transactional(rollbackFor = Array(classOf[Throwable]))
def processNextMessage(category: String) = {
val maybeMessage = readNextMessage(category) // <- this is a destructive read
for (message <- maybeMessage) {
// this is temporary code for testing
throw new RuntimeException("blaaaaaah")
// end temporary code
// sendToQueue(message, queue)
// writeToMessageStore(message)
}
}
Can anyone advise how I can use WebSphere's JTA transaction manager with Spring?
First of all, I would really like to see the code for readNextMessage as that may be the culprit.
Is the queue connection factory set up as an XA resource. You are trying to use JTA for transactions, so as far as I know you need to configure the message qcf accordingly.
You do not have to setup the JmsTemplate for transactions, as these are handled by the QueueConnectionFactory.
On a side note: if you are just dealing with mq, you can skip the UOW JTA provider and use transacted JMS sessions, which should work fine.

Resources