Copy Assets from Crx to Physical server location



I am trying to Copy the asstes from crx to physical server location based on their Metadata (ex release date). So based on the Metadata a listener has to create a scheduler and deploy it to the physical server.

package sampleforms.core.listener;


import java.util.Calendar;

import java.util.Date;

import java.util.HashMap;

import java.util.Map;

import javax.jcr.Node;

import javax.jcr.Property;

import javax.jcr.RepositoryException;

import javax.jcr.Session;

import javax.jcr.observation.Event;

import javax.jcr.observation.EventIterator;

import javax.jcr.observation.EventListener;

import javax.jcr.observation.ObservationManager;

import org.apache.jackrabbit.api.observation.JackrabbitEventFilter;

import org.apache.jackrabbit.api.observation.JackrabbitObservationManager;






import org.osgi.service.component.ComponentContext;

import org.osgi.service.component.annotations.Component;

import org.osgi.service.component.annotations.Reference;

import org.osgi.service.metatype.annotations.AttributeDefinition;

import org.osgi.service.metatype.annotations.Designate;

import org.osgi.service.metatype.annotations.ObjectClassDefinition;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;



@Component(immediate = true, service = EventListener.class)

public class DeployAssetsHandler implements EventListener {

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

// Inject a Sling ResourceResolverFactory


private ResourceResolverFactory resolverFactory;

private Session observationSession = null;

private JackrabbitObservationManager observationManager;


private SlingRepository repository;


private Scheduler scheduler;

    public static final String DEPLOY_DATE_PROPERTY = "deploy_date";

private String damPathImages;

private String serverPathImages;

private final String[] nodeTypes = new String[] { "nt:unstructured" };

// Place app logic here to define the AEM Custom Event Handler

protected void activate() {

damPathImages = "/content/dam/images";

serverPathImages = "Physical server location";

logger.debug("activate: DAM PATH='{}''", damPathImages);

try {

// Invoke the adaptTo method to create a Session

// ResourceResolver resourceResolver =

// resolverFactory.getAdministrativeResourceResolver(null);

observationSession = repository.loginAdministrative(null);

// Setup the event handler to respond to a new claim under

// content/claim....

observationManager = (JackrabbitObservationManager) observationSession.getWorkspace()


JackrabbitEventFilter eventFilter = new JackrabbitEventFilter()


             .setEventTypes(Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED)





observationManager.addEventListener(this,eventFilter);"Observing property changes to {} ", damPathImages);

} catch (Exception e) {

logger.error("Exception {} ", e);



protected void deactivate(ComponentContext componentContext)

throws RepositoryException {

try {

if (observationManager != null) {



} catch (Exception e) {

logger.error("Exception {} ", e);


if (observationSession != null) {


observationSession = null;



// when the event occurred.

public void onEvent(EventIterator it) {

while (it.hasNext()) {

Event event = it.nextEvent();

try {"{} property event: ------->>>>> {}",DEPLOY_DATE_PROPERTY, event.getPath());

Property changedProperty = observationSession.getProperty(event


if (changedProperty.getName().equalsIgnoreCase(DEPLOY_DATE_PROPERTY)) {

Date date = changedProperty.getValue().getDate().getTime();

Date currentDate = new Date();

if (date.getTime() >= currentDate.getTime()) {

Calendar deplotDate = (Calendar) changedProperty


String cronExpression = deplotDate.get(Calendar.SECOND)

+ " " + deplotDate.get(Calendar.MINUTE) + " "

+ deplotDate.get(Calendar.HOUR_OF_DAY) + " "

+ deplotDate.get(Calendar.DAY_OF_MONTH) + " "

+ (deplotDate.get(Calendar.MONTH)+1) + " ? "

+ deplotDate.get(Calendar.YEAR);"cron: {}", cronExpression);

String assetPath = event.getPath().split("/jcr:content")[0];

Node damResorce = observationSession.getNode(assetPath);

String jobName = damResorce.getName();

scheduleWork(assetPath, serverPathImages, cronExpression,jobName);



} catch (Exception e) {

logger.error(e.getMessage(), e);





private void scheduleWork(String assetPath,String saveLocation,String cronExpression,String jobName) {

        try {

  "In ReRegister" + jobName + " " + assetPath + " " + cronExpression);

            Map<String, Serializable> serviceProps = new HashMap<String, Serializable>();

            serviceProps.put("assetPath", assetPath);

            serviceProps.put("jobName", jobName);

            serviceProps.put("saveLocation", saveLocation);

            Runnable job = new DeployAssetsScheduler(serviceProps);

            scheduler.addJob(jobName, job, serviceProps, cronExpression, false);

  "#### Successfully re registered ####" + jobName);

        } catch (Exception e) {

            logger.error("Could not schedule work.", e);



public class DeployAssetsScheduler implements Runnable {

    private Map<String, Serializable> jobProperties;

public DeployAssetsScheduler(Map<String, Serializable> jobProperties) {"#####In my DeployAssetsScheduler constructor with property " + jobProperties.get("jobName"));

        this.jobProperties = jobProperties;



    public void run() {

        // TODO Auto-generated method stub

        logger.debug("In Job Run Method");

        String assetPath = (String) this.jobProperties.get("assetPath");

        String saveLocation = (String) this.jobProperties.get("saveLocation");

        deployAsset(assetPath, saveLocation);



private void deployAsset(String assetPath,

String saveLocation) {

ResourceResolver resourceResolver = null;

try {"entered deployAsset {}",resolverFactory);

resourceResolver = resolverFactory


Resource r = resourceResolver.getResource(assetPath);

Asset asset = r.adaptTo(Asset.class);

Rendition original = asset.getOriginal();

if (original != null) {

String name = asset.getName();

String newFile = saveLocation +"/"+ name;"Asset path {}",newFile);

// Use AssetManager to place the file into the AEM DAM assetMgr = resourceResolver


Asset deployedAsset = assetMgr.createAsset(newFile, original.getStream(),

asset.getMimeType(), true);"End of Deploy Asset {}",deployedAsset.getPath());


} catch (Exception e) {

logger.error("Exception {}", e);

} finally {






Can i use this code.And what type of credentials are required to Read and write in Physical server location Which is  a linux

Accepted Solutions (1)

Accepted Solutions (1)



You mean on the file system of the server?

The AEM Asset Manager is used to place an asset in a CRX path - not outside of the AEM JCR.

If you want to write the file on LINUX file system as opposed to a JCR path - simply use Java File API

Answers (11)

Answers (11)



Hello Smacdonald2008

Right now our platform is copying the images manually to the physical drive with super administrator credentials.

By the code i am going to automate that process. What type of credentials i need to provide in the code .

Thank you




However - Asset Manager API has this method -


Asset createAsset(String path, InputStream is, String mimeType, boolean doSave)

Creates a new Asset at the given path. If an asset already exists at the given path, its original rendition is updated instead of creating a new asset. If inputStream is null new Asset is created without original rendition. If an asset already exists at given path and inputstream is null, original rendition is not updated.

path - The path of the asset to be created.
is - The input stream of the new asset's original binary.
mimeType - The mime type of the new asset's original binary.
doSave - Whether the repository changes are saved or not.
The newly created asset.
So as long as the path parameter is valid - this will work.



As stated above - i would convert your code from repository.loginAdministrative(null) to repository.loginService("datawrite",null);. 

Creating an Event Listener for Adobe Experience Manager 6.4

Using an Event handler like this is a good approach once you change use of  repository.loginAdministrative() to repository.loginService().



The Physical directory is also in AEM.

So some thing like from

content/dam/images  to  /apps/aemadmin/images in the Linux directory

Can I use this approach



This looks like the right approach - you can use Asset Manager API to move the assets to the AEM DAM.

Also - if you use this code in AEM 6.3/6.4 - you must white list the AEM OSGi bundle to use repository.loginAdministrative(null);

A better approach is to use a system user as shown here -- adminSession = repository.loginService("datawrite",null);.

Creating an Event Listener for Adobe Experience Manager 6.4