Sunday, January 14, 2018

Sling scheduler to auto create the packages through JcrPackageManager API - Adobe Experience Manager(AEM)

Sling scheduler to auto create the packages through JcrPackageManager API - Adobe Experience Manager(AEM)

This post will explains the approach to define Sling scheduler to auto create the packages through JcrPackageManager API in Adobe Experience Manager(AEM).

Define a Service user:

Define a Service User with required access to create a  package.

Login to CRX explorer -  http://localhost:4502/crx/explorer/index.jsp
Click on User Administration


Click on Create System User


Enter the User Id - "packageassembler and the path - "system/packageassembler"



Login to config manager - http://localhost:4502/system/console/configMgr

Search for "Apache Sling Service User Mapper Service"  and add new service mapping


The bundle id can be copied from OSGI console


Search for "Apache Sling Service User Mapper Service Amendment" add service mapping


Login to - http://localhost:4502/useradmin
Search for the user "packageassembler"
Provide the read-only access to the repository

Provide create/modify/delete access to /etc/packages


Factory class to define the Job configuration

@Component(configurationFactory = true, policy = ConfigurationPolicy.OPTIONAL, metatype = true, immediate = true, label = "Scheduled Package Generator")
@Service(value = GeneratePackageSchedulerRequest.class)
public class GeneratePackageSchedulerRequest {

final Logger logger = LoggerFactory.getLogger(this.getClass());

@Property(unbounded=PropertyUnbounded.DEFAULT, label="Scheduler Expression", description="Scheduler Expression", value="")
private static final String SCHEDULER_EXPRESSION = "sheduleExpression";
private String sheduleExpression;

@Property(unbounded = PropertyUnbounded.ARRAY, label = "Packages Filter String", cardinality = 50, description = "Packages Filter String")
public static final String PACKAGE_FILTERS = "packageFilters";
private String[] packageFilters;

@Property(unbounded=PropertyUnbounded.DEFAULT, label="Package Name", description="Package Name")
private static final String PACKAGE_NAME = "packgeName";
private String packageName;

@Property(unbounded=PropertyUnbounded.DEFAULT, label="Root Path to store the package", description="Root Path")
private static final String ROOT_PATH = "rootpath";
private String rootPath;

protected void activate(final ComponentContext ctx) {

Dictionary<?, ?> props = ctx.getProperties();
sheduleExpression = PropertiesUtil.toString(props.get(SCHEDULER_EXPRESSION), "");

packageFilters = PropertiesUtil.toStringArray(props.get(PACKAGE_FILTERS), null);
packageName = PropertiesUtil.toString(props.get(PACKAGE_NAME), null);
rootPath=PropertiesUtil.toString(props.get(ROOT_PATH), null);

public String[] getPackageFilters() {
return packageFilters;

public String getJobname() {
return packageName;

public String getSheduleExpression() {
return sheduleExpression;

public String getRootPath() {
return rootPath;


Job class to create the package based on the Job parameter.

@Component(immediate = true, metatype = true)

public class GeneratePackageScheduledTask {

private SlingRepository repository;
private ResourceResolverFactory resolverFactory;
private SlingSettingsService settingsService;
private Scheduler  scheduler;
private Packaging packaging;
protected final Logger logger = LoggerFactory.getLogger(this.getClass());

@Reference(cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, referenceInterface = GeneratePackageSchedulerRequest.class, policy = ReferencePolicy.DYNAMIC)
private final List<GeneratePackageSchedulerRequest> providers = new LinkedList<GeneratePackageSchedulerRequest>();

protected void bindProviders(final GeneratePackageSchedulerRequest config) throws Exception {

final String schedulingExpression=config.getSheduleExpression();
final String jobname= config.getJobname();
final String[] packageFilters = config.getPackageFilters();
final Runnable job = new Runnable() {
public void run() {
Session session=null;
if (isRunMode("author")&& isMasterRepository()) {

try {
Map<String, Object> param = new HashMap<String, Object>();
param.put(ResourceResolverFactory.SUBSERVICE, "packageService");
ResourceResolver resolver = resolverFactory.getServiceResourceResolver(param);
//ResourceResolver resolver = resolverFactory.getAdministrativeResourceResolver(null);
session= resolver.adaptTo(Session.class);
logger.debug("{} is now running, Parameter='{}'",jobname, packageFilters);  
List<PathFilterSet> pathFilterSets = new ArrayList<PathFilterSet>();
     for (String packageFilter : packageFilters) {
    pathFilterSets.add(new PathFilterSet(packageFilter));
     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS");
    JcrPackageManager jcrPackageManager = packaging.getPackageManager(session);

JcrPackage jcrPackage = jcrPackageManager.create("ScheduledPackages", jobname+sdf.format(new Date()).toString(), "1.0");
JcrPackageDefinition jcrPackageDefinition = jcrPackage.getDefinition();
DefaultWorkspaceFilter workspaceFilter = new DefaultWorkspaceFilter();
for (PathFilterSet pathFilterSet : pathFilterSets) {

jcrPackageDefinition.setFilter(workspaceFilter, true);
jcrPackageDefinition.set(JcrPackageDefinition.PN_DESCRIPTION, "Scheduled Package"+jobname+sdf.format(new Date()).toString(), false);
String filePath=config.getRootPath()+File.separator+ config.getJobname()+sdf.format(new Date()).toString()+".zip";
logger.debug("Package Export File Path:"+filePath);
ProgressTrackerListener listener = new DefaultProgressListener();
jcrPackageManager.assemble(jcrPackageDefinition,listener, new FileOutputStream(filePath));
} catch (Exception rex) {
logger.error("Error occurred in pckage creation..", rex.getMessage());
}finally {
if (session != null) {

logger.debug("run() END"+jobname);

ScheduleOptions so = scheduler.EXPR(schedulingExpression);;
this.scheduler.schedule(job, so);
logger.debug("Scheduled Job: " + config.getJobname()+" "+schedulingExpression);

protected void unbindProviders(final GeneratePackageSchedulerRequest config) {
logger.debug("Removed Job: " + config.getJobname());
private Boolean isRunMode(String mode) {
Set<String> runModes = settingsService.getRunModes();
for (String runMode : runModes) {
if (runMode.equalsIgnoreCase(mode)) {
logger.debug("Current Runmode is : " + runMode);
return true;
return false;
public boolean isMasterRepository(){
    final String isMaster = repository.getDescriptor("crx.cluster.master");
    return isMaster!=null && !isMaster.equals("") && Boolean.parseBoolean(isMaster);

After deployment, Login to config manager - http://localhost:4502/system/console/configMgr
Search for "Scheduled Package Generator" and configure the Jobs(multiple jobs can be configured)

Scheduler Expression - Specify the scheduler expression to run the Job(use Cron maker to generate the expression)
Package Filter - Specify the repository path to include in the package(multiple paths can be specified)
Package Name - Specify the package name
Root Path to store the package - Specify the parent path in the server to store the package



After enabling the configurations the packages will be created in specified location based on the scheduled time.


Download the sample code - com.packagegenerator.core.schedulers in core module)

No comments:

Post a Comment