Избегайте удаления таймера на glassfish

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

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

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

INFO: EJB5119:Expunging timer ['68@@1359143163781@@server@@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

Я знаю, что могу настроить переназначение таймера в домене.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

есть ли способ сделать это программно возможно?

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

2 ответов


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

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

...
@Inject RealWorkHere realImplementation;

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

здесь RealWorkHere является Бобом с фактической реализацией, как в:

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

   }
}

Это приходит с преимуществом:

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

см. также


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

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

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

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