Dynamic Path for ResourceChangeListener


As a authoring environment grows, the paths that a ResourceChangeListener should listen to, might change. They could either:

  • become more granular
  • become more generic
  • apply for only specific AEM instances

A developer can use OSGi configurations to adapt to such changes. This would assure that no code changes are required to deal with the path updates.

Step 1: Create a service that activates only when a configuration node is available in AEM Instance.

@Component(label = "Service Label", immediate = true, metatype = true, policy = ConfigurationPolicy.REQUIRE)
@Service
@Properties(value = { @Property(name = ResourceChangeListener.CHANGES, value = { "CHANGED", "ADDED",
"REMOVED" }, propertyPrivate = true) })
public class SampleServiceImpl implements SampleService, ResourceChangeListener {
....

Step 2: Declare a property  for ‘resource.paths’:

public class SampleServiceImpl implements SampleService, ResourceChangeListener {

// Paths to watch for cache update
@Property(label = "Paths to watch for cache update", value = { PageConstants.DUTY_STATION_FOLDER_PATH,
AssetConstants.FLAG_IMAGE_FOLDER_PATH })
private static final String PATHS_TO_WATCH = ResourceChangeListener.PATHS;
....

Step 3: Create an OSGi configuration for the service with property ‘resource.paths’

Step 4: Deploy your code. Verify that the Listener listens to the updated paths configured via:

  • OSGi Configuration node created in Step 3
  • Path updates via OSGi Web Console

Here is the sample code using DS annotations

package blog.techrevel.listeners;
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.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(service = ResourceChangeListener.class, property = { ResourceChangeListener.PATHS + "=" + "/content",
ResourceChangeListener.CHANGES + "=" + "ADDED", ResourceChangeListener.CHANGES + "=" + "REMOVED",
ResourceChangeListener.CHANGES + "=" + "CHANGED"
})
@Designate(ocd = DynamicPathListener.Config.class)
public class DynamicPathListener implements ResourceChangeListener {
public static final Logger LOGGER = LoggerFactory.getLogger(DynamicPathListener.class);
@ObjectClassDefinition(name = "Dynamic Path Listener Config")
public @interface Config {
@AttributeDefinition(name = "Path")
String resource_paths() default "/content";
}
@Override
public void onChange(List<ResourceChange> changeList) {
for (ResourceChange change : changeList) {
LOGGER.info(change.getPath());
LOGGER.info(change.getType().name());
}
}
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s