How to implement a constantly running process in JavaEE

How do you propose to implement the following in JavaEE:

  • I need to have a background process on the application server (I was thinking of a session with beans state) that constantly monitors “something”, and if some conditions apply, it performs operations with the database.

  • The most important thing is to remotely manage different clients.

So, basically, I need a process that will work all the time, save its state and be open to a method call by several remote clients.

Since I'm new to JavaEE, I'm a little confused about which approach / "technology" to use. Help will be appreciated.

+5
source share
4 answers

singleton bean EJB - . bean , . bean . EJB, , bean .

:

@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
   }
}

. : Oracle JavaEE

+6

Java EE - . :

  • Java EE, , EJB:

    1.1 IDE: Eclipse Juno - , 1.2. . EJB3,

  • EJB. JBoss - , Glassfish - . JBoss JBoss Tools Eclipse, .

EDIT: EJB Timer ( )

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, '{} 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

}

, .

+1

, : 1) 2) .

For 1) you can use TimerServiceor create a stream using ServletContextListener. The second is not fully consistent, but it works. If you use timers, you can either create a periodic timer (as indicated by @dcernahoschi) or a unique timer that regresses itself:

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

If your periodic timer fires every 10 seconds and you have processing the last form for more than 10 seconds, you may have a problem. Having a timer that rebuilds itself works better if the processing time is not fixed.

For 2) you can go with stateless people or staefull EJB, what exactly is their purpose.

+1
source

All Articles