How do I change the schedule of a built-in Jahia job, and can I stop one that is running?
Question
How do I change the schedule of a built-in Jahia job, and can I stop one that is running?
Answer
Changing the cron of a built-in job
There is no jahia.properties key for it. Built-in job schedules are defined
in Spring XML, and the cron expression is a literal, not a ${...} placeholder.
Taking DataStoreGarbageCollectorJob as the example, in
applicationcontext-scheduler-jobs.xml:
<bean id="DataStoreGarbageCollectorJob" parent="jobSchedulingBean" lazy-init="true">
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="name" value="DataStoreGarbageCollectorJob"/>
<property name="group" value="Maintenance"/>
...
<property name="trigger">
<bean class="org.quartz.CronTrigger">
<property name="name" value="DatastoreGarbageCollectorTrigger"/>
<property name="cronExpression" value="0 0 0 1 * ?"/>
So the default is the 1st of each month at midnight.
To change it, drop a Spring override file into
<JAHIA_HOME>/digital-factory-config/jahia/, matching applicationcontext-override-*.xml,
redefining the bean with the same id and your cron.
Keeping the id matters. Jahia instantiates this bean by name at startup
(applicationContext.getBean(dataStoreGarbageCollectorBeanId)), so renaming it
means the job is simply never scheduled - silently.
Yes, the change applies on restart - even in production mode
A common assumption is that overwriteExisting defaults to false outside
development mode and therefore your edit is ignored. It is not. When the job is
already stored, Jahia calls syncJobTriggers(), which compares the cron
expressions and reschedules when they differ:
if (!newCron.equals(existingCron)) {
...
updateTrigger(newTrigger);
}
Keep the trigger name identical too. Triggers are matched by full name, so renaming the trigger unschedules the old one and creates a new one instead of rescheduling - which works, but discards the trigger's existing state.
Watch the spelling: the job is DataStoreGarbageCollectorJob (capital S) and
the trigger is DatastoreGarbageCollectorTrigger (lowercase s). They differ.
Turning a job off instead
The parent bean accepts <property name="disabled" value="true"/>.
Reaching the scheduler from code
SchedulerService schedulerService = ServicesRegistry.getInstance().getSchedulerService();
org.quartz.Scheduler persistent = schedulerService.getScheduler(); // JDBC-backed
org.quartz.Scheduler ram = schedulerService.getRAMScheduler(); // in-memory
There really are two schedulers. Persistent jobs survive a restart and run only on a processing server; RAM jobs do not survive and run anywhere.
getScheduler() does not hand you the raw Quartz object - verified on a running
8.2.3.2, it returns a ReadOnlyModeAwareScheduler wrapper that refuses mutating
calls while the platform is in read-only mode. getRAMScheduler() returns the
unwrapped StdScheduler.
Reading the live triggers on a stock 8.2.3.2 gives, for example:
| Scheduler | Trigger | Cron | Job |
|---|---|---|---|
| persistent | DEFAULT/DatastoreGarbageCollectorTrigger | 0 0 0 1 * ? | Maintenance/DataStoreGarbageCollectorJob |
| persistent | DEFAULT/ContentHistoryPurgeTrigger | 0 0 0 L DEC ? * | Maintenance/ContentHistoryPurgeJob |
| persistent | DEFAULT/JobHistoryPurgeTrigger | 0 0 * * * ? | Maintenance/JobHistoryPurgeJob |
| ram | DEFAULT/EvictExpiredHTMLCacheKeyTrigger | 0 0/15 * * * ? | Maintenance/EvictExpiredHTMLCacheKeyJob |
Note the trigger group is DEFAULT while the job group is Maintenance -
another easy mistake when calling the Quartz API, which takes the trigger's group
for trigger operations.
Can I force-stop a running job? No
Jahia's BackgroundJob implements org.quartz.StatefulJob, not
org.quartz.InterruptableJob. Checked live on 8.2.3.2:
InterruptableJob.class.isAssignableFrom(BackgroundJob.class) -> false
InterruptableJob appears nowhere in Jahia core, and nowhere in Jahia's public
GitHub organisation. Scheduler.interrupt(...) exists on the API but cannot
interrupt a job class that does not implement that interface.
What you can do affects future runs only:
| Goal | Call |
|---|---|
| Stop it running again | unscheduleJob(triggerName, triggerGroup) |
| Remove the job entirely | deleteJob(jobName, jobGroup) |
| Suspend / resume | pauseJob(...) / resumeJob(...) |
| Run it right now | triggerJobWithVolatileTrigger(...) |
None of these stop a thread already inside the job. The only way to stop an in-flight background job is to restart the node - and even then Jahia is configured to wait for running jobs to finish on shutdown.
For the DataStore GC specifically, the work happens inside Jackrabbit's mark/sweep, which Jahia could not interrupt even if the job class allowed it.
The jobs admin page
The job list lives in the Tools module, not in the Administration UI:
<host>/tools/jobadmin.jsp, with ?schedulerType=ram for the RAM scheduler. It
shows each job's trigger and cron and offers trigger-now, pause, resume,
unschedule and delete - but no edit-cron and no kill, consistent with the
above.
This article was drafted with AI assistance, then reviewed and curated by Jahia Customer Support engineers before publication.