A JOB is an action which is guaranteed to be performed at least once and its state is persisted under node /var/eventing/jobs.
A Job's at least once execution can't be guaranteed if the AEM instance that is processing the job itself crashes after processing the job but before persisting its state. That's quite rare🤔.
When would you use job to perform a task?
Following are few use cases where Job can be used:
Store Reports
Workflow Automation
Email Notification
How do we trigger a job?
A Job is triggered using a JobConsumer OSGI Service which is registered to one or more topics.
Every Job has two parameters passed to it:
TOPIC: A property that uniquely identifies a JobConsumer
PAYLOAD: A key value map of serializable objects. You can consider these as inputs which we pass to a JobConsumer.
Let's write a simple JobConsumer:
Below JobConsumer is registered to TOPIC "sample/job".
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.consumer.JobConsumer;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(service = JobConsumer.class, immediate = true, property = { Constants.SERVICE_DESCRIPTION + "= Sample Job", JobConsumer.PROPERTY_TOPICS + "=sample/job" })
public class SampleJob implements JobConsumer {
private final Logger logger =LoggerFactory.getLogger(getClass());
@Override
public JobResult process(Job job) {
try {
logger.info("Sample JOB Process Started");
return JobConsumer.JobResult.OK;
} catch (Exception e) {
logger.error("Exception ", e);
return JobResult.FAILED;
}
}
}
Job States:
return JobResult.OK on successful execution,
return JobResult.FAILED if there was some issue in execution but you need to queue a job for retry,
return JobResult.CANCEL if you wish to cancel the job.
Now, let's trigger this job using a simple servlet:
A Job is initiated by calling the JobManager.addJob(<job topic>,<payload>) method.
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.event.jobs.JobManager;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@Component(service = Servlet.class, property = { "sling.servlet.methods=" + HttpConstants.METHOD_GET, "sling.servlet.paths=" + "/bin/jobTrigger" })
public class JobTriggerServlet extends SlingSafeMethodsServlet {
private static final long serialVersionUID = 1L;
@Reference
private JobManager jobManager;
@Override
protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp) throws ServletException, IOException {
final Map<String, Object> payload = new HashMap<>();
payload.put("nodePath", "/etc/jobTest");
jobManager.addJob("sample/job", payload);
resp.getWriter().write("Job Triggered");
}
}
Let's have a look at nodes under /var/eventing/jobs:
A node is created under var/eventing/jobs/assigned when the job is scheduled or is being processed. Notice that the nodePath property we passed in payload is also persisted. When job processing completes/fails this node is deleted.
If the Job fails and is eventually cancelled after the retries, the history is stored under /var/eventing/jobs/cancelled(default maximum retires is 10).
Once the processing is successful, the job history is deleted by default. So what to do when we need to persist history of the Successful Jobs?
There is a configuration Apache Sling Job Queue Configuration which enables custom configuration of one or more JOB Topics.
On save of above configuration, as the Keep History option is enabled, you will start seeing the Job History under /var/eventing/jobs/finished.
That's all for today! If you've found this blog post informative or helpful, I’d greatly appreciate it if you could give it a like. It keeps me motivated 💛
Enjoying my ad-free blog? Support by buying me a coffee! I've kept this space ad-free, sponsoring it myself to maintain its purity. Your contribution would help keep the site afloat and ensure quality content. Thanks for being part of this ad-free community.
Comments