Message-Driven Bean Timers

Message-driven bean timers are similar to stateless session bean timers in several ways: timers are associated only with the type of bean. When a timer expires, a message-driven bean instance is selected from a pool to execute the ejbTimeout( ) method. In addition, message-driven beans can be used for performing audits or other types of batch jobs. The primary difference between a message-driven bean timer and a stateless session bean timer is the way in which they’re initiated: timers are created in response to an incoming message or, if the container supports it, from a configuration file.

In order to initialize a message-driven bean timer from an incoming message, simply put the call to the TimerService.createTimer( ) method in the message-handling method. For a JMS-based message-driven bean, the method call goes in the onMessage( ) method:

public class JmsTimerBean 
      implements javax.ejb.MessageDrivenBean, javax.ejb.TimedObject {
    
    public void onMessage(Message message){
        MapMessage mapMessage = (MapMessage)message;
        long expirationDate = mapMessage.getLong("expirationDate");
        
        TimerService timerService = ejbContext.getTimerService( );
        timerService.createTimer(expirationDate, null );
                   }
    
    public void ejbTimeout( ){
        // put timeout logic hear
    }

The incoming JMS message should contain information about the timer: the beginning (start) date, duration, or even the serializable info object. Combining JMS with the Timer Service can offer some powerful design options for implementing audits, batch processing, and agent-like solutions.

Although it’s not standardized, it is possible that vendors will allow message-driven bean timers to be configured at deployment time. This would require a proprietary solution, since standard configuration options for message-driven bean timers do not exist. The advantage of configured timers is that they do not require a client to initiate some action to start the timer. When the bean is deployed, its timer is set automatically. This capability makes message-driven bean timers more like Unix cron jobs, which are preconfigured and then run. Consult your vendor to see if they offer a proprietary configuration for message-driven bean timers.

As was the case for stateless session beans, the TimedObject interface changes the life cycle of the message-driven bean slightly (see Figure 13-3). When a timed event occurs, the container must pull a message-driven bean instance from the pool. If there are no instances in the pool, then an instance must be moved from the Does Not Exist state to the Method Ready Pool before it can receive the timed event.

Message-driven bean life cycle with TimedObject

Figure 13-3. Message-driven bean life cycle with TimedObject

Problems with the Timer Service

The Timer Service is an excellent addition to the EJB platform, but it’s limited. A lot can be learned from cron, the Unix scheduling utility that’s been around for years. Here are some proposals for improving the service. If you are only interested in learning how timers work now, as opposed to how they may be improved, feel free to skip the rest of this chapter—it’s not required reading. That said, understanding how timers can be improved helps you understand their limitations. If you have some time and want to expand your understanding of timers, keep reading.

A very little bit about cron

Cron is a Unix program that allows you to schedule scripts (similar to batch files in DOS), commands, and other programs to run at specified dates and times. Unlike the EJB Timer Service, cron allows for flexible calendar-based scheduling. Cron jobs (anything cron runs is called a job) can be scheduled to run at intervals, including a specific minute of the hour, hour of the day, day of the week, day of the month, and month of the year.

For example, you can schedule a cron job to run every Friday at 12:15 p.m., or every hour, or the first day of every month. While this level of refinement may sound complicated, it is actually very easy to specify. Cron uses a simple text format of five fields of integer values, separated by spaces or tabs, to describe the intervals at which scripts should be run. Figure 13-4 shows the field positions and their meanings.

Cron date and time format

Figure 13-4. Cron date and time format

The order of the fields is significant, since each specifies a different calendar designator: minute, hour, day, month, and day of the week. The following examples show how to schedule cron jobs:

20    *   *   *   *   --->   20 minutes after every hour. (00:20, 01:20, etc.)
 5   22   *   *   *   --->   Every day at 10:05 p.m. 
 0    8   1   *   *   --->   First day of every month at 8:00 a.m.
 0    8   4   7   *   --->   The fourth of July at 8:00 a.m.
15   12   *   *   5   --->   Every Friday at 12:15 p.m.

An asterisk indicates that all values are valid. For example, if you use an asterisk for the minute field, you’re scheduling cron to execute the job every minute of the hour. You can define more complex intervals by specifying multiple values, separated by commas, for a single field. In addition, you can specify ranges of time using the hyphen:

0   8   *   *   1,3,5   --->   Every Monday, Wednesday, and Friday at 8:00 a.m.
0   8   1,15    *   *   --->   The first and 15th of every month at 8:00 a.m.
0   8-17    *   *   1-5 --->   Every hour from 8 a.m. through 5 p.m., Mon-Fri.

Cron jobs are scheduled using crontab files, which are simply text files in which you configure the date/time fields and a command—usually a command to run a script.

Improving the Timer Service

The cron date/time format provides a lot more flexibility than is currently offered by the EJB Timer Service. The Timer Service requires you to designate intervals in exact milliseconds, which is a bit awkward to work with (you have to convert days, hours, and minutes to milliseconds), but more importantly, it’s not flexible enough for many real-world scheduling needs. For example, there is no way to schedule a timer to expire on the first and 15th of every month, or every hour between 8 a.m. and 5 p.m., Monday through Friday. You can derive some of the more complex intervals, but only at the cost of adding logic to your bean code to calculate them, and in more complicated scenarios, you’ll need multiple timers for the same task.

Cron is not perfect either. Scheduling jobs is like setting a timer on a VCR: everything is scheduled according to the clock and calendar. You can specify that cron run a job at specific times of the day on specific days of the year, but you can’t have it run a job at relative intervals from an arbitrary starting point. For example, cron’s date/time format doesn’t let you schedule a job to run every 10 minutes, starting now. You have to schedule it to run at specific minutes of the hour (e.g., 0, 10, 20, 30, 40, 50). Cron is also limited to scheduling recurring jobs; you can’t set up a single-action timer, and you can’t set a start date. A problem with both cron and the EJB Timer Service is that you can’t program a stop date—a date on which the timer will automatically cancel itself.

You also may have noticed that cron granularity is to the minute rather than the millisecond. At first glance this looks like a weakness, but in practice it’s perfectly acceptable. For calendar-driven scheduling, more precision simply isn’t very useful.

The Timer Service interface would be improved if it could handle a cron-like date/time format, with a start date and end date. Rather than discard the current createTimer( ) calls (which are useful, especially for single-action timers and arbitrary millisecond intervals), it would be preferable simply to add a new method with cron-like semantics. Instead of using 0-6 to designate the day of the week, it would be better to use the values Sun, Mon, Tue, Wed, Thu, Fri, and Sat (as in the Linux version of cron). For example, code to schedule a timer that would run every weekday at 11:00 p.m. starting October 1, 2003, and ending May 31, 2004, would look like this:

TimerService timerService = ejbContext.getTimerService( );
Calendar start = Calendar.getInstance( ).set(2003, Calendar.OCTOBER, 1);
Calendar end = Calendar.getInstance( ).set(2004, Calendar.MAY, 31);

String dateTimeString = "23   *   *   *   Mon-Fri";
timerService.createTimer(dateTimeString, start, end, null);

This proposed change to the Timer Service retains the millisecond-based createTimer( ) methods, because they are very useful. While cron-like configuration is powerful, it’s not a silver bullet. If you need to schedule a timer to go off every 30 seconds starting now (or any arbitrary point in time), you need to use one of the existing createTimer( ) methods. True millisecond accuracy is difficult; first of all, normal processing and thread contention tend to delay response time, and secondly, a server clock must be properly synchronized with the correct time (i.e., UTC)[45] to the millisecond, and most are not.

Message-driven bean timers: Standard configuration properties

There is enormous potential for using message-driven beans as cron-like jobs that are configured at deployment and run automatically. Unfortunately, there is no standard way to configure a message-driven bean timer at deployment time. Some vendors may support this, while others do not. Preconfigured message-driven bean timers are going to be in high demand by developers who want to schedule message-driven beans to perform work at specific dates and times. Without support for deployment-time configuration, the only reliable way to program an enterprise bean timer is to have a client call a method or send a JMS message. This is not an acceptable solution. Developers need deployment-time configuration and it should be added to the next version of the specification.

Building on the cron-like semantics proposed in the previous subsection, it would be easy to devise standard activation properties for configuring message-driven bean timers at deployment time. For example, the following code configures a message-driven bean, the Audit EJB, to run at 11 p.m., Monday through Friday, starting October 1, 2003, and ending May 31, 2004 (start and end dates are not required):

<activation-config>
  <description>Run Monday through Friday at 11:00 p.m. 
                                    Starting on Oct 1st,2003 until May 31st, 2004</description>
  <activation-config-property>
    <activation-config-property-name>dateTimeFields
                         </activation-config-property-name>
    <activation-config-property-value> 
                     23   *   *   *   Mon-Fri
                         </activation-config-property-value>
  </activation-config-property>
  <activation-config-property>
    <activation-config-property-name>startDate</activation-config-property-name>
    <activation-config-property-value>October 1, 2003
                         </activation-config-property-value>
  </activation-config-property>
  <activation-config-property>
    <activation-config-property-name>endDate</activation-config-property-name>
    <activation-config-property-value>May 31, 2004
                         </activation-config-property-value>
  </activation-config-property>
</activation-config>

This type of configuration would be fairly easy for providers to implement if they supported enhanced cron-like semantics. In addition, you could configure message-driven beans to use the millisecond-based timers EJB 2.1 already supports.

Other problems with Timer API

The semantics of the Timer object convey little information about the object itself. There is no way to determine whether a timer is a single-action timer or an interval timer. If it’s an interval timer, there is no way to determine the configured interval, or whether the timer has executed its first expiration. To solve these problems, additional methods should be added to the Timer interface that provide this information. As a stopgap, it’s a good idea to place this information in the info object so it can be accessed by applications that need it.



[45] Coordinated Universal Time (UTC) is the international standard reference time. Servers can be coordinated with UTC using the Network Time Protocol (NTP) and public time servers. Coordinated Universal Time is abbreviated UTC as a compromise among standardizing nations. A full explanation is provided by the National Institute of Standards and Technology’s FAQ on UTC at http://www.boulder.nist.gov/timefreq/general/misc.htm#Anchor-14550.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.117.191