Wiki source code of Create Scheduler jobs in Java
Last modified by Lavinia Vitel on 2020/08/24
Show last authors
author | version | line-number | content |
---|---|---|---|
1 | XWiki provides a [[Scheduler Application>>extensions:Extension.Scheduler Application]] that offers the possiblity of creating jobs and perform actions on these jobs (Schedule, Trigger, Cancel ...). | ||
2 | |||
3 | Jobs created by the scheduler application executes a Groovy script periodicaly following a predifined period that is using a Cron expression. | ||
4 | |||
5 | A Scheduler Job is an **XWiki.SchedulerJobClass** object attached to a wiki page. | ||
6 | |||
7 | The script to excute is set in the Job Script property of the **XWiki.SchedulerJobClass** object, it is a groovy script. | ||
8 | |||
9 | In this post we will provide a solution to use Java code instead of Groovy in the Job Script. | ||
10 | |||
11 | == Use Java in the job script == | ||
12 | |||
13 | To use java in the Job script you will need 2 steps: | ||
14 | 1) Create a java class that extends **com.xpn.xwiki.plugin.scheduler.AbstractJob** class and implements the **org.quartz.Job** interface. | ||
15 | 2) Set the Job **class** property with the full java class name and let the Job script property empty. | ||
16 | |||
17 | === Create the java class === | ||
18 | |||
19 | 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. | ||
20 | |||
21 | In the java class we will need to override the **executeJob** method that will be called periodically from the scheduler. | ||
22 | |||
23 | 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>>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]] | ||
24 | |||
25 | ==== Methods that need to be defined in the class ==== | ||
26 | |||
27 | **init** method: Sets objects required by the Job : XWiki, XWikiContext, Components ... etc. | ||
28 | |||
29 | {{code}} | ||
30 | ... | ||
31 | public void init(JobExecutionContext jobContext) throws Exception | ||
32 | { | ||
33 | JobDataMap data = jobContext.getJobDetail().getJobDataMap(); | ||
34 | |||
35 | this.watchlist = Utils.getComponent(WatchList.class); | ||
36 | this.schedulerJobObject = (BaseObject) data.get("xjob"); | ||
37 | this.watchListJobObject = | ||
38 | getXWikiContext().getWiki().getDocument(this.schedulerJobObject.getDocumentReference(), getXWikiContext()) | ||
39 | .getXObject(WatchListJobClassDocumentInitializer.DOCUMENT_REFERENCE); | ||
40 | } | ||
41 | ... | ||
42 | {{/code}} | ||
43 | |||
44 | **executeJob** method: Method called from the scheduler. | ||
45 | |||
46 | {{code}} | ||
47 | ... | ||
48 | @Override | ||
49 | public void executeJob(JobExecutionContext jobContext) throws JobExecutionException | ||
50 | { | ||
51 | try { | ||
52 | init(jobContext); | ||
53 | |||
54 | if (this.watchListJobObject == null) { | ||
55 | return; | ||
56 | } | ||
57 | |||
58 | Collection<String> subscribers = getSubscribers(); | ||
59 | |||
60 | // Stop here if nobody is interested. | ||
61 | if (!hasSubscribers()) { | ||
62 | return; | ||
63 | } | ||
64 | |||
65 | // Determine what happened since the last execution for everybody. | ||
66 | Date previousFireTime = getPreviousFireTime(); | ||
67 | WatchListEventMatcher eventMatcher = Utils.getComponent(WatchListEventMatcher.class); | ||
68 | List<WatchListEvent> events = eventMatcher.getEventsSince(previousFireTime); | ||
69 | setPreviousFireTime(); | ||
70 | |||
71 | // Stop here if nothing happened in the meantime. | ||
72 | if (events.size() == 0) { | ||
73 | return; | ||
74 | } | ||
75 | |||
76 | // Notify all the interested subscribers of the events that occurred. | ||
77 | // When processing the events, a subscriber will only be notified of events that interest him. | ||
78 | Map<String, Object> notificationData = new HashMap<>(); | ||
79 | notificationData.put(DefaultWatchListNotifier.PREVIOUS_FIRE_TIME_VARIABLE, previousFireTime); | ||
80 | |||
81 | String mailTemplate = | ||
82 | this.watchListJobObject.getStringValue(WatchListJobClassDocumentInitializer.TEMPLATE_FIELD); | ||
83 | notificationData.put(WatchListEventMimeMessageFactory.TEMPLATE_PARAMETER, mailTemplate); | ||
84 | |||
85 | // Send the notification for processing. | ||
86 | this.watchlist.getNotifier().sendNotification(subscribers, events, notificationData); | ||
87 | } catch (Exception e) { | ||
88 | // We're in a job, we don't throw exceptions | ||
89 | LOGGER.error("Exception while running job", e); | ||
90 | } | ||
91 | } | ||
92 | ... | ||
93 | {{/code}} | ||
94 | |||
95 | 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 | ||
96 | |||
97 | === Set the Job class property with the java full class name === | ||
98 | |||
99 | 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. | ||
100 | |||
101 | {{image reference="edit-job.png"/}} | ||
102 | //Scheduler job object// | ||
103 | |||
104 | == Conclusion == | ||
105 | |||
106 | This approach will allow you to take advantage of all power that Java provides in scheduler jobs. |