2013-04-07 17 views
5

Jak proponujesz do wdrożenia następujących w JavaEE:Jak wdrożyć proces stale pracuje w JavaEE

  1. muszę mieć proces tła w serwerze aplikacji (myślałem stanową fasoli sesji) który stale monitoruje "coś" i jeśli pewne warunki mają zastosowanie, to działa z bazą danych.

  2. Najważniejsze jest to, że musi on być manipulowany zdalnie przez różnych klientów.

Potrzebuję więc procesu, który będzie działał stale, zachowa swój stan i będzie otwarty na wywołania metod przez wielu klientów zdalnych.

Odkąd jestem nowy w JavaEE jestem nieco zdezorientowany, które podejście/"technologia" użyć. Pomoc byłaby doceniona.

Odpowiedz

6

Można użyć kombinacji bezstanowej sesji lub pojedynczego komponentu bean z usługą czasomierza EJB. Komponent bean był interfejsem używanym przez klientów zdalnych do kontrolowania procesu w tle. Usługa licznika czasu okresowo oddzwoni do metody na fasoli, aby zweryfikować warunek. Liczniki są automatycznie utrzymywane przez kontener EJB, więc wykonają swoje zadanie po odłączeniu klientów komponentu bean.

Oto szkic:

@Singleton 
... 
public TimerMangerbean implements TimerManager { 

    @Resource 
    private TimerService timerService; 

    public void startMonitoring() { 
     //start in 5 sec and timeout every 10 minutes 
     Timer timer = timerService.createTimer(5000, 60000, "MyTimer"); 
    } 

    public void stopMonitoring() { 
     Collection<Timer> timers = timerService.getTimers(); 
     for(Timer timer : timers) { 
     //look for your timer 
     if("MyTimer".equals(timer.getInfo())) { 
      timer.cancel();break; 
     } 
     } 
    } 

    //called every 10 minutes 
    @Timeout 
    public void onTimeout() { 
     //verify the condition and do your processing 
    } 
} 

Patrz także: Using the timer service on Oracle JavaEE tutorial

+0

Doceń swoją odpowiedź, ale miałem nadzieję na bardziej fundamentalny sposób robienia tego, rozwiązanie, które sugerujesz, wygląda bardziej na podstęp. Czy istnieje inne, bardziej fundamentalne rozwiązanie, które byłoby odpowiednie dla szerszego zakresu problemów ciągłych procesów i ich manipulacji. –

+0

Nie, to nie podstęp, 'TimerService' i' Timer' (s) są standardowym sposobem w JEE do sterowania i wykonywania powtarzalnych procesów. Nie wiążą cię z konkretnym rodzajem problemów. Jakie ograniczenia widzisz w tym podejściu? Jak stwierdziłeś, pytanie wydaje się idealnie pasować. – dcernahoschi

+0

+1 Nie ma bezpośredniego wsparcia dla długo działających procesów w tle w Java EE. Zamiast tego mają wsparcie okresowych timerów, z 'TimerService'. – ewernli

1

Java EE jest rozwiązaniem. Trzeba będzie śledzić thoses etapy:

  1. zbudować aplikację Java EE, słoik zawierający EJB:

    1.1 trzeba będzie IDE: Eclipse Juno jest mój ulubiony, 1,2 Wiele tuto istnieje na sieć. Wyszukaj EJB3, a znajdziesz,

  2. mieć serwer aplikacji do uruchamiania EJB. JBoss to dobry wybór, Glassfish to kolejny dobry wybór. Dzięki JBoss i zainstalowanej wtyczce JBoss Tools dla Eclipse, będziesz w stanie szybko zbudować i uruchomić podstawową aplikację.

EDIT: kompletna Klasa Timer EJB (z Autoprzeładowanie razie potrzeby)

package clouderial.saas.commons.utils; 

import java.util.Map; 

import javax.annotation.PreDestroy; 
import javax.annotation.Resource; 
import javax.ejb.ScheduleExpression; 
import javax.ejb.Timeout; 
import javax.ejb.Timer; 
import javax.ejb.TimerConfig; 
import javax.ejb.TimerService; 
import javax.inject.Inject; 

import jmcnet.libcommun.exception.ExceptionTechnique; 
import jmcnet.libcommun.utilit.mail.MailException; 

import org.apache.commons.configuration.event.ConfigurationEvent; 
import org.apache.commons.configuration.event.ConfigurationListener; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import clouderial.saas.commons.email.EmailSender; 
import clouderial.saas.commons.jpamongo.JPAMongoBasePersistenceContextAccessor; 

/** 
* A base class for a periodic process 
* @author jmc 
* 
*/ 
public abstract class PeriodicProcessBase extends JPAMongoBasePersistenceContextAccessor implements ConfigurationListener { 
    private static Logger log = LoggerFactory.getLogger(PeriodicProcessBase.class); 

    @Resource 
    private TimerService timerService; 

    @Inject 
    protected GlobalConfiguration _config; 

    @Inject 
    protected EmailSender _emailSender; 

    private Timer _timer=null; 

    private String _processName=null; 
    private Logger _log = null; 

    protected void initTimer(String processName, Logger log) { 
     if (processName != null) _processName = processName; 
     if (log != null) _log = log; 

     String second = _config.getString("timer."+_processName+".second","0"); 
     String minute = _config.getString("timer."+_processName+".minute","0"); 
     String hour  = _config.getString("timer."+_processName+".hours","4"); 
     String dayOfWeek = _config.getString("timer."+_processName+".dayOfWeek","*"); 

     ScheduleExpression scheduleExp = 
       new ScheduleExpression().second(second).minute(minute).hour(hour).dayOfWeek(dayOfWeek); 

     cancelTimer(); 
     if (timerService != null) { 
      _timer = timerService.createCalendarTimer(scheduleExp, new TimerConfig(_processName, false)); 
      _log.info("{} : timer programmed for '{}'h, '{}'m, '{}'s for days '{}'.", _processName, hour, minute, second, dayOfWeek); 
     } 
     else _log.error("{} : no timer programmed because timerService is not initialized. (Normal during tests)", _processName); 

     // Listen to change 
     _config.addModificationListener(this); // on timer modification, configurationChanged is called 
    } 

    @PreDestroy 
    private void cancelTimer() { 
     if (_log != null) _log.info("Stopping timer for '{}'", _processName); 
     if (_timer != null) _timer.cancel(); 
     _timer = null; 
    } 

    @Override 
    public void configurationChanged(ConfigurationEvent event) { 
     if (_log != null) _log.info("Configuration have change. Reloading config for ProcessBilling."); 
     _config.removeModificationListener(this); 
     initTimer(null, null); 
    } 

    @Timeout 
    private void run(Timer timer) { 
     runProcess(timer); 
    } 

    /** 
    * The entry point for runner the process. Must be overriden by super class 
    * @param timer 
    */ 
    protected abstract void runProcess(Timer timer); // do the job here 

} 

Mam nadzieję, że to pomaga.

+0

Tak, faktycznie uruchamiam JBoss 7.1.1 i Eclipse Juno z narzędziami JBoss. Pytanie, który konkretny interfejs API należy zastosować, aby proces był uruchamiany w sposób ciągły i na przykład nie był niszczony po rozłączeniu klienta (SLSB). –

+0

OK pozwala sprawdzić pełną odpowiedź powyżej dotyczącą implementacji TimerEJB w JBoss 7.1.1 – jmcollin92

1

Jak stwierdził sam, masz dwa warunki: 1) okresowo wykonywać pewne zadania w tle, oraz 2) reagują na żądania klientów.

Dla 1) można użyć TimerService lub odrodzić wątek z ServletContextListener. Drugi nie jest w pełni zgodny, ale działa.Jeśli używasz timerów, można stworzyć okresowy licznik (jak podkreślił @dcernahoschi) lub unikatowy czasomierz, że zmiany terminów spłaty sobie:

@Timeout 
public void onTimeout() { 
    //do something 
    // create a new timer 
} 

jeśli swoimi okresowych pożarów timera każdy 10 sek i masz przetwarzania, które trwają przez ponad 10 sekund, możesz mieć problem. Posiadanie zegara, który zmienia kolejność, działa lepiej, jeśli czas przetwarzania nie jest ustalony.

Dla 2) można iść z bezpaństwowcami lub EJB staefull, to jest dokładnie ich cel.