I am using Spring Integration 4.1.5 and trying to do something with transactions, but unfortunately am not able to and could not find working examples. I'm trying to setup a JMS poller that is looking for messages. Once a message is received, a service activator will insert a row into the database, and the message is passed to another service activator. I would like to make the first two pieces, the message pickup & database insert transactional. I do not want the rest of the flow to be transactional. I am using Weblogic as the application container so will be using the WebLogicJtaTransactionManager.
The problem I'm running into is I am unable to make the first two pieces transactional. It's either all, or nothing. I've tried many methods, but I feel like using an advice-chain on the poller is the best bet. I would be able to control which methods would be part of the transaction.
I've seen examples using a message driven listener, but I am using Weblogic and would be using the Work Managers and I believe I must use a poller in order to take advantage of work managers (if that's not the case, I guess that's another question for the future!)
I've taken the xml and simplified it, but besides editing out the package name, the context produces the issue.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration"
xmlns:file="http://www.springframework.org/schema/integration/file"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:int-sftp="http://www.springframework.org/schema/integration/sftp"
xmlns:int-xml="http://www.springframework.org/schema/integration/xml"
xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/file
http://www.springframework.org/schema/integration/file/spring-integration-file.xsd
http://www.springframework.org/schema/integration/sftp
http://www.springframework.org/schema/integration/sftp/spring-integration-sftp.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/integration/xml
http://www.springframework.org/schema/integration/xml/spring-integration-xml.xsd
http://www.springframework.org/schema/integration/jms
http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="jtaTransactionManager"
class="org.springframework.transaction.jta.WebLogicJtaTransactionManager">
<property name="transactionManagerName" value="javax.transaction.TransactionManager" />
</bean>
<bean id="insertMessageToDb" class="com.ReadMsgFromAxway" />
<bean id="serviceActivator" class="com.CreateTMDFile" />
<int-jms:inbound-channel-adapter id="jmsDefaultReceiver"
connection-factory="inboundDefaultAdaptorConnectionFactory"
extract-payload="false" destination="inboundAdaptorDefaultListenerQueue"
channel="inboundJMS" acknowledge="transacted">
<int:poller id="poller"
max-messages-per-poll="100" fixed-rate="10">
<int:advice-chain>
<ref bean="txAdvice" />
</int:advice-chain>
</int:poller>
</int-jms:inbound-channel-adapter>
<tx:advice id="txAdvice" transaction-manager="jtaTransactionManager">
<tx:attributes>
<tx:method name="processMessage" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txOperation"
expression="execution(* axway.ReadMsgFromAxway.processMessage(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txOperation" />
</aop:config>
<int:service-activator input-channel="inboundJMS"
output-channel="serviceActivatorChannel" ref="insertMessageToDb" method="processMessage" />
<int:chain input-channel="serviceActivatorChannel" output-channel="nullChannel">
<int:service-activator ref="serviceActivator" />
</int:chain>
</beans>
ReadMsgFromAxway.java
public Message<File> processMessage(Message<?> message) {
//Insert into DB
trackerProcess.insertUpdateMessageTracker(message, "axwayChannel",
"axwayChannel", currentStatusID, null, null);
count++;
int mod = count % 2;
if (mod != 0) {
// pass every 2
String hello = "hey";
} else {
throw new RuntimeException("Testing transactional");
}
Message<File> springMessage = MessageBuilder.createMessage(payloadFile,
messageHeaders);
return springMessage;
}
The XML as is doesn't do anything, whether the runtime exception is thrown, or an exception is thrown at the next service activator component.
If I change the advice attributes to
<tx:method name="*" propagation="REQUIRED"/>
Then the exceptions at the 1st and 2nd service activator causes the rollback.
Oddly enough if I do this
<tx:method name="processMessage" propagation="REQUIRED"/>
<tx:method name="*" propagation="NEVER"/>
Then whether the runtime exception in the 1st service activator, or the 2nd activator is thrown, the message gets rolled back. I would think the pointcut would limit which class would cause the transaction, but I maybe I'm misunderstanding something.
Another note - THis application is housed in an ear file with several other wars. This context starts the entire inbound process, and connects to another war, which contains business logic, via a JMS queue. In the scenario of using method name="*" I saw the exceptions in the business logic war to cause the JMS message of the original inbound message get rolled back too. I was under the impression that the 2nd war would do its processing in another thread, since it receives a message via a queue, and thus not be part of the transaction. Could this be a side effect of JTA, which is container managed?
Thanks!