As the title suggestions, I want something to happen when my EJB application is started.
To give further context, I would like my bean to run, doing something every x minutes (e.g. checking some system property then sending out an email).
I can use the TimerService and schedule a reoccuring task - that seems straightforward. But, the question is, where can I put this Timer creation code?
Looking around, EJB3.1 gets over this with @schedule, but I'm trying to stick with EJB3.0 for the time being as it is this exam that I'm working towards and I don't want to confuse myself with what's in what!
Another solution is to use a ServletContextListener, but hijacking the web container in this way just feels like a bodge. As Timer's are persistent across Container restarts, you also have to be careful to check whether the appropriate Timer has already been created, or you could create multiples!
I'm wondering whether I can just use the bean's no-arg constructor. As long as I call super(), and keep it no-arg, perhaps I could sneak my Timer creation in there. The sacrifice is that I would still need to do the above described check (as we also could also have mutliple bean creations as well).
This also brings up an interesting question about bean instance numbers. How can I limit my bean to a single instance? I'm sure I read somewhere about a singleton pattern, so should I use that? Or, can I limit the pool to a single instance (ie. a max of one).
So many questions. I imagine though that this is a relatively simple/common thing, so would appreciate suggestions on any aspect of the above.
You can't create a Timer in a constructor because getTimerService() is available to you in @PostConstruct and later, in business methods, and only in SLSB. In ejb 3.1 I would go about it using a Singleton Bean with a @Startup annotation probably.
Not sure, but maybe there is / will be an equivalent of ServletContextListener for ejb 3.1? Reza should know sth about it.
There are two ways to do this - write slightly awkward code to start the EJB timer via a Servlet life-cycle listener or use Quartz/Flux to call an EJB method. Most real world applications do the latter, possibly using Spring to configure Quartz and hook up the EJB instance. Generally, the instance numbers are not a big concern since the schedule should be fairly mutually exclusive. If schedule overlap is an issue, limiting the number of instances would be the logical choice.
In EJB 3.1, this would be a use case for @Schedule or @Startup/@Singleton with a regular timer.
Hope it helps,
Independent Consultant — Author, EJB 3 in Action — Expert Group Member, Java EE 6 and EJB 3.1
Joined: Nov 11, 2006
Thank you very much for your replies.
Tbh, this sounds like such a common thing to want to do - I can think of so many uses - that I'm surprised it didn't get looked at until EJB 3.1
I guess that points to why other frameworks came in to fill this void.
I may give Quartz/Flux a look at - all new skills to be learned. Do I need to drag in Spring as well, or can I use these frameworks standalone somehow?
Perhaps that'll become clearer as I give them a better look.
Thanks once again,
Joined: Feb 01, 2005
You can use Quartz or Flux without Spring. However, Quartz in particular can be hard to configure without Spring. Neither really have a very hard learning curve. As to why it was not included in EJB before, it was considered in EJB 2.1. The consensus was that this is fine as a container/product specific feature that really isn't the core domain of EJB. Speaking of which, you can also look at schedulers built containers like WebLogic and WebSphere that can natively invoke EJB.
There are application server specific (non-portable) ways of doing this currently in EJB3.0. Which application server do you use? For JBoss, you can use the @Service which does what you are looking for.
At the moment, I'm using Glassfish 2.1. Mainly as a learning tool as it's new to me and Sun were plugging it so heavily at a recent Java Conference I attended (I wasn't brave enough to go for 3.0 prelude).