Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login
×

You must be logged to download. Click here to login

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Java EE: How to Make Use of Design Pattern Timer Service

This article will explore what the design pattern Timer Service is, what the new features introduced in the API are, and how we can implement this standard in the new Java EE 7 platform.

The Timer Service is not referenced in the classic books of design patterns such as the GoF book. However, this programming model is widely used and considered in current applications of Java EE platform.

A large part of the enterprise applications need to perform tasks based on a calendar of events or at a scheduled time. This task can be, for example, the generation of weekly reports containing user activities, sending to a client an e-mail reminder, among other tasks that can range from simple to complex. Overall, the Timer Service allows developers to schedule events at specific times or at regular intervals within the Java EE platform.

In the rest of the article we will see how to implement this standard on the new Java EE 7 platform.

Timer Service Pattern

Java EE and Java SE platforms did not offer embedded solutions for operations based on time. However, some tools developed by third parties permitted this type of application development. For example, Quartz tool that is still widely used mainly in the Java SE environment.

From the EJB 2.1 specification the timer services were introduced. But in the Java SE, there is no timer service which can be used yet. Therefore, Quartz is the better option in both Java SE and Java EE platforms.

If you want to learn more about how to use Quartz libraries and other ways to schedule tasks in Java, please refer to some of our articles below:

More features and enhancements have been added in the EJB 3.2 specification (latest release) to the Timer Service which made it even more simple and robust. Among the innovations we have the @Schedule and @Schedules annotations introduction and even the expressions additions.

The Timer Service runs on a container as a service and logs the Enterprise JavaBeans (EJB) for callbacks (callbacks methods). It tracks the timers that exist and their respective schedules, and also persists the timerin case a server is turned off or has a failure of it.

In this case, the only thing that the developer needs to know is to schedule the task.

The Timer Service has undergone several improvements over time from the EJB 2.1 through the EJB 3.0, EJB 3.1 and EJB 3.2.

In the next section we will see how to implement the Timer Service in Java EE 7 platform.

Implementing Timer Service in Java EE platform

There are two types of timers in Java EE 7 platform, they are: the Automatic timers and Programmatic timers.

Automatic timers are configured by deploying (deployment) of an Enterprise Java Bean (EJB) that contains a method annotated with @Schedule or @Schedules. The annotated method is invoked by the container scheduler at specified times or intervals of time defined by annotations arguments. Such methods are referred to as callback methods. The timer starts counting once the EJB is deployed.

A programmatic timer, in turn, is configured at runtime by a method call on the business logic. The timer can be set dynamically and invoked at any time. Therefore, the timer starts when the programming logic determine that it should start.

In the next sections will be explained the differences between automatic and programmatic timers.

Automatic Timers

Any method annotated with @Schedule is called by the container which, in turn, applies the settings specified in the attributes of the annotation.

In Listing 1 we have an example of use of @Schedule annotation with some of its attributes.

Listing 1. Example usage of @Schedule annotation.

@Schedule(second="*/1", minute="*", hour="*")
public void runTask() {
	System.out.println("Task concluded with success!");
}

In this code snippet we can see that the runTask method is annotated with @Schedule indicating that the container should set a timer in the deployment of this method based on the values defined in the attributes of the annotation.

In the above example, the expression contained in each of the attributes indicates that the container will invoke the method runTask once every second.

By default, all the timers are persisted and restored after the shutdown or lock of a server. If the optional attribute "persistent" is set to "false" the timer is reset at server restart. Two additional attributes can be configured: "info" and "timezone". The attribute "info" allows a developer to provide a description when a call is made to the method "getInfo" at Timer interface. If the attribute "timezone" is set, this zone will be respected when the timer runs. Otherwise, the zone of the server is used.

In Listing 2 ,we have an example of using of the attributes "timezone" and "info".

@Schedule(hour = "23", minute = "59", timezone = "CET", info = "Generates Night Report.")
public void runTask() {
	   System.out.println("Task concluded with success!");
}

In the previous code, "runTask" method is called at 23:59 in the time zone of Central Europe, thus disregarding the server's time zone where the deployment was done. A call to the "getInfo" returns the text set in the attribute "info", ie "Generates Night Report".

All those can also be configured using more complete timers with @Schedules annotation (now no more @Schedule) through the use of multiple expressions as shown in the example of Listing 3.

Listing 3. Example of use of the Schedules.

@Schedules({
	@Schedule(dayOfMonth = "1"),
	@Schedule(dayOfWeek = "Mon,Tue,Wed,Thu,Fri", hour = "8")
})
public void runTask() {
	System.out.println("Task concluded with success!");
}

As we can see, the timer is triggered on the first day of each month and from Monday to Friday at 08:00.

Listing 4 code shows a complete example of an automatic timer.

Listing 4. Complete example of an automatic timer.

package br.com.mrbool.timer;

import javax.ejb.Schedule;
import javax.ejb.Schedules;

public class TimerExample {

	   @Schedules({
		  @Schedule(dayOfMonth = "1"),
		  @Schedule(dayOfWeek = "Mon,Tue,Wed,Thu,Fri", hour = "8")
	   })
	   public void executaTarefa() {
		  System.out.println("Task concluded with success!");
	   }
}

A disadvantage of the automatic timer is that your schedule is set at the time of the deployment and cannot be changed while the application is running. Fortunately, there is a solution to this situation through a programmatic timer. A programmatic timer lets you set the schedule at any time during execution. This timer will be better analyzed in the next section.

Programatic Timers

Programmatic timers are created at runtime by calling one of its "create" methods of the interface. The example in Listing 5 shows one of the "create" methods available in the interface.

Listing 5. Example of use of the method "createTimer" to create a programmatic timer.

public void setTimer() { 
	timerService.createTimer(30000, "New Timer"); 
}

When the setTimer method is invoked by the application we have the creation of a timer that invokes a "timeout" method in the same bean after the specified period of 30,000 milliseconds.

A method "timeout" is identified by @Timeout annotation and must obey certain requirements:

  1. It should not throw exceptions or return a value,
  2. It does not need take parameters, but if you receive, this should be the javax.ejb.Timetype
  3. There must be only one "timeout" method.

In Listing 6 we have an example of a method annotated with @Timeout that meets the specified requirements.

Listing 6. Example of using a timeout method.

@Timeout
public void timeoutExample() {
	System.out.println("Task concluded with success!");
}

The CDI container (Context Dependency Injection) injects a reference to the TimerService in an instance variable annotated with @Resource. The following is an example of the container in the injecting TimerService instance variable.

@Resource
TimerService timerService;

The above codes could be placed together in a single bean where the application calls the setTimer method and a "timeout" method which will be called after 30 seconds. In Listing 7, we have an example of how we could implement this programmatic timer

Listing 7. Example of implementing a programmatic Timer.

package br.com.mrbool.timer;

import javax.annotation.Resource;
import javax.ejb.Timeout;
import javax.ejb.TimerService;

public class ProgramaticTimerExample {

   @Resource
   TimerService timerService;

   public void setTimer(){
	  timerService.createTimer(30000, "New Timer.");
   }

   @Timeout
   public void runTask() {
	  System.out.println("Task concluded with success!");
   }
}

There is a total of four methods of creating timers in TimerService interface with a total of ten signatures.

In the following example we have the createIntervalTimer method that creates a timer that is triggered at a given date and then every ten seconds:

createIntervalTimer(new Date(), 10000, new TimerConfig());

In the next example we have the createSingleActionTimer method that creates a timer that is triggered after one second.

createSingleActionTimer(1000, new TimerConfig());

In the example below we have the createTimer method that creates a timer that is triggered after 30 seconds:

createTimer(30000, "New Programatic Timer!");

In the example below, we have the createCalendarTimer method that creates a timer that is triggered every 10 seconds:

createCalendarTimer(new ScheduleExpression().second("*/10").minute("*").hour("*"));

All methods beyond "createCalendarTimer"methodcan receive as first parameter a duration in milliseconds or a date. This sets the point at which the timer is triggered. Take a look at the example in Listing 8.

Listing 8. Example of use of createSingleActionTimer creation method.

SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy ‘at’ HH:mm");
Date date = formatter.parse("07/01/2015 at 17:00");
timerService.createSingleActionTimer(date, new TimerConfig());

In this example, the method "timeout" is called at 17:00 of the day July 1, 2015.

If a timer is required we can use createCalendarTimer method. This method receives a ScheduleExpression which is set using expressions as discussed in the next section. Let's see an example in Listing 9.

Listing 9. Example of use of expressions with ScheduleExpression.

ScheduleExpression expression = new ScheduleExpression();
expression.second("*/10").minute("*").hour("*");
timerService.createCalendarTimer(expression);

In this code, the schedule is configured to start every ten seconds of every minute and every hour.

All the creation methods return a Timer object that represents the timer. The Timer object has the method "getHandle" which returns a serialized identifier for the timer. The object identifier can be kept in a database or memory. Subsequently, we could retrieve the object identifier and return a reference to the timer invoking the method "getTimer". With this object in hands, you can retrieve useful information about the timer. Details on the timer schedule can be retrieved using the "getSchedule" which returns a "ScheduleExpression" object. That, in turn, has the methods getters for each attribute. For example, the "getMinute()" method returns the value set for the attribute "minute".

The "getNextTimeout" method returns the point when the timer is triggered, while the method "getTimeRemaining" returns the milliseconds before the timer expires. The "isCalendarTimer" method returns "true" if the timer has been set for a "ScheduleExpression" object, but should be called the "getSchedule" method to determine if the timer has been set. Otherwise, the "isCalendarTimer" method throws an IllegalStateException exception. To determine information about the persistent state of the timer is to use "isPersistent" method. Similarly, we can obtain time information by calling the "getInfo". Timers are automatically canceled when they expire. To cancel scheduled timers simply call the method "cancel" on the Timer object.

Expressions in Timers

The programmatic timers and automatic timers can use the attributes to set the timer. In automatic timers, we can set the attributes in the annotations, while in programmatic timers we use the methods of ScheduleExpression class.

There are some restrictions that must be respected for each of the attributes:

  • the "second" attribute accepts one or more seconds within a minute with values between 0 and 59,
  • the attribute "minute" accepts one or more minutes in an hour with values between 0 and 59,
  • the attribute "hour" accepts one or more hours in a day with values between 0 and 23,
  • the attribute "dayOfWeek" takes one or more days within one week with values between 0 and 7 and 7 Sunday,
  • The attribute "dayOfMonth" takes one or more days within a month with values between 1 and 31 and also accepts the value -7 to -1 regarding days from the end of the month, Last to the last day, or 1st, 2nd, 3rd, etc., and finally, values between Sun and Sat,
  • the attribute "month" accepts one or more months within a year with values between 1 and 12 and with values between Jan and Dec,
  • and finally, the "year" attribute accepts a year like 2014, 2015 etc.

The default value for the attribute values is zero for the time and asterisk to the attributes that are not numerical. The asterisk is a placeholder for all possible values for an attribute. To set a timer that is triggered every hour, we can use, for example, the expression hour="*". The same applies to the hour method from the ScheduleExpression class in which would be used the method "hour("*")". Another possibility is to use a list or a range as the expression dayOfMonth="1, 15, last" to set up the starting in the first, fifteenth and last day of each month. In turn, the expression hour="8-18"represents every hour from 08:00 until 18:00. To specify intervals and increase them with a starting point, we could use the expression hour="8/1" that would start every hour from 08:00, differently from expression hour="*/12" that triggers every 12 hours.

You can also just set intervals for seconds, minutes and hours. Therefore, the expression

  • second="10" is triggered every ten seconds,
  • hour="2" is triggered every two hours,
  • minute="15" triggers every 15 minutes,
  • dayOfWeek="Mon, Fri"every Monday and Friday midnight,
  • the expression dayOfWeek="0-7", hour="8" triggers every day at 8 am,
  • dayOfMonth="-7"starts six days before the end of each month at midnight,
  • dayOfMonth="1st Mon", hour="22" triggers on the first Monday of every month at 10 pm,
  • the expressionMonth="Mar", dayOfMonth="15" triggers on the fifteenth day of March next year,
  • expressionyear="2015", month="May"starts at the first of March 2015 midnight.

In EJB 3.2, you can access all active timers in the EJB module. This includes programmatic and automatic timers.

In Listing 10, we have an example of how we can implement this feature in EJB.

Listing 10. Example of how to retrieve and manipulate timers.

package br.com.mrbool.timer;

import java.util.Collection;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timer;
import javax.ejb.TimerService;

@Singleton
@Startup
public class AllTimersExample {

   @Resource
   TimerService timerService;

   @PostConstruct
   public void manageTimers(){
		Collection<Timer> timers = timerService.getAllTimers();

		for(Timer t : timers){
			System.out.println("Timer Info: " + t.getInfo());
			System.out.println("Remaining Time: " + t.getTimeRemaining());
			//cancel the timer
			t.cancel();
		}
   }
}

Final Words

Note that the bean is instantiated at startup and the manageTimers method is called. In this method we recovere a collection of all active timers and after that we iterate on the entire collection by printing the timer information and the number of milliseconds remaining before expiration of the programmed timer. Finally, it cancels the timer.

If you want to complement your reading about this subject, we strongly recommend to refer:



Julio is a System analyst and enthusiast of Information Technology. He is currently a developer at iFactory Solutions company, working in the development of strategic systems, is also a JAVA instructor. He has knowledge and experi...

What did you think of this post?
Services
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login