Creating a Quartz RMI Server

You must follow a few steps to configure Quartz to use RMI. Some of these steps must be done on the Quartz RMI server, and a few are done on the Quartz client that connects to the server. We go through the server configuration steps first.

Configuring the Quartz RMI Server

The first step is to modify the quartz.properties file that will be deployed with the Quartz RMI server. When using RMI within Quartz, you must add several new properties. Table 9.1 includes the complete list of RMI properties.

Table 9.1. The Properties That Are Necessary for the RMI Server

Property

Default

org.quartz.scheduler.rmi.export

Notes: This flag must be set to true if you want the Quartz Scheduler to be available as a RMI object.

false

org.quartz.scheduler.rmi.registryHost

Notes: This is the host at which the RMI Registry is running.

localhost

org.quartz.scheduler.rmi.registryPort

Notes: This is the port on which the RMI Registry is listening (usually 1099).

1099

org.quartz.scheduler.rmi.createRegistry

Notes: This determines whether Quartz creates the RMI Registry. Use false or never if you don't want Quartz to create a Registry. Use TRue or as_needed if you want Quartz to first attempt to use an existing Registry and then fall back to creating one. Use always if you want Quartz to create a Registry and then fall back to using an existing one. If a Registry is created, it will be bound to a port number in the given registryPort and registryHost.

never

org.quartz.scheduler.rmi.serverPort

Notes: This is the port on which the Quartz Scheduler service will bind and listen for connections. By default, the RMI service randomly selects a port as the Scheduler is bound to the RMI Registry.

-1

All the properties in Table 9.1 need to be added to the quartz.properties file for the Quartz RMI server. Although there are defaults for these properties, it's best to specify the values explicitly to prevent any confusion. Listing 9.1 shows an example properties file that is used with the Quartz RMI server.

Listing 9.1. An Example quartz.properties file for Use with the Quartz RMI Server

#============================================================== # Configure Main Scheduler Properties #============================================================== org.quartz.scheduler.instanceName = RMIScheduler #============================================================== # Configure RMI Properties #============================================================== org.quartz.scheduler.rmi.export = true org.quartz.scheduler.rmi.registryHost = localhost org.quartz.scheduler.rmi.registryPort = 1099 org.quartz.scheduler.rmi.serverPort = 0 org.quartz.scheduler.rmi.createRegistry = true #============================================================== # Configure ThreadPool #============================================================== org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount = 10 org.quartz.threadPool.threadPriority = 5 #============================================================== # Configure JobStore #============================================================== org.quartz.jobStore.misfireThreshold = 60000 org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

You'll recognize most of the settings in Listing 9.1 from the various quartz.properties files that you've seen in previous chapters. The only new properties are the ones added from Table 9.1.

Creating a Quartz RMI Server Startup Class

To run the Quartz RMI server, you need to create a startup class that obtains a Scheduler from the factory and starts running the Scheduler. This is true of Quartz with or without RMI. Because we are using RMI in this example, however, a few new steps must be carried out.

First, to make things less confusing, we rename our quartz.properties file server.properties and tell the Quartz RMI server to load that file instead of the default quartz.properties file. Changing the name makes things easier when trying to debug problems. This way, we can be sure that Quartz is loading the correct settings file.

The second change is that we load a new SecurityManager so that all the necessary permissions will be granted to the RMI server. We discussed the RMISecurityManager earlier in the chapter.

Other than these changes, the startup class shown in Listing 9.2 should look familiar.

Listing 9.2. The QuartzRMIServer Can Be Used to Start the Quartz RMI Server

package org.cavaness.quartzbook.chapter9; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Date; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.Scheduler; import org.quartz.SchedulerFactory; import org.quartz.impl.StdSchedulerFactory; public class QuartzRMIServer { public void run() throws Exception { Log log = LogFactory.getLog(QuartzRMIServer.class); // Use this properties file instead of quartz.properties System.setProperty("org.quartz.properties", "server.properties"); // RMI with Quartz requires a special security manager if (System.getSecurityManager() == null) { System.setSecurityManager(new java.rmi.RMISecurityManager()); } // Get a reference to the Scheduler Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); /* * Due to the server.properties file, our Scheduler will * be exported to RMI Registry automatically. */ scheduler.start(); log.info("Quartz RMI Server started at " + new Date()); log.info("RMI Clients may now access it. "); System.out.println(" "); System.out.println( "The scheduler will run until you type "exit""); BufferedReader rdr = new BufferedReader( new InputStreamReader(System.in)); while (true) { System.out.print("Type 'exit' to shutdown server: "); if ("exit".equals(rdr.readLine())) { break; } } log.info("Scheduler is shutting down..."); scheduler.shutdown(true); log.info("Scheduler has been stopped."); } public static void main(String[] args) throws Exception { QuartzRMIServer example = new QuartzRMIServer(); example.run(); } }

In Listing 9.2, after the RMISecurityManager has been set, a Scheduler is retrieved from the factory and the start() method is called. The server is designed to be run from the console so after the Scheduler is started, it runs until the user types exit from the console. The Scheduler then is shut down and stops serving remote clients.

Other than using the RMISecurityManager, notice that we didn't have to do anything special in the code with the Quartz Scheduler to use it as a remote Scheduler. That was all taken care of in the server.properties file. When the Scheduler is created, if the properties file tells it to, the Scheduler exports itself to the RMI Registry and makes it available to be called remotely.

Категории