In AEM, we can create scheduler in two ways -
- Whiteboard Pattern - In this, we create a Runnable thread to perform our task. This is similar to the Java Thread concept.
- Scheduler API - In this, we use Apache Commons' Scheduler API to perform our task. It uses an open-source Quartz library.
Scheduler in AEM
To create a scheduler in AEM, we will follow the below steps -
- Create an OSGi configuration to read the scheduler specific values from the user i.e. cron expression, the name of the scheduler, custom parameter etc.
- Create a sling scheduler which displays the custom parameter at an interval specified by the cron expression.
Without making a further delay, let's dive into our code
Create an OSGi configuration
package org.redquark.demo.core.services;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.AttributeType;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
/**
* @author Anirudh Sharma
*
* This is the configuration class that takes properties for a scheduler to run
*/
@ObjectClassDefinition(name = "SlingSchedulerConfiguration", description = "Sling scheduler configuration")
public @interface SlingSchedulerConfiguration {
/**
* This method will return the name of the Scheduler
*
* @return {@link String}
*/
@AttributeDefinition(
name = "Scheduler name",
description = "Name of the scheduler",
type = AttributeType.STRING)
public String schdulerName() default "Custom Sling Scheduler Configuration";
/**
* This method will check if the scheduler is concurrent or not
*
* @return {@link Boolean}
*/
@AttributeDefinition(
name = "Enabled",
description = "True, if scheduler service is enabled",
type = AttributeType.BOOLEAN)
public boolean enabled() default false;
/**
* This method returns the Cron expression which will decide how the scheduler will run
*
* @return {@link String}
*/
@AttributeDefinition(
name = "Cron Expression",
description = "Cron expression used by the scheduler",
type = AttributeType.STRING)
public String cronExpression() default "0 * * * * ?";
/**
* This method returns a custom parameter just to show case the functionality
*
* @return {@link String}
*/
@AttributeDefinition(
name = "Custom Parameter",
description = "Custom parameter to be displayed by the scheduler",
type = AttributeType.STRING)
public String customParameter() default "AEM Scheduler Demo";
}
Here we are getting configuration properties for the Sling Scheduler.
Create Scheduler
Now we are going to create a sling scheduler. Create a class named CustomScheduler and paste the following code in it.
package org.redquark.demo.core.schedulers;
import org.apache.sling.commons.scheduler.ScheduleOptions;
import org.apache.sling.commons.scheduler.Scheduler;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.metatype.annotations.Designate;
import org.redquark.demo.core.services.SlingSchedulerConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Anirudh Sharma
*
* A Sling Scheduler demo using OSGi R6 annotations
*
*/
@Component(immediate = true, service = CustomScheduler.class)
@Designate(ocd = SlingSchedulerConfiguration.class)
public class CustomScheduler implements Runnable {
/**
* Logger
*/
private static final Logger log = LoggerFactory.getLogger(CustomScheduler.class);
/**
* Custom parameter that is to be read from the configuration
*/
private String customParameter;
/**
* Id of the scheduler based on its name
*/
private int schedulerId;
/**
* Scheduler instance injected
*/
@Reference
private Scheduler scheduler;
/**
* Activate method to initialize stuff
*
* @param config
*/
@Activate
protected void activate(SlingSchedulerConfiguration config) {
/**
* Getting the scheduler id
*/
schedulerId = config.schdulerName().hashCode();
/**
* Getting the custom parameter
*/
customParameter = config.customParameter();
}
/**
* Modifies the scheduler id on modification
*
* @param config
*/
@Modified
protected void modified(SlingSchedulerConfiguration config) {
/**
* Removing the scheduler
*/
removeScheduler();
/**
* Updating the scheduler id
*/
schedulerId = config.schdulerName().hashCode();
/**
* Again adding the scheduler
*/
addScheduler(config);
}
/**
* This method deactivates the scheduler and removes it
* @param config
*/
@Deactivate
protected void deactivate(SlingSchedulerConfiguration config) {
/**
* Removing the scheduler
*/
removeScheduler();
}
/**
* This method removes the scheduler
*/
private void removeScheduler() {
log.info("Removing scheduler: {}", schedulerId);
/**
* Unscheduling/removing the scheduler
*/
scheduler.unschedule(String.valueOf(schedulerId));
}
/**
* This method adds the scheduler
*
* @param config
*/
private void addScheduler(SlingSchedulerConfiguration config) {
/**
* Check if the scheduler is enabled
*/
if (config.enabled()) {
/**
* Scheduler option takes the cron expression as a parameter and run accordingly
*/
ScheduleOptions scheduleOptions = scheduler.EXPR(config.cronExpression());
/**
* Adding some parameters
*/
scheduleOptions.name(config.schdulerName());
scheduleOptions.canRunConcurrently(false);
/**
* Scheduling the job
*/
scheduler.schedule(this, scheduleOptions);
log.info("Scheduler added");
} else {
log.info("Scheduler is disabled");
}
}
/**
* Overridden run method to execute Job
*/
@Override
public void run() {
log.info("Custom Scheduler is now running using the passed custom paratmeter, customParameter {}", customParameter);
}
}
- Let us understand the code step-by-step. First, we are registering the class as a service and implementing the Runnable interface. At the same time, using @Desginate annotation, we are linking the OSGi configuration created in the previous section with this class.
- Now, we are injecting the org.apache.sling.commons.scheduler.Scheduler dependency.
- In the activate() method, we are reading the required values. Then we are getting the schedulerId from the scheduler name.
- The modified() method recalculates the schedulerId in case the OSGi configuration is modified.
- In the addScheduler() method, we are registering the scheduler using the Scheduler API.
- The run() method will be defining our task. Here we are just printing the customParameter in the logs.
Configuring OSGi
- Go to ./system/console/configMgr and search for SlingSchedulerConfiguration and configure it like the below screenshot.
OSGi Configuration
- Save the configuration.
Result
Now go to your project-specific log (my log file is - project-demoproject.log) and look for the traces, you will find like below
No comments:
Post a Comment
If you have any doubts or questions, please let us know.