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

AEM-service-user

Click on Create System User

AEM-service-user

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

AEM-service-user


AEM-service-user



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

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

AEM-service-user

The bundle id can be copied from OSGI console

AEM-service-user


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

AEM-service-user

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

AEM-service-user

GeneratePackageSchedulerRequest.java:


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;


@Activate
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;
}

}


GeneratePackageScheduledTask.java


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

@Component(immediate = true, metatype = true)
@Service(GeneratePackageScheduledTask.class)

public class GeneratePackageScheduledTask {

@Reference
private SlingRepository repository;
@Reference
private ResourceResolverFactory resolverFactory;
@Reference
private SlingSettingsService settingsService;
@Reference
private Scheduler  scheduler;
@Reference
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 {

providers.add(config);
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) {
workspaceFilter.add(pathFilterSet);
}

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));
jcrPackageManager.remove(jcrPackage);
} catch (Exception rex) {
rex.printStackTrace();
logger.error("Error occurred in pckage creation..", rex.getMessage());
}finally {
if (session != null) {
session.logout();
}
}
}

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

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

protected void unbindProviders(final GeneratePackageSchedulerRequest config) {
logger.debug("Removed Job: " + config.getJobname());
this.scheduler.unschedule(config.getJobname());
providers.remove(config);
}
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");
    logger.debug("isMaster.."+isMaster);
    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

AEM-package-generator-scheduler


OSGI-scheduler-factory

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

AEM-package-generator-scheduler

Download the sample code - https://gitlab.com/albinsblog-data/PackageGenerator(Refer com.packagegenerator.core.schedulers in core module)

No comments:

Post a Comment