Избегайте выключения таймера на стеклянной рыбке - программирование
Подтвердить что ты не робот

Избегайте выключения таймера на стеклянной рыбке

У меня есть метод, аннотированный с помощью @Schedule, который вызывается контейнером раз в то время.

@Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
public void myTimerMethod() throws Exception {
    ...
}

Проблема заключается в определенных условиях. Я хочу, чтобы этот метод выдавал исключение, чтобы вызвать откат текущей транзакции. Но если я сделаю это более двух раз, таймер будет удален и больше не будет вызван!

INFO: EJB5119:Expunging timer ['[email protected]@[email protected]@[email protected]@domain1' 'TimedObject = MyBean' 'Application = My-War' 'BEING_DELIVERED' 'PERIODIC' 'Container ID = 89072805830524936' 'Fri Jan 25 21:49:30 CET 2013' '0' '*/5 # * # * # * # * # * # * # null # null # null # true # myTimerMethod # 0' ] after [2] failed deliveries

Я знаю, что могу настроить перенастройку таймера в domain.xml с помощью

<domains>
    ...
    <configs>
        <config>
            ...
            <ejb-container session-store="${com.sun.aas.instanceRoot}/session-store">
               <ejb-timer-service>
                     <property name="reschedule-failed-timer" value="true"></property>
                </ejb-timer-service>
            </ejb-container>
            ...
        </config>
    </configs>
    ...
</domains>

Но мой вопрос: могу ли я настроить этот параметр при развертывании моего приложения?

Не удается найти его:

glassfish-resources.xml
glassfish-ejb-jar.xml
glassfish-web.xml

Есть ли способ сделать это программно, может быть?

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

4b9b3361

Ответ 1

Я бы использовал другой подход.

Вместо того, чтобы бросать исключение непосредственно из запланированного метода, попробуйте ввести уровень косвенности, как в:

...
@Inject RealWorkHere realImplementation;

@Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
public void myTimerMethod(){
  try{
     realImplementation.myTimerMethodImpl()
  }catch (Exception x){
   // hopefully log it somewhere
  }
}
...

где RealWorkHere - это bean с фактической реализацией, как в:

@Stateless
public class RealWorkHere{
   @TransactionAttribute(REQUIRES_NEW)
   public void myTimerMethod() throws Exception {

   }
}

Это происходит с выгодой:

  • Не бросать исключение в транзакцию, инициированную контейнером (таким образом, избегая исключения)
  • Лучшее ведение журнала исключения
  • Очистить демаркацию "реальной" бизнес-транзакции.

См. также

Ответ 2

Текущая версия Glassfish до версии 4 удаляет таймер, если во время выполнения метода обратного вызова timeout возникает исключение приложения.

Исключение приложения вызывает откат текущей транзакции. В такой ситуации Glassfish еще раз повторяет безошибочное выполнение метода обратного вызова. Если произойдет откат снова, Glassfish удалит таймер.

Я подал проблему в трекер проблем Glassfish, чтобы не удалять таймер в случае исключения. Glassfish, кажется, единственный сервер приложений, который удаляет таймер в случае исключения приложения. См . Glassfish # 20749: Glassfish удаляет таймер, даже если метод обратного вызова сохраняет контракт для получения более подробной информации. Можете ли вы проголосовать за мой вопрос.

Я также подал вопрос о спецификации EJB, чтобы уточнить, как должен вести себя контейнер EJB в таких ситуациях. Смотрите ejb-speС# 111: Пожалуйста, проясните поведение контейнера, если исключение приложения выдается во время выполнения метода обратного вызова таймера для получения дополнительной информации.