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 experession to be used to excute 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())

executeJob method: Method called from the scheduler.

    public void executeJob(JobExecutionContext jobContext) throws JobExecutionException
        try {

            if (this.watchListJobObject == null) {

            Collection<String> subscribers = getSubscribers();

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

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

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

            // 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 =
            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.

Scheduler job object


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

Created by Mohamed Boussaa on 2016/06/21

Get Connected