CronJob Generator

Describe a scheduled job once -- get the AbstractJobPerformable class, its Spring bean, an optional custom CronJob type, and the ImpEx to schedule it.

🔒 Your code never leaves your browser — everything is generated locally from templates, no AI, no server round-trip.

  • Job name is required.
Becomes CleanupJob.java -- no need to type "Job" at the end.

Schedule

🕐 Runs once a day at 02:00.

Custom CronJob type

trainingcore/src/com/prospect2p/core/cronjob/MyJobJob.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.prospect2p.core.cronjob;

import de.hybris.platform.cronjob.enums.CronJobResult;
import de.hybris.platform.cronjob.enums.CronJobStatus;
import de.hybris.platform.cronjob.model.CronJobModel;
import de.hybris.platform.servicelayer.cronjob.AbstractJobPerformable;
import de.hybris.platform.servicelayer.cronjob.PerformResult;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class MyJobJob extends AbstractJobPerformable<CronJobModel> {

    private static final Logger LOG = LogManager.getLogger(MyJobJob.class);

    @Override
    public PerformResult perform(final CronJobModel cronJob) {
        LOG.info("Starting MyJobJob");

        // TODO: replace with the job's real work. Check isAbortRequested(cronJob)
        // periodically inside any loop so a manual abort from Backoffice/HAC
        // actually stops the job instead of running to completion.
        if (isAbortRequested(cronJob)) {
            return new PerformResult(CronJobResult.UNKNOWN, CronJobStatus.ABORTED);
        }

        LOG.info("Finished MyJobJob");
        return new PerformResult(CronJobResult.SUCCESS, CronJobStatus.FINISHED);
    }

    @Override
    public boolean isAbortable() {
        return true;
    }
}
Generated scaffold. Review and test before using in production.
Advertisement

What is a CronJob in SAP Commerce?

A CronJob in SAP Commerce (Hybris) is a scheduled background task: a Java class that runs on a recurring schedule, defined by a CronJob item plus a Trigger that holds the actual cron expression. Platform examples include catalog synchronization, order cleanup, and search indexing.

The Java side is a class extending AbstractJobPerformable<T>, registered as a Spring bean, and wired to the CronJob item via a ServicelayerJob whose springId points at that bean.

When to use it

Use a CronJob for anything that needs to run on its own schedule without a user triggering it directly -- nightly cleanup, periodic data sync, scheduled report generation, expiring stale records, and similar recurring background work.

If the custom CronJob type is enabled below, the job gets its own configurable attributes (e.g. a batch size) stored on the CronJob item itself and editable per-run in Backoffice/HAC, instead of being hardcoded in the Java class.

Files generated

  • The job class (<JobName>Job.java) extending AbstractJobPerformable, with perform() and abort handling.
  • A Spring bean registering the class with parent="abstractJobPerformable".
  • An items.xml snippet for the custom CronJob type, if enabled.
  • An ImpEx script creating the ServicelayerJob, CronJob, and Trigger rows.

Step-by-step: how to use the output

  1. Copy the Java class into <extension>/src/<package>/cronjob/ and the Spring XML bean into your extension's -spring.xml (or merge the <bean> into an existing one).
  2. If a custom CronJob type was generated, copy the items.xml snippet into your extension's -items.xml and run an update (ant updatesystem equivalent, or the Update step in Platform/System Initialization).
  3. Import the generated ImpEx via HAC > Console > ImpEx Import, or call importImpexFile(...) from a SystemSetup for it to run automatically on system update (see the SystemSetup Generator).
  4. Trigger the job once from Backoffice (right-click the CronJob > Execute) to confirm it runs cleanly before waiting on the schedule.

Common mistakes

  • Forgetting the Trigger entirely -- a CronJob with no Trigger never runs on its own; it can still be executed manually but won't be scheduled.
  • Not checking isAbortRequested(cronJob) inside a long-running loop -- isAbortable() alone doesn't make an abort actually stop the work in progress.
  • Reusing a ServicelayerJob springId that's already taken by another job -- each springId must be unique across the system.
  • Setting the cron expression's day-of-month and day-of-week fields both to a specific value -- Quartz-style cron requires one of them to be "?".

Frequently asked questions

What's the difference between a CronJob and a Trigger?

The CronJob item defines what to run (via its job reference) and holds run state/results; the Trigger holds the schedule (cronExpression) and is what actually causes it to fire. One CronJob can have multiple Triggers.

Do I need a custom CronJob type?

No -- most jobs work fine on the plain CronJob type. Add a custom type only when the job needs its own configurable parameters (like a batch size) that should be editable per CronJob instance without touching code.

How do I test the job without waiting for the schedule?

In Backoffice, open the CronJob and use Actions > Execute, or in HAC's Console > Flexible Search find the CronJob and trigger it. Both run it immediately regardless of the Trigger's schedule.

What does isAbortable() actually control?

It controls whether an "Abort" action is offered in Backoffice/HAC for a running instance of this job. Returning true doesn't stop the job by itself -- the perform() method still has to check isAbortRequested(cronJob) and return early.

Can one job class run on multiple schedules?

Yes -- create multiple CronJob + Trigger pairs that both reference the same ServicelayerJob springId, each with its own schedule.

🗳️ Vote for the next SAP Commerce guide

Vote or suggest a topic
What should we write next? Vote