Assuming you are doing all the work in a single SI message flow (behind a gateway), it will work, but you don't need to rollbackFor an IOException because the IOException will be wrapped in a MessagingException which is a RuntimeException and default rollback rules will rollback on a RuntimeException.
I just ran a test (based on the tcp-client-server sample) and all worked as expected. I used a <recipient-list-router /> to send the message to jms and then tcp...
Code:
public interface SimpleGateway {
@Transactional(value="txManager")
public void send(String text);
}
Code:
@ContextConfiguration("/META-INF/spring/integration/jmsAndTcpClientTxDemo-context.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class JmsAndTcpClientTxDemoTest {
@Autowired
SimpleGateway gw;
@Autowired
JmsTemplate jmsTemplate;
@Test
public void testHappyDay() {
String text = "Hello world!";
try {
gw.send(text);
} catch (Exception e) {
e.printStackTrace();
}
jmsTemplate.setReceiveTimeout(100);
Object jmsMessage = jmsTemplate.receiveAndConvert();
assertEquals(text, jmsMessage);
}
}
Code:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/integration"
xmlns:ip="http://www.springframework.org/schema/integration/ip"
xmlns:jms="http://www.springframework.org/schema/integration/jms"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd
http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- Client side -->
<tx:annotation-driven/>
<gateway id="gw"
service-interface="org.springframework.integration.samples.tcpclientserver.SimpleGateway"
default-request-channel="toRouter"/>
<recipient-list-router input-channel="toRouter">
<recipient channel="toJms"/>
<recipient channel="toTcp"/>
</recipient-list-router>
<ip:tcp-connection-factory id="client"
type="client"
host="localhost"
port="11111"
single-use="true"
so-timeout="10000"
/>
<channel id="toJms" />
<jms:outbound-channel-adapter
channel="toJms"
connection-factory="connectionFactory"
destination="queue"/>
<!-- only for message retrieval in test case -->
<beans:bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<beans:property name="connectionFactory" ref="connectionFactory" />
<beans:property name="defaultDestination" ref="queue" />
</beans:bean>
<channel id="toTcp" />
<ip:tcp-outbound-channel-adapter
channel="toTcp"
connection-factory="client"
/>
<beans:bean id="txManager" class="org.springframework.jms.connection.JmsTransactionManager">
<beans:property name="connectionFactory" ref="connectionFactory"/>
</beans:bean>
<beans:bean id="queue" class="org.apache.activemq.command.ActiveMQQueue">
<beans:constructor-arg value="test.queue"/>
</beans:bean>
<beans:bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<beans:property name="targetConnectionFactory">
<beans:bean class="org.apache.activemq.ActiveMQConnectionFactory">
<beans:property name="brokerURL" value="vm://localhost"/>
</beans:bean>
</beans:property>
<beans:property name="sessionCacheSize" value="10"/>
<beans:property name="cacheProducers" value="false"/>
</beans:bean>
<!-- Server side -->
<ip:tcp-connection-factory id="crLfServer"
type="server"
port="11111"/>
<ip:tcp-inbound-channel-adapter
connection-factory="crLfServer"
channel="serverBytes2StringChannel"/>
<transformer id="serverBytes2String"
input-channel="serverBytes2StringChannel"
output-channel="toSA"
expression="new String(payload)"/>
<channel id="toSA" />
<service-activator input-channel="toSA"
ref="someService"
method="test1"
/>
<beans:bean id="someService"
class="org.springframework.integration.samples.tcpclientserver.SomeService" />
</beans:beans>
If you change the port on the client connection factory to, say, 11112 and re-run the test, it fails to retrieve the message because it was rolled back after the tcp operation failed to create a connection.
With debugging turned on, you can also see the commit or rollback in each case.
Hope that helps.