Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.
SOLVED

JCR Session comes back null in custom Workflow step implementation

Avatar

Level 3

I have created a custom Workflow step for AEM 6.0.  I created a class that implements com.adobe.granite.workflow.exec.WorkflowProcess.  I need to get the jcr session and session.adaptTo(Session.class) is returning null.  session is not null and its type is com.adobe.granite.workflow.WorkflowSession.  The example in the Extending Workflow Functionality documentation uses this call to get the jcr session. http://docs.adobe.com/docs/en/aem/6-0/develop/extending/workflows/wf-extending.html

Below is the class declaration and the first part of the execute method.  This custom Workflow step is set up in place of the Product Asset Upload step at the end of the DAM Update Asset Workflow. 

@Component
@Service(value = WorkflowProcess.class)
@Properties({
 @Property(name = "process.label", value = "Custom Product Assets Upload Process"),
 @Property(name = Constants.SERVICE_DESCRIPTION, value = "Custom Product Assets Upload Process"),
 @Property(name = Constants.SERVICE_VENDOR, value = "Test")
})
public class CustomProductAssetsUploadProcess implements com.adobe.granite.workflow.exec.WorkflowProcess{
 
 private static final String TYPE_JCR_PATH = "JCR_PATH";
    private static final Logger log = LoggerFactory.getLogger(CustomProductAssetsUploadProcess.class);
    public static final String ENABLE_WRITEBACK = "writebackEnable";
 
    @Reference(cardinality= ReferenceCardinality.MANDATORY_UNARY, policy = ReferencePolicy.STATIC)
    private ResourceResolverFactory resourceResolverFactory;
   
    public void execute(WorkItem item, WorkflowSession session, MetaDataMap args) throws WorkflowException {

        try {
           String payloadPath = null;

            if (item.getWorkflowData().getPayloadType().equals(TYPE_JCR_PATH)) {
                payloadPath = item.getWorkflowData().getPayload().toString();
            }
                       
            log.info("payload path :"+payloadPath);
                       
            Session jcrSession = session.adaptTo(Session.class);

...

1 Accepted Solution

Avatar

Correct answer by
Employee

Hmm...

Is there any chance you are embedding a dependency jar inside your bundle?  If you have your own copy of the javax.jcr.Session class file inside your bundle the classloaders could be messed up.  

Sorry again just a guess.

Will

View solution in original post

11 Replies

Avatar

Level 10

As of AEM 6, you get a session instance (required to work with the JCR API) by using a Sling method named getServiceResourceResolver().


 The following code shows use of the more secure getServiceResourceResolverAPI call.

Map<String, Object> param = new HashMap<String, Object>();
param.put(ResourceResolverFactory.SUBSERVICE, "datawrite");
ResourceResolver resolver = null;

try {
           
    //Invoke the adaptTo method to create a Session used to create a QueryManager
resolver = resolverFactory.getServiceResourceResolver(param);
    session = resolver.adaptTo(Session.class);

This code uses a specific AEM account with JCR read and write privileges to access the AEM 6 JCR. For more infor, see this community article

http://helpx.adobe.com/experience-manager/using/querying-experience-manager-sling.html
 

Avatar

Employee

Please check if you are using correct API to access the session. The OOTB code still uses old com.day.cq.workflow.WorkflowSession; code

while the example recommend using  com.adobe.granite.workflow.WorkflowSession;

http://docs.adobe.com/docs/en/cq/5-3/javadoc/com/day/cq/workflow/WorkflowSession.html 

Avatar

Employee

I tried to reproduce this and could not. If you log the session object, what do you get?

Regards,

Justin

Avatar

Employee

Hi,

Shot in the dark here - wondering what the import for the Session class you are using is in your original example. Is there any chance you've got the wrong Session specified?

You should always be able to adapt a com.adobe.granite.worklfow.WorkflowSession to a javax.jcr.Session

Will

Avatar

Level 3

The import for the Session class I am trying to adapt to is: import javax.jcr.Session;

Avatar

Level 3

This is what I get when I log the WorkflowSession object.

06.02.2015 09:50:46.121 *INFO* [JobHandler: /etc/workflow/instances/2015-02-06/model_320814424647979:/content/dam/projects/test10/incoming/Test Photoshoot.zip/jcr:content/renditions/original] com.custom.dam.bl.services.CustomProductAssetsUploadProcess com.adobe.granite.workflow.core.WorkflowSessionImpl@40ee7b69

Avatar

Level 10

Did you use the getServiceResourceResolver()method to get a session object in the custom Workflow step? 

Avatar

Correct answer by
Employee

Hmm...

Is there any chance you are embedding a dependency jar inside your bundle?  If you have your own copy of the javax.jcr.Session class file inside your bundle the classloaders could be messed up.  

Sorry again just a guess.

Will

Avatar

Level 3

That fixed it.  I accidentally had that dependency in my pom file.  Thanks for the help.

I'm running into another issue in the code below.  

Asset asset = null;
        if (item.getWorkflowData().getPayloadType().equals("JCR_PATH")) {
            String path = item.getWorkflowData().getPayload().toString();
            //Resource resource = this.getResourceResolver(session).getResource(path);
            Resource resource = resourceResolver.getResource(path);            
            if (null != resource) {
                asset = DamUtil.resolveToAsset(resource);
            }
            else {
                log.error("getAssetFromPaylod: asset [{}] in payload of workflow [{}] does not exist.", path, item.getWorkflow().getId());
            }
        }
        return asset;

DamUtil.resolveToAsset(resource) is throwing an exception.  I think this may be a dependency issue as well.  Here is the exception:

com.adobe.granite.workflow.WorkflowException: Process execution resulted in an error
    at com.adobe.granite.workflow.core.job.HandlerBase.executeProcess(HandlerBase.java:218)
    at com.adobe.granite.workflow.core.job.JobHandler.process(JobHandler.java:140)
    at org.apache.sling.event.jobs.JobUtil$1.run(JobUtil.java:365)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.LinkageError: loader constraint violation: when resolving method "com.day.cq.dam.commons.util.DamUtil.resolveToAsset(Lorg/apache/sling/api/resource/Resource;)Lcom/day/cq/dam/api/Asset;" the class loader (instance of org/apache/felix/framework/BundleWiringImpl$BundleClassLoaderJava5) of the current class, com/custom/dam/bl/services/customProductAssetsUploadProcess, and the class loader (instance of org/apache/felix/framework/BundleWiringImpl$BundleClassLoaderJava5) for resolved class, com/day/cq/dam/commons/util/DamUtil, have different Class objects for the type ling/api/resource/Resource;)Lcom/day/cq/dam/api/Asset; used in the signature
    at com.custom.dam.bl.services.customProductAssetsUploadProcess.getAssetFromPayload(CustomProductAssetsUploadProcess.java:181)
    at com.custom.dam.bl.services.customProductAssetsUploadProcess.execute(CustomProductAssetsUploadProcess.java:116)
    at com.adobe.granite.workflow.core.job.HandlerBase.executeProcess(HandlerBase.java:212)
    ... 5 common frames omitted

Avatar

Level 3

I just tried that.  I am getting an error in the log "Login Failure: all modules ignored".  I completed the following to test this out:

1.  I added a user with the login = "data" and gave them  the necessary permissions.

2.  I updated the configuration for the Apache Sling Service User Mapper Service to include the following entry:

com.custom.dam.bl.services.CustomProductAssetsUploadProcess:datawrite=data

 

3.  I added the following code:

Map<String, Object> param = new HashMap<String, Object>();
param.put(ResourceResolverFactory.SUBSERVICE, "datawrite");
ResourceResolver resolver = null;
try{      
         resolver = resourceResolverFactory.getServiceResourceResolver(param);

...

Avatar

Employee

Hi,

Glad that was the issue.  Yes the next problem you're seeing also seems to be the same issue.  Basically you want to make sure that any dependencies you use in your POM don't get embedded (either the jar or jar exploded .class files) in the jar you build.  You can open the jar you build in winzip or another zip tool to see what's in it to verify that you got it right, and then play with your pom.xml file.

Good luck!

Will