Expand my Community achievements bar.

Enhance your AEM Assets & Boost Your Development: [AEM Gems | June 19, 2024] Improving the Developer Experience with New APIs and Events
SOLVED

ResourceChangeListener

Avatar

Level 2

I'm writing a ResourceChangeListener to check for changes in a particular property ( for ex : "cq:lastReplicated") 
But the listener gets triggered for any kind of change, I want it to listen only to the property specified in the 

"ResourceChangeListener.PROPERTY_NAMES_HINT"
 
I don't want to use EventListener because I need to listen to multiple changes at once

Here is my example code

 

package com.demo.core.jobs;

import java.util.List;
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 org.osgi.framework.Constants;

/**
 * ResourceChangeListener
 */
@Component(service = ResourceChangeListener.class, property = {
        Constants.SERVICE_DESCRIPTION + "=Demo to listen on changes in the replication",
        ResourceChangeListener.PATHS + "=" + "/content/dam",
        ResourceChangeListener.CHANGES + "=" + "CHANGED",
        ResourceChangeListener.PROPERTY_NAMES_HINT + "=" + "cq:lastReplicated"
})
public class ResourceListenerTest implements ResourceChangeListener {

    /**
     * logger for logging.
     */
    private final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * Override
     */
    
    public final void onChange(final List<ResourceChange> changes) {

        for (ResourceChange change : changes) {
            String path = change.getPath();
            logger.info("Handling resource change at: {}", path);
        }

    }

}

 

 

 
Any suggestion on how to make this work would be appreciated. 
Thanks
1 Accepted Solution

Avatar

Correct answer by
Community Advisor

@hr-empd 

 

If my memory serves me right, following combination of path regex and getPath returns path till property. 

 

@Component(service = ResourceChangeListener.class,
        immediate = true,
        property = {
                ResourceChangeListener.PATHS + "=glob:/content/techrevelaemsite/us/**/products/**",
                ResourceChangeListener.CHANGES + "=" + "ADDED",
                ResourceChangeListener.CHANGES + "=" + "CHANGED",
                ResourceChangeListener.CHANGES + "=" + "REMOVED"
        }
)
public class SimpleResourceListener implements ResourceChangeListener {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void onChange(List<ResourceChange> changes) 
        changes.forEach(change -> {
            logger.info("Resource event: {} at: {}", change.getType(), change.getPath());
        });
    }
}

 Source: https://techrevel.blog/2017/03/15/resourcechangelistener/


Aanchal Sikka

View solution in original post

6 Replies

Avatar

Community Advisor

@hr-empd - From the Apache documentation mentioned here https://sling.apache.org/apidocs/sling9/org/apache/sling/api/resource/observation/ResourceChangeList... its states below:

An optional hint indicating to the underlying implementation that for changes regarding properties (added/removed/changed) the listener is only interested in those property names listed inhere. If the underlying implementation supports this, events for property names that are not enlisted here will not be delivered, however events concerning resources are not affected by this hint. This is only a hint, a change listener registering with this property must be prepared that the underlying implementation is not able to filter based on this property. In this case the listener gets all events as defined with the other properties.

 

Hope this helps!

Avatar

Level 2

Hi @Jineet_Vora  thanks for the response.
Is there any way to filter out changes based on a specific property change, from what I see 

change.getChangedPropertyNames() method is deprecated so there must be a better way to achieve this

Avatar

Community Advisor

@hr-empd 

 

Can you please try printing change.getPath()? I guess it gives you complete path of the change


Aanchal Sikka

Avatar

Level 2

Hi @aanchal-sikka 

I want to know the name of the property that has been changed, path isn't of much use in my case

Avatar

Correct answer by
Community Advisor

@hr-empd 

 

If my memory serves me right, following combination of path regex and getPath returns path till property. 

 

@Component(service = ResourceChangeListener.class,
        immediate = true,
        property = {
                ResourceChangeListener.PATHS + "=glob:/content/techrevelaemsite/us/**/products/**",
                ResourceChangeListener.CHANGES + "=" + "ADDED",
                ResourceChangeListener.CHANGES + "=" + "CHANGED",
                ResourceChangeListener.CHANGES + "=" + "REMOVED"
        }
)
public class SimpleResourceListener implements ResourceChangeListener {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void onChange(List<ResourceChange> changes) 
        changes.forEach(change -> {
            logger.info("Resource event: {} at: {}", change.getType(), change.getPath());
        });
    }
}

 Source: https://techrevel.blog/2017/03/15/resourcechangelistener/


Aanchal Sikka

Avatar

Administrator

@hr-empd Did you find the suggestions from users helpful? Please let us know if more information is required. Otherwise, please mark the answer as correct for posterity. If you have found out solution yourself, please share it with the community.



Kautuk Sahni