Spring MVC обрабатывает события очереди в транзакции контроллера - PullRequest
0 голосов
/ 07 февраля 2012

Я использую прокси транзакции для переноса службы, мой applicationContext.xml содержит:

<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

    }
}
 }

Ошибка получения объекта, так как транзакция не завершена. Каков наилучший способ отправить сообщение в очередь после завершения транзакции? Я должен сделать это в методе создания, так как это открытый интерфейс службы.

Все компоненты работают в одном экземпляре tomcat.

Thankss

1 Ответ

0 голосов
/ 07 февраля 2012

Если я правильно понимаю, у вас есть транзакция, которая сохраняет некоторые данные в базе данных и отправляет сообщение. И получатель сообщения пытается прочитать данные из базы данных, но не находит их, потому что сообщение получено, но транзакция отправителя еще не зафиксирована.

Вы находитесь в ситуации, когда вам нужен менеджер транзакций с поддержкой XA (двухфазная фиксация), который регистрирует базу данных и JMS-брокера в одной глобальной транзакции. Таким образом, запись в базу данных и отправка сообщения выполняются атомарно, и нет никакого способа отправить сообщение, если запись в базу данных еще не выполнена и успешно завершена.

Есть такие бесплатные менеджеры транзакций, как Bitronix, Atomikos или JBoss TM.

...