Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Отслеживание таймаута при обработке транзакции


Автор: Alagert 15.6.2010, 23:46
Всем доброго времени суток.

Прошу помощи вот в какой ситуации:
есть большое приложение, управляемое Spring, крутится на Apache Tomcat. Задача приложения - отвечать на запросы клиентов по протоколу. Обработку одного конкретного запроса необходимо делать в транзакции, так же необходимо чтобы она длилась строго меньше 15 секунд. В случае превышения этого времени нужно откатить транзакцию и уведомить клиента. Отсюда вопрос как отследить время.

Обработка запрос построена следующим образом: перед тем как данные попадают в контроллер они проходят цепочку фильтров, управляемых тоже Spring. Прохождение фильтров тоже должно включаться в интервал 15 сек. 

Так же понятно, что обрабатываться могут несколько запросов одновременно, поэтому на каждый нужен свой таймер. 

Сам копаю в сторону Timer из JDK, думаю взводить его при начале работы первого фильтра.  Еще есть сложность с тем, что ролбэк транзакции целиком делается руками и состоит из нескольких шагов. Если я взведу таймер в начале работы первого фильтра, то у меня еще не будет всей необходимой инфы, чтобы в случае срабатывания, откатить транзакцию на последних этапах обработки.

Может быть можно как нит в Spring заюзать таймер, только чтобы он выполнился один раз, а не сигналил периодически. 

В общем, посоветуйте как быть smile

Автор: ki6opr 16.6.2010, 08:16
нетвой случай:
http://java.sun.com/javaee/5/docs/tutorial/doc/bncjc.html 
а вот и твой:
http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

спринг умеет делать все что ты хочешь smile
правда не могу точно сказать на счет сервлет фильтров, если они со

Автор: Alagert 16.6.2010, 11:36
Спасибо за ссылки, прочитал еще раз smile 

Что конкретно Вы имели ввиду под 
Цитата(ki6opr @  16.6.2010,  08:16 Найти цитируемый пост)
спринг умеет делать все что ты хочешь 

?

У меня ситуация следующая: сервис, который обрабатывает данные, дергает по мимо DAO объектов еще два специфичных сервиса, один медиа сервис, другой платежный. Поэтому я не очень понимаю, как тут использовать декларативный способ управления транзакциями. Нужен ведь правильная реализация PlatformTransactionManager  То есть ее необходимо писать самому.

Второй же вариант использовать TransactionTemplate 

В целом же, конечно, хочется избавиться от управления транзакциями руками и работы с таймерами. Буду копать дальше. 

Автор: ki6opr 17.6.2010, 02:42
имелось в виду что не нужно копаться в сторону таймеров, потому что отслеживание времени за которое транзакция должна выполнится, может делать сам спринг 

ну выложи последовательность действий. может и не нужно там тебе ничего такого сложного писать.

Автор: afon 17.6.2010, 12:06
Судя по всему я могу помочь. Просто расскажу, как у меня настроены транзакции через Spring, хотя я и не использую таймауты.

1. Инициализация транзакций в конфигурации спринга, в данном случае мы указываем, что будем аннотировать нужные методы (классы) через @Transactional и транзактить будем свою sessionFactory через HibernateTransactionManager
Код


<bean id="coreSessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" destroy-method="destroy">
        <property name="dataSource" ref="coreDataSource" />
        <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
        <property name="hibernateProperties">
                .......
        </property>
</bean>

<tx:annotation-driven transaction-manager="coreTransactionManager"/>
    
<bean id="coreTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="coreSessionFactory"/>
</bean>


Вот и вся конфигурация. Теперь в корневом методе, от которого должна начинаться транзакция и откат, пишем: 

        
Код

@Transactional(
        readOnly = false,    
        isolation = Isolation.READ_COMMITTED, 
        propagation = Propagation.REQUIRES_NEW,
        rollbackFor = MyDataBusinessException.class,
        timeout = 15
)
public void doWithMyTransactionalData() throws MyDataBusinessException {
    ....
}


Кратко поясняю. Транзакция откатывается при любом RuntimeException а так же при любом корневом или наследнике MyDataBusinessException.class. В данном методе обязана открыться новая транзакция, даже если вызывающий поток уже находится в своей транзакции. Изоляция ReadCommitted, но там уже сами почитайте. Ну и ключевое для вас - 15 секунд таймаут. 

Следующее: включить в транзакции фильтры не получится, так как они вызываются перед корневым методом в любом случае. А кроме того, по библии smile если ваша правая рука пишит фильтры, которые что-то делают с данными, лучше оторвите правую руку, чтобы она не грешила smile . Дальше, фильтры эти должны выполняются мнгновенно, даже их десяток, так что на исход транзакции вляить не должны. 

Следующая загвоздка с таймаутом в том, что не все драйвера не ко всем базам поддерживают управление таймаутом из драйвера, так что, возможно, придется настраивать таймаут транзакции в самой базе. 

Последнее. Вы пишете: 
Цитата

сервис, который обрабатывает данные, дергает по мимо DAO объектов еще два специфичных сервиса, один медиа сервис, другой платежный. Поэтому я не очень понимаю, как тут использовать декларативный способ управления транзакциями. Нужен ведь правильная реализация PlatformTransactionManager  То есть ее необходимо писать самому.


Тут я так понимаю, что если вы внутри этой транзакции через сервисы у кого-то запрашиваете данные, то тут ничего страшного нет. Если вы передаете данные по сервисам на запись, ну.. тут только варинат с поддержкой удаленным сервисом вызова отката. Понятное дело, что если бы все удаленщики сидели в каком-то глобальном ejb + jndi спейсе, проблем бы не было.. Но других вариантов, кроме как требовать от них метод отката операции не вижу. 

Вроде все. Надеюсь, что помог.

Автор: Alagert 17.6.2010, 15:12
Всем спасибо за ответы.


afon, спасибо большое за детальный ответ. Но, к сожалению, он мне не подходит. Поясню почему. Если бы действия с данными крутились только вокруг записи в БД, никаких проблем не было бы. Легко декларативно развешиваем управление транзакциями либо по Вашему варианту, либо на основе аспектов. Но, как я уже писал выше, мой сервис вызывает еще 2 очень специфичных сервиса, которые не поддерживают JTA. Поэтому я не могу использовать стандартные JTA менеджеры транзакций. 

Цепочка запрос ответ такая:

Запрос -> Пачка фильтров -> Контроллер -> Головной сервис -> Контроллер -> Ответ клиенту

Головной сервис использует:
1. Обработки пользовательских данных (у него есть DAO объект, сохраняющий в базу)
2. Сторонний медиа сервис (Отгорожены от реального сервиса фасадом)
3. Платежный сервис

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

В моем случае транзакция должна начинаться с момента когда первый фильтр начал работу, до момента отдачи последнего байта ответа клиенту. Медиа сервис и платежный не поддерживают JTA, поэтому коммит и роллбэк для них пишется руками. 

Сейчас экспериментирую со своей реализацией PlatformTransactionManager и декларативным подход для управлениями транзакциями с помощью аспектов.

Автор: afon 18.6.2010, 12:06
Цитата

Запрос -> Пачка фильтров -> Контроллер -> Головной сервис -> Контроллер -> Ответ клиенту

Головной сервис использует:
1. Обработки пользовательских данных (у него есть DAO объект, сохраняющий в базу)
2. Сторонний медиа сервис (Отгорожены от реального сервиса фасадом)
3. Платежный сервис


Цитата

Медиа сервис и платежный не поддерживают JTA, поэтому коммит и роллбэк для них пишется руками. 


С JTA и так сразу было понятно, что часть цепочки его не поддерживает. НО значит роллбек для удаленных сервисов все-такие какой-то есть? Ну тогда не так все плохо. 
Тогда или руками запускать каждую транзакцию (там пара строчек всего и в настройке и в коде) и в catch {} куске обрабатывать удаленные роллбеки или найти, чем в Спринге оверрайднуть то, что у них вызывает откат, идописать в него свои роллбеки по удаленным сервисам. Ну а по фильтрам, я все-таки считаю, что их совершенно незачем включать в транзакцию, но дело ваше, да и специфика ваша. 

Кстати, на сколько я знаю, в е-платежках откаты не практикуются. Это целый принцип екоммерса - многновенность и безоткатность.. Так что эта часть меня в какой-то степени заинтересовала. Неужели есть системы предлагающие откат последней операции (или операции по id)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)