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


Автор: vzf 10.11.2008, 16:30
Добрый день. 

У меня есть ejb таймер и мне бы хотелось сделать так, чтоб он запускался в момент запуска j2ee приложения, а останавливался при остановке приложения. Вопрос: как это правильно сделать ? У меня чисто ejb приложение, нет веба. На сервере ejb, обращение к ним идет из desлtop-клиента. Был бы веб, можно было бы в листенере сервлета прописать запуск и остановку таймера...
Товарищи, никто из вас не подскажет какой-нибудь другой способ реализации запуска и остановки таймера ? Или придется все-таки делать сервлет только ради запуска таймера ?

Буду благодарен советам smile 

Автор: powerOn 10.11.2008, 19:33
Цитата(vzf @  10.11.2008,  16:30 Найти цитируемый пост)
У меня есть ejb таймер и мне бы хотелось сделать так, чтоб он запускался в момент запуска j2ee приложения,


на деплой EJB модуля, насколько мне известно, лисенера не повесить, только если какие-то серверозависимые пути решения искать. 
Либо, подойти к вопросу с другой точки зрения, спросив себя: "А что значит момент старта приложения?" и "А не сделать ли мне "момент старта приложения" в момент первого обращения к какому-либо бину?" Тогда быть может и решение будет простым ;-)

Автор: MisterCleric 11.11.2008, 10:12
powerOn

Вполне логичный ответ. Я в свое время тоже тоже боролся с такой проблемой - хотел поднят спринг-контекст сразу после деплоя ear. Порылся в гугле и нашел решение через JMX. В спринге стартовал подобный ejb таймер. Ну и типа запрашивал сущности с базы для кеширования. А потом понял, что излишняя задача: сущности кешировать можно и по перевому запросу, а сам таймер стартовать как раз MBean'ом... Ему можно сказать депенденс от деплоя ear. и сразу после этого в методе старт вызывал метод бина createTimer()...

думаю, суть понятна.

Автор: KostenkoSergey 17.11.2008, 16:25
Для некоторых апп-серверов (например WAS), есть возможность "запускать EJB при запуске приложения".

С другой стороны если взглянуть на "лучшие практики", то "методов" автоматического запуска ежб-таймера всего три:

1.  Create the timer by invoking the EJB method. (нам не падходит)
2.   Use a Startup class using the proprietary API of your J2EE container. (спорноый вариант, с точки зрения переносимости)
3.  Create a servlet and implement the init method to invoke the EJB method that creates the timer. Set the load-on-startup property for the servlet to automatically start the servlet when the web module is started. (Бинго !) smile


Как мне кажется, именно связка  "ServletContextListener-EJB" и будет подходящим решением для Вашей задачи.

Автор: w1nd 18.11.2008, 18:59
С сверлетом тоже может не срастись - на некоторых серверах и не срастается. В JCA 1.5 появилась возможность создавать такие штуки, которые на жизненный цикл приложения могут реагировать. А JCA 1.5, ЕМНИП, везде реализована.

Автор: Evgeni68 18.11.2008, 19:07
На JBoss момент старта/остановки сервера, deploy/undeploy приложения отслеживали при помощи MBean-а, у которого существуют callback методы жизненного цикла.
Правда наследовали от специфичного для JBoss класса ServiceMBeanSupport.

Автор: mbasil 20.11.2008, 19:13
Если у Вас не легкий EJB контейнер, то в любом сервере приложений web контейнер всегда будет иметь место, используете ли вы его - или нет.

В одном примере Sun встретил такой пример:
Код

import javax.servlet.ServletContext;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent;
import javax.ejb.*;
import ejbcomponents.*;

public class SchedulerContextListener implements ServletContextListener {

    @EJB private StockMessageGeneratorRemote msgGen;
    
    public void contextInitialized(ServletContextEvent evt) {
        ServletContext ctx = evt.getServletContext();
        String interval = ctx.getInitParameter("interval");
        
        if(interval == null) {
            interval = "10";
        }
        
        String delemitedStocks = ctx.getInitParameter("stocks");
        Object o = new ...;

        msgGen.scheduleTimer( o, interval );
    }
    public void contextDestroyed(ServletContextEvent evt) { }
}


По моему это самый подходящий вариант, так как
1. Это предпочтительней сервлета и срабатывает именно при старте приложения.
2. Компоненты типа MBean разные на каждом сервере и это потребует при переносе выполнять изменениея.

Автор: MisterCleric 21.11.2008, 10:06
Вопрос по поводу переноса:
А часто ли вам в своей практике приходиться переносить приложение с одного контейнера на другой?
Я вот за три года работы дальше JBOSS и TomCat не пошел - нету требований на другие сервера приложений. 
Да хоть и этак при переезде все-равно придеться что-то переделывать. Не ужели нельзя будет и старт EJB-таймера реализовать конкретно под сервер? Что-то мне подсказывает, что переделывать-то всего лишь наследование от контейнер-зависимых классов и интрерфейсов.
Наверное, мин 5 работы. с переписыванием и компиляцией...

Автор: w1nd 21.11.2008, 11:56
Цитата(MisterCleric @  21.11.2008,  10:06 Найти цитируемый пост)
Что-то мне подсказывает, что переделывать-то всего лишь наследование от контейнер-зависимых классов и интрерфейсов.Наверное, мин 5 работы. с переписыванием и компиляцией...

Вопрос в том, что вам нужно - переносить приложение или сделать переносимым. В принципе, в каждом сервере есть некоторые средства, которые позволят вам получить нужный функционал, но на переделку уйдёт не пять минут, а уж сколько уйдёт на изучение вопроса...

Автор: mbasil 21.11.2008, 12:13
To MisterCleric
Парадокс заключается в том, что в настоящее время все больше и больше задач, которые становятся типовыми, мы выносим из приложения и возлагаем ответственность за их выполнение на сервер приложений.
Зачастую к таким задачам теперь относится:
1. Настройка пула подключений к базе данных.
2. Создание источников данных и помещение их в JNDI.
3. Аутентификация пользователей.
4. Авторизация пользователей.
5. и т.п.
Проблема заключается в том, что все эти решения не стандартизованы, а реализация всегда специфическая для вендора сервера приложения. Причем поставщики серверов как будто соревнуются в том, чтобы предложить решения отличающиеся от других.
Одно решение переделать под новый сервер можно быстро, а много не связанных друг с другом?
1. Использование MBean оправдано и весьма хорошо в тех случаях, когда задачу нельзя решить средствами приложения.
2. Полагаться на решения для конкретного сервера волей-неволей придется. Однако здесь нужен здоровый компромисс.
3. Переносить приложение может и не понадобится, но не учитывать несовместимость серверных решений неправильно. 
Это всего лишь мое мнение и я излагаю его вследствие того, что это затронул MisterCleric
Меня уже упрекали модераторы за то, что я выхожу за пределы вопроса тописка, поэтому я заранее прошу прощения.

Автор: KostenkoSergey 25.11.2008, 13:05
Цитата(MisterCleric @  21.11.2008,  10:06 Найти цитируемый пост)
А часто ли вам в своей практике приходиться переносить приложение с одного контейнера на другой?


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

Я пару месяцев назад закончил перевод проектов с BEAS на WAS - так вот, было много моментов написанных не по спецификации а под конкретное API серверов - та ещё головная боль при переносе...

Автор: vzf 27.11.2008, 18:20
Цитата(KostenkoSergey @ 17.11.2008,  16:25)
Для некоторых апп-серверов (например WAS), есть возможность "запускать EJB при запуске приложения".

С другой стороны если взглянуть на "лучшие практики", то "методов" автоматического запуска ежб-таймера всего три:

1.  Create the timer by invoking the EJB method. (нам не падходит)
2.   Use a Startup class using the proprietary API of your J2EE container. (спорноый вариант, с точки зрения переносимости)
3.  Create a servlet and implement the init method to invoke the EJB method that creates the timer. Set the load-on-startup property for the servlet to automatically start the servlet when the web module is started. (Бинго !) smile


Как мне кажется, именно связка  "ServletContextListener-EJB" и будет подходящим решением для Вашей задачи.


Цитата

Если у Вас не легкий EJB контейнер, то в любом сервере приложений web контейнер всегда будет иметь место, используете ли вы его - или нет.


У меня не было ни одного сервлета в приложении. 

Цитата

У меня чисто ejb приложение, нет веба. На сервере ejb, обращение к ним идет из desлtop-клиента. Был бы веб, можно было бы в листенере сервлета прописать запуск и остановку таймера...


Но, алилуя ! В проекте появился небольшой веб-модуль с одним служебными сервлетом, поэтому запуск таймера я сделал в ServletContextListener.

Ура ! smile

Автор: mbasil 27.11.2008, 21:51
Кстати, не обязательно иметь сервлет, чтобы запускать ServletContextListener, он срабатывает сам по себе и именно при старте приложения. На самом деле изначально просто были придуманы неудачные названия.

ServletContext это на самом деле контекст приложения.
ServletContextListener это на самом деле прослушиватель старта и завершения работы приложения и прямого отношения к какому-либо сервлету не имеет.

Автор: vzf 28.11.2008, 11:12
Понятно, не знал этого, спасибо smile 

Автор: MisterCleric 28.11.2008, 11:46
А я бы сказал, что ServletContextListener имеет косвенное отношение к сервлетам - все-таки он лежит в пакете javax.servlet. Да и его экземпляр и вызовы методоп происходят в сервлет-контейнере...
т.е. варничеч с web.xml все-равно придется создавать

Автор: vzf 29.11.2008, 12:46
Да, придется, получится пустой варник с web.xml и ServletContextListener. У меня сейчас он практически пустой - там всего один служебный сервлет.

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