Your achievements

Level 1

0% to

Level 2

Tip /
Sign in

Sign in to Community

to gain points, level up, and earn exciting badges like the new
Bedrock Mission!

Learn more

View all

Sign in to view all badges

SOLVED

Multiple paths handling in EventHandler not working

thatsmeadarsh
Level 3
Level 3

I need to get the events while the property 'jcr:lastModified' is either added or modified. Also I only need to watch certain paths. I tried to add properties like this. I also checked the event console http://localhost:4502/system/console/events where I couldn't find my class. The debugger is also not reaching to the handleEvent method. Is this the correct way to do this.

 

@component(immediate = true, service = EventHandler.class, property = {
Constants.SERVICE_DESCRIPTION + "= This event handler listens the events on asset addition/modification",
EventConstants.EVENT_TOPIC + "=org/apache/sling/api/resource/Resource/ADDED",
EventConstants.EVENT_TOPIC + "=org/apache/sling/api/resource/Resource/CHANGED",
EventConstants.EVENT_FILTER + "(&" + "(|(path=/content/dam/custom-path1/*/jcr:content)(path=/content/dam/custom-path2/*/jcr:content)) (|("
+ SlingConstants.PROPERTY_CHANGED_ATTRIBUTES + "=*jcr:lastModified) " + "(" + ResourceChangeListener.CHANGES
+ "=*jcr:lastModified)))" })
public class PreviewS3AssetEventHandler implements EventHandler {

@Override
public void handleEvent(Event event) {
String event1 = event.getTopic();
String event2 = event1;

}

}

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution
Vijayalakshmi_S
Correct answer by
Community Advisor
Community Advisor

Hi @thatsmeadarsh,

Since we are looking for property change/add event on a Resource, we can make use of specific Listener named "ResourceChangeListener"https://sling.apache.org/apidocs/sling9/org/apache/sling/api/resource/observation/ResourceChangeList...

Sample snippet : (tried and works in my local - AEM 6.5.0)

Have used the PATHS as is without pattern. Glob pattern is allowed, check the description and use per your need - https://sling.apache.org/apidocs/sling9/org/apache/sling/api/resource/observation/ResourceChangeList...

package com.aem.demoproject.core.listeners;

import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChangeListener;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

@Component(service = ResourceChangeListener.class, immediate = true, property = {
        ResourceChangeListener.PATHS + "=/content/dam/demo",
        ResourceChangeListener.PATHS + "=/content/dam/we-retail/en/features",
        ResourceChangeListener.CHANGES + "=CHANGED",
        ResourceChangeListener.CHANGES + "=ADDED",
        ResourceChangeListener.PROPERTY_NAMES_HINT + "=jcr:lastModified"
})
public class SampleResourceChangeListener implements ResourceChangeListener {

    private final Logger LOG = LoggerFactory.getLogger(this.getClass());

    @Override
    public void onChange(List<ResourceChange> list) {
        LOG.info("On add/change of jcr:lastModified");
    }
}

View solution in original post

7 Replies
Vijayalakshmi_S
Correct answer by
Community Advisor
Community Advisor

Hi @thatsmeadarsh,

Since we are looking for property change/add event on a Resource, we can make use of specific Listener named "ResourceChangeListener"https://sling.apache.org/apidocs/sling9/org/apache/sling/api/resource/observation/ResourceChangeList...

Sample snippet : (tried and works in my local - AEM 6.5.0)

Have used the PATHS as is without pattern. Glob pattern is allowed, check the description and use per your need - https://sling.apache.org/apidocs/sling9/org/apache/sling/api/resource/observation/ResourceChangeList...

package com.aem.demoproject.core.listeners;

import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChangeListener;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

@Component(service = ResourceChangeListener.class, immediate = true, property = {
        ResourceChangeListener.PATHS + "=/content/dam/demo",
        ResourceChangeListener.PATHS + "=/content/dam/we-retail/en/features",
        ResourceChangeListener.CHANGES + "=CHANGED",
        ResourceChangeListener.CHANGES + "=ADDED",
        ResourceChangeListener.PROPERTY_NAMES_HINT + "=jcr:lastModified"
})
public class SampleResourceChangeListener implements ResourceChangeListener {

    private final Logger LOG = LoggerFactory.getLogger(this.getClass());

    @Override
    public void onChange(List<ResourceChange> list) {
        LOG.info("On add/change of jcr:lastModified");
    }
}

View solution in original post

thatsmeadarsh
Level 3
Level 3

Thanks @Vijayalakshmi_S  and @Arun_Patidar  for your response. Resource change listener seems to be more appropriate option for me. However I am wondering if it is possible to inject the path properties from an OSGI configuration, cause we are looking for dynamic path listener.

Arun_Patidar
Community Advisor
Community Advisor

The type of thePATHS property must either be String, or a String array and

The value for annotation attribute Component.property must be a constant expression.

 

So you can't pass dynamic value here.

thatsmeadarsh
Level 3
Level 3

Thanks @Arun_Patidar  for the clarification. I was thinking maybe some factory service injecting OSGi config properties as constructor would work. 

Vijayalakshmi_S
Community Advisor
Community Advisor

Hi @thatsmeadarsh

You can make use of ObjectClassDefinition(OCD) for providing component configuration properties dynamically from Config Admin. 

Sample snippet :

  • resource_paths() here will be evaluated as resource.paths which is the constant value for ResourceChangeListener.PATHS
    • Same goes with other two. 
  • If you would like to have the Listener working with specified default values for the very first time it is deployed/when you don't provide the config values via Config Admin(/configMgr), use the @Activate method with Config as the param. 
  • Otherwise, you can remove the method -> Once the code is deployed, provide the desired config values via /configMgr and then Listener would work with respective property and its values. 
package com.aem.demoproject.core.listeners;

import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChangeListener;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
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;

import java.util.List;

@Component(service = ResourceChangeListener.class, immediate = true)
@Designate(ocd = SampleResourceChangeListener.Config.class)
public class SampleResourceChangeListener implements ResourceChangeListener {

    private final Logger LOG = LoggerFactory.getLogger(this.getClass());

    @Override
    public void onChange(List<ResourceChange> list) {
        LOG.info("On add/change of jcr:lastModified, listener activated with config via OCD");
    }

    @Activate
    protected void activate(SampleResourceChangeListener.Config configValues) {
        LOG.debug("Config values={}", configValues.resource_paths());
    }

    @ObjectClassDefinition(name = "SampleResourceChangeListener", description = "Resource change Listener Registration properties")
    public @interface Config {
        @AttributeDefinition(name = "Paths", description = "ResourceChangeListener Paths property")
        String[] resource_paths() default {"/content/dam/demo"};

        @AttributeDefinition(name = "Changes", description = "ResourceChangeListener Changes property")
        String[] resource_change_types() default {"CHANGED"};

        @AttributeDefinition(name = "Properties", description = "ResourceChangeListener PropertyNamesHint property")
        String[] resource_property_names_hint() default {"jcr:lastModified"};
    }
}

 

Arun_Patidar
Community Advisor
Community Advisor

Hi,

You can combine the path in single rule e.g.

path=/content/dam/onemarketing/platform/(oe1-ref-headless-portal|patternlab)/*/jcr:content

EventConstants.EVENT_FILTER + "(&" + "(|(path=/content/dam/onemarketing/platform/(oe1-ref-headless-portal|patternlab)/*/jcr:content)(|("
+ SlingConstants.PROPERTY_CHANGED_ATTRIBUTES + "=*jcr:lastModified) " + "(" + ResourceChangeListener.CHANGES
+ "=*jcr:lastModified)))" })