Chapter 2. Scheduler Programming

Table of Contents

2.1. Overview
2.2. JEUS Scheduler Class
2.3. Defining Tasks
2.3.1. Implementing ScheduleListener Interface
2.3.2. Schedule Class Inheritance
2.3.3. Inheriting RemoteSchedule Class
2.4. Obtaining Scheduler Object
2.4.1. Obtaining Scheduler Object in Local Environment
2.4.2. Obtaining a Scheduler Object in Remote Environment
2.5. Registering Tasks
2.5.1. Registering One-Time Tasks
2.5.2. Registering Recurring Tasks
2.5.3. Registering Schedule Task Objects
2.6. Controlling Tasks
2.7. Using Scheduler
2.7.1. Using In a Standalone Environment
2.7.2. Using on JEUS Server
2.7.3. Using in Java EE Component
2.8. Using Job-list

This chapter describes the basic knowledge and instructions for JEUS Scheduler programming.

The following features have been added or changed since JEUS version 5.0. JEUS 5.0 is backward compatible and programs that are written in previous versions can be used without modification.

The next section describes the classes that make up the JEUS Scheduler, and how to define, register, and control a job schedule. All examples explained in this chapter can be found in the JEUS_HOME/samples/scheduler directory.

JEUS Scheduler is conceptually identical to and contains similar interfaces as J2SE Timer. The java.util.TimerTask class that represents a task corresponds to the jeus.schedule.ScheduleListener interface, and the java.util.Timer class that registers a task corresponds to the jeus.schedule.Scheduler interface. Previous users of J2SE Timer interface can easily use JEUS Scheduler.

The following figure shows each Scheduler API classes.


API ClassDescription
package jeus.scheduleAll classes and interfaces of JEUS Scheduler belong to jeus.schedule package and its sub-packages.
interface ScheduleListenerA task that needs to execute at a set time is defined as a class by implementing the ScheduleListener interface. ScheduleListener contains a callback method called onTime() that is invoked at the scheduled time.
abstract class ScheduleAbstract class that implements ScheduleListener which was used in versions earlier than JEUS 5.0. This class contains the nextTime() and onTime() callback methods. The nextTime() method is used dynamically to get the time to execute the task after it is scheduled.
abstract class RemoteScheduleSpecial abstract class that contains the initialize() callback method and receives initialization parameters when creating an object.
class SchedulerFactoryUsed to call a concrete Scheduler object.
interface SchedulerCore interface for registering tasks in JEUS Scheduler. It defines various registerSchedule() methods.
interface ScheduleControllerWhen a task is registered in the Scheduler, the object that implements the ScheduleController interface is returned. This handler object is used to get information about or cancel the task.
exception JeusSchedulerExceptionJeusSchedulerException may be thrown if an internal error occurs while registering or cancelling a task in JEUS Scheduler.

Note

For more information about each interface or class, refer to the JEUS Scheduler Javadoc API.

To execute a task, first the task class must be defined, and then the task according to the execution time and cycle.

Instead of directly implementing a ScheduleListener, it can be defined by inheriting the Schedule class or RemoteSchedule class.

The Schedule and RemoteSchedule classes are used in previous versions of JEUS. In JEUS 5.0, ScheduleListener must be implemented to define tasks in general, but the previous task classes are also provided for backward compatibility.

The Schedule abstract class contains the nextTime() callback method in addition to the onTime() method. The nextTime() method does not schedule the call time when registering tasks, but instead the next call time is scheduled in the task class. Therefore, it is more efficient to use the method for tasks with a variable time cycle than a fixed time cycle.

JEUS Scheduler determines the initial execution time by calling nextTime() after registering a task object. At the set time, onTime() is called and the task executes when onTime() call terminates. The nextTime() method must return the next scheduled execution interval in milliseconds. If it returns 0, the task will no longer execute.

Since the Schedule task object calls nextTime() after onTime() finishes executing, the nextTime() call is delayed while onTime() is executing. Therefore, it is difficult to write programs to execute the task at exact time intervals. Thus, it is recommended to set the execution cycle when registering tasks rather than through the nextTime() method.


The RemoteSchedule class is a Schedule object that can set the initialization parameters when registering tasks remotely. This is mainly used to register task objects using the class name.

The class contains the initialize() Callback method which is called just once after a task is registered. Therefore, it can be used to assign initialization values when using the class name to register a task remotely.

The initialize() callback is only invoked when RemoteSchedule task object is registered by using the Scheduler.registerSchedule(classname, hashtable, daemon_flag) method.


Note

When registering a task by using the Job-list or an API that uses the class name, a no-arg (default) constructor is required because the corresponding class is initialized by the container.

This section describes how to obtain a Scheduler object. JEUS Scheduler operates in both local and remote environments.

This section describes how to register tasks using the Scheduler interface.

The methods for registering tasks are the same in both local and remote Schedulers. The only difference is that the task objects are serialized and run remotely for a remote JEUS Scheduler.

Recurring tasks can be registered by specifying the initial execution time, cycle, termination time, and the maximum number of executions. Select either the fixed-delay or fixed-rate method according to the task.

Note

For a task registered as fixed-rate, JEUS Scheduler calls the task using another thread when the task execution is delayed, to guarantee the execution time. If a task execution is delayed, same tasks may be executed concurrently and task objects should be checked for thread-safety.

Tasks can be registered using the following methods.

registerSchedule(ScheduleListener task, Date firstTime, long period, Date endTime, 
                 long maxcount, boolean isDaemon)

registerSchedule(ScheduleListener task, long delay, long period, Date endTime, 
                 long maxcount, boolean isDaemon)

registerScheduleAtFixedRate(ScheduleListener task, Date firstTime, long period, 
                 Date endTime, long maxcount, boolean isDaemon)

registerScheduleAtFixedRate(ScheduleListener task, long delay, long period, 
                 Date endTime, long maxcount, boolean isDaemon)

The following describes each parameter.

ParameterDescription
Date firstTimeInitial execution time.
long delayNext execution time relative to the current time (unit: milliseconds).
long periodRecurring execution cycle (unit: milliseconds).
Date endTimeTermination time after which a task is no longer executed. If set to null, the recurring task executes indefinitely.
long maxcountMaximum number of executions. If set to Scheduler.UNLIMITED, there is no constraint.
boolean isDaemon

Used only if the Schedule is registered remotely. If set to true, the task terminates when connection to a client is lost.

A client decides whether a connection is lost according to the DGC (Distributed Garbage Collection) policy of RMI Runtime. Schedule is cancelled after 15 minutes from the time the client is disconnected.

boolean isThreadedDeprecated.

The following example shows how to register tasks.


When a task is registered in JEUS Scheduler, the ScheduleController handler object is returned. This object is created for each registered task and is used to control the task. The handler can be used to get information about the task and to cancel the task.

The following example shows how to cancel tasks by calling the ScheduleController.cancel() method.


JEUS Scheduler can only be used after the tasks have been defined, obtained, registered, and controlled.

This section explains how to use Scheduler in various environments.

JEUS Scheduler can be used by regular J2SE applications or Java EE application clients. In these cases, JEUS Scheduler and J2SE Timer can be used as libraries. The SchedulerFactory class is used to obtain the Scheduler object. A daemon flag can be set to any value because it is not used when tasks are registered in a local environment.

The following is an example of a standalone client:

[Example 2.7] Using Scheduler on a Standalone Client

public class StandAloneClient {
    public static void main(String args[]) {
        try {
            // Get the default scheduler
            Scheduler scheduler = SchedulerFactory.getDefaultScheduler();

            // Register SimpleTask which runs just one time
            echo("Register task1 which runs just one time...");
            SimpleTask task1 = new SimpleTask("task1");
            Date firstTime1 = new Date(System.currentTimeMillis() + 2000);
            ScheduleController handle1 = scheduler.registerSchedule(task1, 
                            firstTime1, false);

            Thread.sleep(5 * 1000);
            echo("");

            // Register SimpleTask which is repeated
            // with fixed-delay
            echo("Register task2 which is repeated " + "until it is canceled...");
            SimpleTask task2 = new SimpleTask("task2");
            ScheduleController handle2 = scheduler.registerSchedule(task2, 2000, 
                          2000, null, Scheduler.UNLIMITED, false);

            Thread.sleep(10 * 1000);
            handle2.cancel();
            echo("");

            // Register SimpleTask which is repeated
            // with fixed-rate
            echo("Register task3 which is repeated " + "for 10 seconds...");
            SimpleTask task3 = new SimpleTask("task3");
            Date firstTime3 = new Date(System.currentTimeMillis() + 2000);
            Date endTime3 = new Date(System.currentTimeMillis() + 10 * 1000);
            ScheduleController handle3 = scheduler.registerScheduleAtFixedRate(
                    task3, firstTime3, 2000, endTime3, 10, false);

            Thread.sleep(12 * 1000);
            echo("");

            // Register SimpleSchedule which is repeated
            // every 2 seconds
            echo("Register task4 which is repeated " + "every 2 seconds...");
            SimpleSchedule task4 = new SimpleSchedule("task4");
            ScheduleController handle4 = scheduler.registerSchedule(task4, false);

            Thread.sleep(10 * 1000);
            echo("");

            // Cancel all tasks
            echo("Cancel all tasks registerd on the scheduler...");
            scheduler.cancel();
            Thread.sleep(5 * 1000);

            System.out.println("Program terminated.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void echo(String s) {
        System.out.println(s);
    }

}


If JEUS Scheduler is used on Java EE application clients, JEUS Scheduler's thread pool configuration can be set in the deployment descriptor (jeus-client-dd.xml).

Note

1.For information about how to set a Scheduler's thread pool, refer to the JEUS Reference Book. "4.2.5. Thread Management Commands".

2. To compile or execute source code that uses Scheduler, JEUS related classes such as jeus.jar must be specified in the class path.

Remote clients can access scheduler services that are running on JEUS server if the scheduler service startup configuration is set on the JEUS server.

The scheduler service on JEUS server registers the RMI Scheduler object with JNDI. Therefore, clients can obtain the remote scheduler objects (stub object) using JNDI Lookup. The name of the object is “jeus_service/Scheduler”, and it uses the Scheduler.SERVER_SCHEDULER_NAME constant.

After obtaining the Scheduler object, same method is used to register tasks. However, the registered task objects are serialized and run from remote Schedulers, which means they run on JEUS servers.

During task registration, if the daemon flag is set to true, the remote tasks terminate when the remote clients terminate.

The following is an example of a remote client:

[Example 2.8] Using Scheduler on a Remote Client

public class RemoteClient {
    public static void main(String args[]) {
        try {
            // Get the remote scheduler
            InitialContext ic = new InitialContext();
            Scheduler scheduler = (Scheduler)ic.lookup(
                Scheduler.SERVER_SCHEDULER_NAME);

            // Register SimpleTask which runs just one time
            echo("Register task1 which runs just one time...");
            SimpleTask task1 = new SimpleTask("task1");
            Date firstTime1 = new Date(System.currentTimeMillis() + 2000);
            ScheduleController handle1 = scheduler.registerSchedule(task1, 
                             firstTime1, true);

            Thread.sleep(5 * 1000);
            echo("");

            // Register SimpleTask which is repeated
            // with fixed-delay
            echo("Register task2 which is repeated " + "until it is canceled...");
            SimpleTask task2 = new SimpleTask("task2");
            ScheduleController handle2 = scheduler.registerSchedule(task2, 
                    2000, 2000, null, Scheduler.UNLIMITED, true);

            Thread.sleep(10 * 1000);
            handle2.cancel();
            echo("");

            // Register SimpleRemoteSchedule which is repeated
            // every 3 seconds
            echo("Register task3 which is repeated " + "every 3 seconds...");
            Hashtable params = new Hashtable();
            params.put("name", "task3");
            params.put("interval", new Long(3000));
            ScheduleController handle3 = scheduler.registerSchedule(
                    "samples.scheduler.SimpleRemoteSchedule", params, true);

            Thread.sleep(10 * 1000);
            echo("");

            // Cancel all tasks
            echo("Cancel all tasks registerd on the scheduler...");
            scheduler.cancel();
            Thread.sleep(5 * 1000);

            System.out.println("Program terminated.");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private static void echo(String s) {
        System.out.println(s);
    }
}

Caution

To execute the previous example, compress relevant task class files into a jar file and save them in the 'DOMAIN_HOME/lib/application' or 'SERVER_HOME/lib/application' directory. The JEUS server loads the class files to execute the task, and JEUS must be restarted if it is running.

JEUS Scheduler can be used in Java EE components such as EJB and Servlet. In this case, JEUS Scheduler runs on JEUS server.

JEUS 5.0 provides the EJB Timer Service that is specified in the EJB 2.1 standard. Therefore, it is recommended to use the EJB Timer Service for EJB components instead of JEUS Scheduler to comply with the Java EE standard. However, JEUS Scheduler should be used for other JAVA EE components besides EJB components since EJB Timer Service cannot be used.

Using JEUS Scheduler in Java EE components is same as using a Standalone JEUS Scheduler. First the SchedulerFactory class is used to obtain a Scheduler object running on the server, and then the necessary method is called to register the task.

The following example shows how to use JEUS Scheduler in EJB.


Job-list registers tasks on JEUS server using the configuration file instead of the programming method. It can be registered on JEUS server Scheduler. If tasks are registered through Job-list, the tasks are executed at fixed-rate.