Spring MVC的控制器交易
问题描述:
内处理队列中的事件我使用一个交易代理包装服务,我applicationContext.xml中包含:Spring MVC的控制器交易
<bean id="someService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager" />
<property name="target" ref="someServiceImpl" />
<property name="transactionAttributes">
<props>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="create*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean name="someServiceImpl" class="impl.serviceImpl">
<property name="dataDao" ref="dataDao" />
<property name="eventQ" ref="eventQJMSTemplate"></property>
</bean>
文物被定义为队列:
<bean id="eventQJMSTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="cachingMsgConnectionFactory" />
<property name="defaultDestination" ref="newEventQ" />
</bean>
<bean id="cachingMsgConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory" >
<property name="targetConnectionFactory" ref="msgConnectionFactory" />
<property name="sessionCacheSize" value="10"/>
</bean>
<bean id="msgConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory" >
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
该服务具有操作
public void create(Object obj)
{
dataDao.createAndSave(obj);
eventQ.send(new NewMessageCreator(obj.getId());
}
消息处理程序被定义为
<bean id="newEventProcessor" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="cachingMsgConnectionFactory"/>
<property name="destination" ref="newEventQ"/>
<property name="messageListener" ref="newEventListener" />
</bean>
<bean id="newProjectEventListener" class="messages.NewEventHandler">
<property name="dataDao" ref="dataDao" />
</bean>
消息处理程序的实现:
public class NewEventHandler implements MessageListener
{
@Override
public void onMessage(Message message)
{
Long objId;
if (message instanceof MapMessage)
{
try
{
MapMessage eventMsg = (MapMessage) message;
objId = eventMsg.getLong("objectId");
}
catch (JMSException ex)
{
log.error("Error parsing new event.", ex);
throw new RuntimeException(ex); // TODO error handling
}
dataDao.find(objId);
//ERROR
// This fails as the object is still in the save transaction
}
}
}
对象的GET操作失败,因为交易尚未完成。事务完成后将消息发送到队列的最佳方式是什么? 我必须在创建方法中执行此操作,因为这是进入服务的公共接口。
所有组件都在一个Tomcat实例运行。
Thankss
答
如果我理解正确的,你有保存在数据库中的一些数据,并发送消息的事务。消息的接收者试图从数据库中读取数据,但没有找到它,因为收到了该消息,但发件人的事务尚未提交。
你是在一个情况下,你需要一个支持XA(2阶段提交)事务管理器,其招收的数据库和JMS代理到同一个全局事务。这样,对数据库的写入和消息的发送都是以原子方式执行的,并且如果数据库写入尚未完成并且成功,则无法发送消息。
有自由这样的事务管理器,像Bitronix,Atomikos公司或JBoss的TM。
是的,没错。我想要实现这个的最初方式是将消息队列生产者作为AOP方面实现,并在事务完成后添加它。 – user1132294 2012-02-07 10:41:50
这有两个缺点:它使得代码更难理解(特别是如果消息内容取决于方法内部完成的内容),并且它不处理数据库中的提交工作的情况,但是发送消息失败。您失去了交易的ACID功能。 – 2012-02-07 11:42:06