0

In one hand I've a CronScheduler class which is meant to starts once per application an configure a TimerService.
In the other hand I've a heavy task (annotated as @EJB) which I want to call in the @timeout of the timer. Note that in the timer, I create a thread which calls p.go()

The code:

@Singleton
@Startup
public class CronScheduler {

  @EJB
  Processor p;

  @Resource
  private TimerService timerService;

  @PostConstruct
  public void init() {
      String h = ... // h,m ,s work fine
      String m = ... 
      String s = ... 
      ScheduleExpression conf = new ScheduleExpression();
      conf.hour(h);
      conf.minute(m);
      conf.second(s);
      // I've tried with the second param (TimerConfig) enabled and disabled 
      timerService.createCalendarTimer(conf, new TimerConfig("msg ", false));
      LOG.log(Level.INFO, ">> Ready for: " + conf.toString());
  }

  @Timeout
  public void run() {
    LOG.log(Level.INFO, "Calling the process");
    Thread t = new Thread() {
      @Override
      public void run() {
        super.run();
        p.go();
      }
    };
    t.start();
  }

}

The point is, the cron is initialize multiple times. The @PostConstruct code runs N times. In the logs I see.

Ready for: A-B-C
Ready for: A-B-C
Ready for: A-B-C

The consequences are p.go() is called multiple times. Is the @singleton annotation working fine?

assylias
  • 321,522
  • 82
  • 660
  • 783
Manu Artero
  • 9,238
  • 6
  • 58
  • 73
  • 1
    Possibly related: http://stackoverflow.com/questions/9077966/postconstruct-method-called-twice-for-the-same-request and http://stackoverflow.com/questions/16796320/cdi-bean-constructor-and-postconstruct-called-multiple-times – assylias Apr 14 '15 at 07:54

2 Answers2

0

Perhaps you have more than one timer running? I recently encountered a weird scenario where timer was set to 1k ms and the new one started before the previous one finished. Adding some kind of lock fixed it for me. Maybe it's similar case.

You could debug and check how many threads you have active.

Dashovsky
  • 137
  • 9
0

Finally I got; it's a matter of EJB and hand-made threads. The point wasn't the Timer itself but the creation of a new thread which is not handled by the EJB magic.

@Singleton
@Startup
public class CronScheduler {

  @EJB
  Processor p;

  @Resource
  private TimerService timerService;

  @PostConstruct
  public void init() {
      String h = ... // h,m ,s work fine
      String m = ... 
      String s = ... 
      ScheduleExpression conf = new ScheduleExpression();
      conf.hour(h);
      conf.minute(m);
      conf.second(s);
      timerService.createCalendarTimer(conf, new TimerConfig("desc msg ", false));
      LOG.log(Level.INFO, ">> Ready for: " + conf.toString());
  }


  @Timeout
  public void run() {
    LOG.log(Level.INFO, "Calling the process");
    p.go();
  }
}
Manu Artero
  • 9,238
  • 6
  • 58
  • 73