Additional Blogs by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 
former_member203429
Discoverer

“Quartz is a full-featured, open source job scheduling service”. Its powerful functionality could be easily integrated into SAP NetWeaver Cloud environment. In this article we demonstrate how with few simple steps we build a cloud application that repeatedly writes a log message at a certain time interval. Detailed information of using Quartz could be found in its official documentation.

Configuration:

Start by creating a standard dynamic web project targeted on SAP NetWeaver Cloud runtime. For more details refer to the SAP NetWeaver Cloud documentation. Download the Quartz quartz-xxx.jar (where xxx is the version number) from your Nexus repository or directly from the Quartz site and place it in the WEB-INF/lib folder of your application.

NOTE: This example is based on version 1.8.6.


The framework uses configuration file named quartz.properties. Basic example:

org.quartz.scheduler.instanceName = SampleSchedulerName
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

Important parameters are org.quartz.threadPool.threadCount which is the number of jobs which can run simultaneously and org.quartz.jobsStore.class that defines where all the job execution data should be stored. For more information about the properties file refer to the official documentation.

In order to execute a job we should create a scheduler and obtain reference to it. The first option is to instantiate a scheduler directly in the application code:

Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

The issue with this approach is that you should fully handle the scheduler lifecycle. The more convenient option is to use org.quartz.ee.servlet.QuartzInitializerListener.This is an implementation of ServletContextListener which takes care to instantiate a scheduler, start it (if the specific configuration parameter is set to true) and put it in the servlet context so that we could access it in our web application. Respectively, when the application is stopped this listener will shutdown the scheduler as well. Add the following fragment to your web.xml:

...
<context-param>
    <param-name>quartz:config-file</param-name>
    <param-value>quartz.properties</param-value>
  </context-param>
  <context-param>
    <param-name>quartz:shutdown-on-unload</param-name>
    <param-value>true</param-value>
  </context-param>
  <context-param>
    <param-name>quartz:wait-on-shutdown</param-name>
    <param-value>false</param-value>
  </context-param>
  <context-param>
    <param-name>quartz:start-scheduler-on-load</param-name>
    <param-value>true</param-value>
  </context-param>
  <listener>
    <listener-class>org.quartz.ee.servlet.QuartzInitializerListener</listener-class>
  </listener>
...

NOTE: Make sure that the quartz.properties file path is correct and is configured in the application’s classpath. In our case it is in a source folder called resource under the application’s root.

We can retrieve the scheduler instance from the servlet context like this:

...
SchedulerFactory schedulerFactory = (SchedulerFactory) servletContext.getAttribute(QuartzInitializerListener.QUARTZ_FACTORY_KEY);
this.scheduler = schedulerFactory.getScheduler();
...

Job definition:

Now we can define the job. It should simply implement the org.quartz.Job interface. Program the business logic of the job in the execute method – in our example this will be writing a message into the server log. Note the JobExecutionContext  parameter – it could be used to pass parameters to and from the job, propagate state, etc. Below is the sample:

package com.startup;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SimpleQuartzJob implements Job {
          private final static Logger logger = LoggerFactory.getLogger(SimpleQuartzJob.class);
          public SimpleQuartzJob() {
          }
         public void execute(JobExecutionContext context) throws JobExecutionException {
                    logger.error("Hello Quartz");
          }
}

Job execution:

Create a job trigger and job detail. Trigger is the component which starts the job execution and JobDetail contains various properties and settings for the job. We will create a SimpleTrigger which executes a job every 10 seconds and repeats it 10 times (refer to documentation for full options list). At the end schedule the job. Here is the code:

...
JobDetail jobDetail = new JobDetail("jobId", "jobGroup", SimpleQuartzJob.class);
SimpleTrigger simpleTrigger = new SimpleTrigger("triggerId", "triggerGroup");
simpleTrigger.setStartTime(new Date());
simpleTrigger.setRepeatCount(10);
simpleTrigger.setRepeatInterval(10000);
this.scheduler.scheduleJob(jobDetail, simpleTrigger);
...

Finally, assemble all of the above source code examples into the web project and deploy it on the local server or in the cloud.

In our example we register a ServletContextListener and hook all our code to the application start.

public class MyListener implements ServletContextListener {
private final static Logger logger = LoggerFactory.getLogger(MyListener.class);
private Scheduler scheduler;
public void contextDestroyed(ServletContextEvent arg0)  {
     logger.info("Application Stopped.");
}
public void contextInitialized(ServletContextEvent sce) {
     logger.info("Application Started.");
     try {
          SchedulerFactory schedulerFactory = (SchedulerFactory) sce.getServletContext().getAttribute(QuartzInitializerListener.QUARTZ_FACTORY_KEY);
          scheduler = schedulerFactory.getScheduler();
          JobDetail jobDetail = new JobDetail("jobId", "jobGroup", SimpleQuartzJob.class);
          SimpleTrigger simpleTrigger = new SimpleTrigger("triggerId", "triggerGroup");
          simpleTrigger.setStartTime(new Date());
          simpleTrigger.setRepeatCount(10);
          simpleTrigger.setRepeatInterval(10000);
          scheduler.scheduleJob(jobDetail, simpleTrigger);
          } catch (SchedulerException se) {
               logger.error("Scheduler error occurred", se);
          } catch (Exception e) {
               logger.error("Application error", e);
          }
     }
}

After the application successful start we can see the log entries appear in the ljs_trace.log file.


NOTE: MyListener should be added after the QuartzInitializerListener in the web.xml because they are dependent.

...
<listener>
    <listener-class>org.quartz.ee.servlet.QuartzInitializerListener</listener-class>
  </listener>
  <listener>
      <listener-class>com.startup.MyListener</listener-class>
  </listener>
...

In this example we demonstrated how just with few simple steps we can define and execute a job with the Quartz library. It's a basic example not intended to cover all of the framework's rich functionality but descriptive enough to show it's advantages, flexibility and simple usage. For more complex use cases you can explore the official documentation and take advantage of the full feature list available explained in numerous examples.

5 Comments