Create Scheduler jobs in Java

Last modified by Oana-Lavinia Florean on 2020/08/24

XWiki provides a Scheduler Application that offers the possiblity of creating jobs and perform actions on these jobs (Schedule, Trigger, Cancel ...).

Jobs created by the scheduler application executes a Groovy script periodicaly following a predifined period that is using a Cron expression.

A Scheduler Job is an XWiki.SchedulerJobClass object attached to a wiki page.

The script to excute is set in the Job Script property of the  XWiki.SchedulerJobClass object, it is a groovy script.

In this post we will provide a solution to use Java code instead of Groovy in the Job Script.

Use Java in the job script

To use java in the Job script you will need 2 steps:
1) Create a java class that extends com.xpn.xwiki.plugin.scheduler.AbstractJob class and implements the org.quartz.Job interface.
2) Set the Job class property with the full java class name and let the Job script property empty.

Create the java class

The class will need a Cron expression to be used to execute the job periodically. The Cron expression will be provided by the Scheduler Job object.

In the java class we will need to override the executeJob method that will be called periodically from the scheduler.

We will take the watchlist scheduler jobs. as an example, the Scheduler job page is Scheduler.WatchListDailyNotifier in your Wiki and the java class is here

Methods that need to be defined in the class

init method: Sets objects required by the Job : XWiki, XWikiContext, Components ... etc.

...
public void init(JobExecutionContext jobContext) throws Exception
   {
        JobDataMap data = jobContext.getJobDetail().getJobDataMap();

        this.watchlist = Utils.getComponent(WatchList.class);
        this.schedulerJobObject = (BaseObject) data.get("xjob");
        this.watchListJobObject =
            getXWikiContext().getWiki().getDocument(this.schedulerJobObject.getDocumentReference(), getXWikiContext())
                .getXObject(WatchListJobClassDocumentInitializer.DOCUMENT_REFERENCE);
   }
...

executeJob method: Method called from the scheduler.

...
 @Override
   public void executeJob(JobExecutionContext jobContext) throws JobExecutionException
    {
       try {
           init(jobContext);

           if (this.watchListJobObject == null) {
               return;
            }

           Collection<String> subscribers = getSubscribers();

           // Stop here if nobody is interested.
           if (!hasSubscribers()) {
               return;
            }

           // Determine what happened since the last execution for everybody.
           Date previousFireTime = getPreviousFireTime();
           WatchListEventMatcher eventMatcher = Utils.getComponent(WatchListEventMatcher.class);
           List<WatchListEvent> events = eventMatcher.getEventsSince(previousFireTime);
           setPreviousFireTime();

           // Stop here if nothing happened in the meantime.
           if (events.size() == 0) {
               return;
            }

           // Notify all the interested subscribers of the events that occurred.
           // When processing the events, a subscriber will only be notified of events that interest him.
           Map<String, Object> notificationData = new HashMap<>();
           notificationData.put(DefaultWatchListNotifier.PREVIOUS_FIRE_TIME_VARIABLE, previousFireTime);

           String mailTemplate =
               this.watchListJobObject.getStringValue(WatchListJobClassDocumentInitializer.TEMPLATE_FIELD);
           notificationData.put(WatchListEventMimeMessageFactory.TEMPLATE_PARAMETER, mailTemplate);

           // Send the notification for processing.
           this.watchlist.getNotifier().sendNotification(subscribers, events, notificationData);
        } catch (Exception e) {
           // We're in a job, we don't throw exceptions
           LOGGER.error("Exception while running job", e);
        }
    }
...

Find a complete example here:  https://github.com/xwiki/xwiki-platform/blob/master/xwiki-platform-core/xwiki-platform-watchlist/xwiki-platform-watchlist-api/src/main/java/org/xwiki/watchlist/internal/job/WatchListJob.java

Set the Job class property with the java full class name

Edit the Scheduler.WatchListDailyNotifier in Object mode and update the Job class property of the XWiki.SchedulerJobClass object with the full java class name and let the Job script property empty.

edit-job.png
Scheduler job object

Conclusion

This approach will allow you to take advantage of all power that Java provides in scheduler jobs.

Tags:
    

Get Connected