Adam Bien's Weblog

Tuesday Feb 09, 2010

Simplest Possible EJB 3.1 Timer


@Singleton
public class TimerService {
    @EJB
    HelloService helloService;
  
    @Schedule(second="*/1", minute="*",hour="*", persistent=false)
    public void doWork(){
        System.out.println("timer: " + helloService.sayHello());
    }
}

A timer doesn't have to be a singleton - it can be a @Stateless and even a @Stateful bean. The method doWork() will be invoked every second. There is no registration or configuration needed.

How to compile:

You will need the EJB 3.1 API in the classpath, or at least the @Singleton, @Schedule and @EJB annotation.

How to deploy:

Just JAR or WAR the interceptor with an EJB and put the archive into e.g: [glassfishv3]\glassfish\domains\domain1\autodeploy

Btw. the initial deployment of the entire WAR took on my machine:


INFO: Loading application SimpleTimer at /SimpleTimer
INFO: SimpleTimer was successfully deployed in 363 milliseconds.

How to use:

Another service can be easily injected to the timer and so invoked periodically:

@Stateless
public class HelloService {
    public String sayHello(){
        return "Hello from control: " + System.currentTimeMillis();
    }
}

And: there is no XML, strange configuration, libraries, additional dependencies needed...You will find the whole executable project (tested with Netbeans 6.8 and Glassfish v3) in: http://kenai.com/projects/javaee-patterns/ [project name: SimpleTimer].

[See also "Real World Java EE Patterns - Rethinking Best Practices"] 


NEW workshop: Microservices with Java EE 7 and Java 8, January 26th, 2015, Airport Munich

A book about rethinking Java EE Patterns

Comments:

Can you please show the Java API for managing timers? In every scenario I can think of, I would need a Java API, not annotations. For example, a user designs an ad-hoc report and wants to have it emailed to three people every Friday at 5:00 PM. Should I have to recompile my source code for this?

Posted by Ryan de Laplante on February 09, 2010 at 04:52 PM CET #

@Ryan,

o.k. then I will write a post especially for you :-). The API was always available, you had to use that. Annotation are new in Java EE 6. With EJB 3.1 comes also a fluent-API. Will write a post about that,

thanks for your feedback!,

adam

Posted by Adam Bien on February 09, 2010 at 05:24 PM CET #

Hi Adam,

I'd be very interested too in examples on how to use the new timer API dynamically inside the code at runtime!

Moreover I'd like to hear your experience regarding performance and capability of the timer API in JEE 6. I'm thinking about a plan to port a standalone application to JEE 6. The app in question currently uses the Quartz framework to handle jobs with all sorts of scheduling plans. Do you think this could lead to performance problems for the scheduler in JEE 6 to handle a few hundred jobs (just the scheduling, not the work the jobs do)? Maybe Glassfish v3 is already using Quartz under the hood?!?

I've already posted this question some time ago in your Kenai forum but unfortunately didn't get an answer yet.

Thanks in advance!

Marco

Posted by Marco Ehrentreich on February 10, 2010 at 04:37 PM CET #

Hi Adam

Have you configured persistent timer for clustered environment? It is very common requirement to execute background job only on single cluster node.

It looks very easy, just set up persistent=true attribute for @Schedule. But I'm wondering how this feature is provided by AS in a portable way. For clustered version of Quartz you have to configure datasource (connection and schema) for jobs store.

I'm really interested in timer support for clustered environment.

Thanks in advance,
Marcin

Posted by Marcin on February 16, 2010 at 11:23 AM CET #

Can the timer values be injected so that we don't have hard-coded values in the class?

Posted by jkilgrow on February 23, 2010 at 06:32 PM CET #

Hi Adam,
Timers CANNOT be created for stateful session beans.

The spec says so. I am wondering why you said they can : "A timer doesn't have to be a singleton - it can be a @Stateless and even a @Stateful bean. "

Did i miss something ?

Posted by Celinio Fernandes on March 11, 2010 at 02:20 PM CET #

Thanks: That was cleanly put and a great place to start from (and it works).

Posted by Brian Silberbauer on April 01, 2010 at 12:11 PM CEST #

@Celinio

It is true that if you use the API that MDBs and SLSBs cannot create timers from a postconstruct, but the EJB 3.1 annotation spec is supposed to allow for timer creation in SLSBs and MDBs

Posted by Matt on August 18, 2010 at 04:23 AM CEST #

Excellent resource, EJB 3.1 are optimized for many processes in the server side, Java is the language in which I always find a solution with less coding.

Thank you from Mexico.

Posted by Diana Flores on January 28, 2011 at 03:06 AM CET #

Hi Adam,

I tried to deploy the war file on a Glassfish cluster, but it fails with the following message:

Error occurred during deployment: Exception while deploying the app [SimpleTimer] : Failed to create automatic timers for TimerService -- EJB Timer Service is not available.

We use Glassfish 3.1.1.
Have you tested the war file on a cluster?

Regards,

Jeroen

Posted by Jeroen on September 09, 2011 at 03:13 PM CEST #

Are you using the Web Profile version of GlassFish?

Posted by Alexis MP on September 12, 2011 at 12:47 PM CEST #

@Alexis,

no, I'm always using the full version. It is just 30 MB difference and no noticeable runtime overhead between the both...

thanks!,

adam

Posted by Adam Bien on September 12, 2011 at 03:17 PM CEST #

Hi Adam,

We found the solution for this problem. It was not a cluster problem. The problem was that we changed the __TimerPool to a remote MySQL database. More information can be found on the Glassfish forum: http://www.java.net/forum/topic/glassfish/glassfish/error-deploying-timer-application-glassfish-311-cluster-fails-timerservice-not-availible-0.

Regards,

Jeroen

Posted by Jeroen on September 19, 2011 at 01:06 PM CEST #

Hi Adam ,
I'm wondered like jkilgrow. I read in the specifiaction too that you can create only timers from MDB, Sigleton When I try with JB7 create a Timer from stateful i get
Exception in thread "main" javax.ejb.EJBException: java.lang.IllegalStateException: JBAS014366: Session id hasn't been set for stateful component:Statefultest

Posted by Süleyman Vurucu on November 25, 2011 at 02:03 PM CET #

So how can you tell if your Timer is running properly? Is there something in the Glassfish admin tool(s) that you can check to see what's where regarding Timers?

Posted by Dave on April 07, 2012 at 03:36 AM CEST #

Hi Adam,
I have a query. If I schedule a service to run in every 5th seconds and actually the service takes 10 seconds to complete then how the situation will be handled? Like quartz scheduler which creates a thread for each job, is it going to create another thread to run on 6th seconds? or wait till the service completes its execution?

Thanks in advance for your help.

Posted by Souvik Basu on April 14, 2013 at 11:17 PM CEST #

Hi,

I have a big problem to solve and i expect that you could help.

I need to run a Timer Service like this on a cluster, with 3,4 or more nodes...but the timer must run in just one node.

I use JbossAS 5 and 6. In those version is just ok with the annotation: @Depends("jboss.ha:service=HASingletonDeployer,type=Barrier")

But in Jboss 7 I cant run in the same whay. The timer always run in every node.

Posted by Fábio Preti on May 28, 2013 at 02:28 AM CEST #

Really helpful article to start with timers on EJB 3.1. With this now I can avoid the using of Quartz for simple scheduling tasks.

Thank you very much.

Posted by Guillermo on September 22, 2013 at 11:29 PM CEST #

How to recover from automatic timer fail?

In case you have a non-persistent automatic timer by annotating @Schedule plus you cover any exception by surrounding the code under execution with try ... catch but anyways that timer fails:

@Schedule(.., persistent=false)
public void pullMoney() {
try {
// my code
} catch (Throwable throwable) {
// NOP
}
}

My ERROR [org.jboss.ejb3.timerservice.mk2.task.TimerTask] (pool-251-thread-7) Error during retyring timeout for timer: [id=addde741-b246-41ce-8086-adea70d65dd5 timedObjectId=jboss.j2ee:ear=my.ear,jar=my.jar,name=MyTimerBean,service=EJB3 auto-timer?:true persistent?:false timerService=org.jboss.ejb3.timerservice.mk2.TimerServiceImpl@48ea5972 initialExpiration=Tue Nov 26 00:00:07 CET 2013 intervalDuration(in milli sec)=0 nextExpiration=Sun Dec 08 17:34:47 CET 2013 timerState=RETRY_TIMEOUT: javax.ejb.EJBTransactionRolledbackException: Transaction rolled back

How would you re-start the automatic timer that is not on schedule any more?

(The only solution seems to be a programmatic timer that can be re-scheduled from outer Beans.)

Agreed?

Posted by Tobias on December 09, 2013 at 10:03 PM CET #

Post a Comment:
  • HTML Syntax: NOT allowed
realworldpatterns.com
...the last 150 posts
...the last 10 comments
License