2012-02-07 76 views
0

內處理隊列中的事件我使用一個交易代理包裝服務,我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

回答

0

如果我理解正確的,你有保存在數據庫中的一些數據,併發送消息的事務。消息的接收者試圖從數據庫中讀取數據,但沒有找到它,因爲收到了該消息,但發件人的事務尚未提交。

你是在一個情況下,你需要一個支持XA(2階段提交)事務管理器,其招收的數據庫和JMS代理到同一個全局事務。這樣,對數據庫的寫入和消息的發送都是以原子方式執行的,並且如果數據庫寫入尚未完成並且成功,則無法發送消息。

有自由這樣的事務管理器,像Bitronix,Atomikos公司或JBoss的TM。

+0

是的,沒錯。我想要實現這個的最初方式是將消息隊列生產者作爲AOP方面實現,並在事務完成後添加它。 – user1132294 2012-02-07 10:41:50

+0

這有兩個缺點:它使得代碼更難理解(特別是如果消息內容取決於方法內部完成的內容),並且它不處理數據庫中的提交工作的情況,但是發送消息失敗。您失去了交易的ACID功能。 – 2012-02-07 11:42:06