Использование реализации CommonJ с GlassFish и Spring 3
В своем стремлении объединить развертывание между средами Websphere 7 и GlassFish 3 я решил попробовать реализовать CommonJ WorkManager и TimerManager в GlassFish. Но это не совсем работает, как ожидалось. Я сделал следующее:
Используйте реализацию myFOO CommonJ, расположенную по адресу: http://commonj.myfoo.de/ и включите библиотеки в папку моего домена /lib (включая библиотеки Spring)
Добавлено следующее в <resources>
раздел glassfish domain.xml:
<custom-resource res-type="commonj.work.WorkManager" jndi-name="wm/default" factory-class="de.myfoo.commonj.work.FooWorkManagerFactory"></custom-resource>
<custom-resource res-type="commonj.timers.TimerManager" jndi-name="tm/default" factory-class="de.myfoo.commonj.timers.FooTimerManagerFactory"></custom-resource>
Включить ссылки в <servers>
/<server>
раздел домена.xml:
<resource-ref ref="wm/default"></resource-ref>
<resource-ref ref="tm/default"></resource-ref>
Добавьте соответствующие ссылки на ресурсы в web.xml моего тестового приложения:
<resource-ref>
<description>WorkManager</description>
<res-ref-name>wm/default</res-ref-name>
<res-type>commonj.work.WorkManager</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<resource-ref>
<description>TimerManager</description>
<res-ref-name>tm/default</res-ref-name>
<res-type>commonj.timers.TimerManager</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Unshareable</res-sharing-scope>
</resource-ref>
Добавьте следующие bean-компоненты в мой applicationContext.xml:
<bean id="threadTestTaskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName" value="wm/default" />
<property name="resourceRef" value="true"/>
</bean>
<bean id="threadTestTimerExecutor" class="org.springframework.scheduling.commonj.TimerManagerTaskScheduler">
<property name="timerManagerName" value="tm/default" />
<property name="resourceRef" value="true" />
<property name="shared" value="false" />
</bean>
<bean id="threadTest" class="test.ThreadTester"></bean>
<task:scheduled-tasks scheduler="threadTestTimerExecutor">
<task:scheduled ref="threadTest" method="execute" fixed-delay="30000" /> <!-- 30 seconds -->
</task:scheduled-tasks>
После всей этой настройки все загружает поиск и веб-приложение запускается; однако класс ThreadTester не запускается на таймере.
Я прошел через код myFOO, и основной цикл TimerManager (FooTimerManager.java) работает, просто кажется, что он никогда не распознает, что каждые 30 секунд он должен запускать класс.
Мои вопросы:
У кого-нибудь был опыт внедрения JSR 236/237 (CommonJ) со GlassFish 3 и Spring?
Есть ли другая реализация, отличная от myFOO, которую я мог бы использовать и попробовать? Кто-нибудь пытался сделать то, что я сделал? Хотели бы вы поделиться своими результатами, если бы вам это удалось?
Спасибо!
Изменить 1:
Я забыл упомянуть, что использование myFOO CommonJ-реализации с GlassFish действительно работает в отношении WorkManager. Что не работает, так это TimerManager. Это означает, что я могу запускать потоки по требованию просто отлично, но сработавшее планирование не работает.
Изменить 2:
После обновления до GlassFish 3.1.1 реализация TimeFManager myFOO CommonJ работает нормально. Так здорово! Этот вопрос теперь больше похож на HOWTO Guide.
3 ответа
Что ж, похоже, что после обновления до GlassFish 3.1.1 у меня больше нет проблем с реализацией myFOO TimerManager. мой @Scheduled
бобы работают очень хорошо сейчас.
Я не думаю, что будет хорошей идеей использовать TimerManager из myFoo CommonJ - в дополнение к тому, что он неактивен около 6 лет, в некоторых моментах код просто странный (ссылаясь на v1.1). Например, метод isExpired класса FooTimer выглядит следующим образом:
public boolean isExpired() {
return scheduledExcecutionTime >= System.currentTimeMillis();
}
Итак, таймер истечет, когда его запланированное время следующего выполнения будет в будущем? Ерунда - это должно быть наоборот!
В другом месте (TimerExecutor#run) notifyAll вызывается для объекта (TimerManager), для которого текущий поток не имеет монитора, что постоянно вызывает java.lang.IllegalMonitorStateExceptions.
Руки прочь!
Если вы работаете в Spring, почему вы используете другую реализацию Timer? Почему бы просто не использовать интеграцию планирования Spring? Тогда вам не нужно беспокоиться о том, на каком сервере запущено ваше приложение, поскольку Spring это не волнует.