EJB3.1 in JBoss AS 6.0.0.M4

Overview

 

JBoss AS 6.0.0.M4 introduces support for EJB3.1 Timer Service and EJB3.1 Asynchronous invocations.

 

 

What to download and how to use

 

You can download JBoss AS 6.0.0.M4 from here. After downloading the AS, start and stop it once to make sure it boots without any issues.

 

 

In the next steps we will see a simple EJB3.1 timerservice example (mainly the calendar expression support)

 

EJB3.1 Timer Service:

 

Note that the examples shown below are just for the sake of illustrating the usage of timerservice API and as such don't hold much meaning.

 

Let's deploy a very simple stateless session bean which exposes a remote business interface view

 

 

package org.jboss.ejb3.timerservice.example;

public interface SchedulerOps
{

   /**
    * Schedules a timer for the passed schedule    *   
    * @param schedule The calendar expression based schedule
    * 
    * 
    */
   void scheduleTask(ScheduleExpression schedule);
   
   
}

 

 

 

package org.jboss.ejb3.timerservice.example;

import java.util.Date;

import javax.annotation.Resource;
import javax.ejb.Remote;
import javax.ejb.ScheduleExpression;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;

import org.jboss.ejb3.annotation.RemoteBinding;

@Stateless
@Remote (SchedulerOps.class)
@RemoteBinding (jndiBinding = "myscheduler")
public class Scheduler implements SchedulerOps
{

   @Resource
   private TimerService timerService;
   
   @Override
   public void scheduleTask(ScheduleExpression schedule)
   {
      // Use the injected timerservice to create a timer instance,
      // for the passed schedule
      Timer timer = this.timerService.createCalendarTimer(calendarSchedule);
      
      // that's it, we are done. When the scheduled timeout occurs, the 
      // timeout callback method on this bean will be invoked by the server
   }
   
   /**
    * This timeout callback method will be invoked when the timer schedule
    * expires
    * 
    * @param timer The {@link Timer} for which the timeout occurred
    */
   @Timeout
   private void timeout(Timer timer)
   {
      // Let's just print out to System.out
      System.out.println("Timeout method invoked at " + new Date() + " for bean " + this.getClass().getSimpleName());
   }

}

 

 

In the example above, we have a SchedulerOps interface which is exposed as the remote view for the Scheduler Stateless session bean. The SchedulerOps interface allows scheduling timers based on a javax.ejb.ScheduleExpression. ScheduleExpression is used to express calendar based timeout expressions. Later in this wiki, we'll see how we create a calendar based schedule.

 

In order to create and operate on timers, we are injecting the TimerService into the bean, through the use of @javax.annotation.Resource annotation:

 


   @Resource
   private TimerService timerService;

 

 

The important scheduleTask method looks like this:

 

@Override
   public void scheduleTask(ScheduleExpression schedule)
   {
      // Use the injected timerservice to create a timer instance,
      // for the passed schedule
      Timer timer = this.timerService.createCalendarTimer(calendarSchedule);
      
      // that's it, we are done. When the scheduled timeout occurs, the 
      // timeout callback method on this bean will be invoked by the server
   }

 

We use the injected timerservice to create a calendar timer. A calendar timer is a Timer which is created based on a calendar schedule expression.

Please refer to the EJB3.1 spec for more details on ScheduleExpression.

 

For example, if we want to schedule a timer to fire every Friday at 5:45 in the morning, then we can create the following ScheduleExpression:

 

     ScheduleExpression everyFridayFiveFortyFive = new ScheduleExpression();
     everyFridayFiveFortyFive.dayOfWeek("Fri").hour(5).minute(45);
     

         

 

Now that we created a timer in our bean, the timer will be started after the bean's method completes(remember, timers are transactional, so the timer start waits for the transaction to complete). When the schedulded timeout occur, the server will invoke the timeout callback method on the bean. In our example, we have annotated our timeout() method as the timeout callback method (note the @Timeout annotation):

 

   /**
    * This timeout callback method will be invoked when the timer schedule
    * expires
    * 
    * @param timer The {@link Timer} for which the timeout occurred
    */
   @Timeout
   private void timeout(Timer timer)
   {
      // Let's just print out to System.out
      System.out.println("Timeout method invoked at " + new Date() + " for bean " + this.getClass().getSimpleName());
   }


 

Here's how the client code is going to schedule the timer through the bean:

 

package org.jboss.ejb3.timerservice.example.client;
 
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.jboss.ejb3.timerservice.example.*;
 
public class Client
{
   public static void main(String[] args) throws Exception
   {
     
      Context ctx = new InitialContext();
      // lookup the bean
      SchedulerOps scheduler = (SchedulerOps) ctx.lookup("myscheduler");
      
      // create a schedule
      // Every Tue at 2 and 4 in the afternoon during the month of August
      ScheduleExpression everyTueAtTwoAndFourInNoonDuringAugust = new ScheduleExpression();
      everyTueAtTwoAndFourInNoonDuringAugust.dayOfMonth("Tue").hour("14,16").month("Aug");
      
      // schedule our task
      scheduler.scheduleTask(everyTueAtTwoAndFourInNoonDuringAugust);
      
   }
 
}

 

In the client code, we first lookup the SchedulerOps remote business view of the bean. Then we create a calendar schedule which is expected to expire every Tuesday at 2 and 4 in the noon during the month of August. We then invoke the scheduleTask method on the bean. That's it! When the scheduled timeout occurs, you will see the timeout() method on the bean being called.

 

Auto timers

 

In the above example, we used a remote business view and a method on that interface just to create a timer. That can be avoided if we use auto timers. Auto timers are created automatically by the EJB container when a bean is deployed. The container looks for the presence of  @javax.ejb.Schedule or @javax.ejb.Schedules (or their xml equivalents) to decide whether auto timers are to be created.

Because of https://issues.jboss.org/browse/EJBTHREE-2229 you should set 'persistent=false' with @javax.ejb.Schedule annotation.

 

Here's an example of the same (using annotations):

 

package org.jboss.ejb3.timerservice.example;

import javax.ejb.Schedule;
import javax.ejb.ScheduleExpression;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
import javax.naming.Context;
import javax.naming.InitialContext;

@Stateless
public class AutoTimerBean 
{

   /**
    * This method will be invoked every day at 5:00:00 in the morning
    * @param timer The timer instance
    */
   @Schedule (hour = "5", persistent=false)
   private void executeEveryDayAtFive(Timer timer)
   {
      // do some task here. 
      System.out.println("Auto-timer method invoked at " + new Date() + " for bean " + this.getClass().getSimpleName());
      
   }

}

 

As you can see we have a Stateless (no-interface view) bean which has the executeEveryDayAtFive method. This method is annotated with @Schedule. The server will automatically create the timer when the bean is deployed. The schedule for the timer is passed through the annotation's attribute values. The method on which the @Schedule is used, will be considered the timeout callback method for that auto timer and will be invoked when the timeout occurs.

 

The example above creates an auto timer which is expected to fire every day at 5 in the morning.

 

Let's quickly see the use of @javax.ejb.Schedules (note the 's' in the end of that annotation name). That allows you to create multiple auto timers with different schedules for the same timeout callback method.

   /**
    * Multiple auto timers with different schedules will be created for this
    * timeout callback method
    * @param timer The timer instance
    */
   @Schedules (
   {
      @Schedule(hour="8", minute="15"),
      @Schedule(dayOfMonth="Mon", info="test")
   }
   )
   private void multiAutoTimeoutMethod(Timer timer)
   {
      // do some task here. for now, let's just print out to System.out
      System.out.println("Multi auto-timeout method invoked at " + new Date() + " for timer " + timer);
      
   }

In this example above, we have used @Schedules to create 2 auto timers, each with a different schedule. Note that you can even pass an optional "info" to the created timers. That info will be available through the javax.ejb.Timer in the timeout callback method. In this example, multiAutoTimeoutMethod method will be invoked when either of the scheduled timeout occurs.

 

What next?

 

Those were just some examples on EJB3.1 timerservice to get you started. Download JBossAS 6.0.0.M4 and try out your own application and/or examples and let us know how it goes. If you run into any issues, feel free to start a discussion in our EJB3 user forum or ping us on IRC.

 

 

I have some tutorial for singleton beans, Can I contribute?

 

Similar to our other EJB3 tutorials, we are going to include a tutorial for EJB3.1 Timer Service. Infact, the example that is posted here in the wiki, can perhaps be just added as a tutorial in SVN. If anyone of you wants to contribute a different tutorial and a chapter in our guide, then feel free to let us know - either through the forums or IRC.