ResourceChangeListener onChange event not getting trigger | Community
Skip to main content
Level 2
Apr 23, 2019 9:59 AM UTC

ResourceChangeListener onChange event not getting trigger

Hi All,

the following code for onChange used to work in AEM 6.2 but after we migrated to 6.3 , I see onChange is not getting fired, not sure what is going wrong.

@Component(immediate = true)

@Service
@Properties(value = { @Property(name = ResourceChangeListener.PATHS, value = { CommunityConstants.CONTENT_ROOT_PATH }),

   @Property(name = ResourceChangeListener.CHANGES, value = { "ADDED", "CHANGED" }, propertyPrivate = true) })

public class xyz implements ResourceChangeListener {

@Reference
private ResourceResolverFactory resourceResolverFactory;

@Reference
private ContentModelService contentModelService;

@Override
public void onChange(@Nonnull List<ResourceChange> changes) {

//some logic here

}

}

Please help me to understand it further.

Many Thanks,

Kranthi

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.

12 replies

joerghoh
Employee
Apr 23, 2019 10:23 AM UTC

Some basic checks first:

* Please check that the bundle containing this service is active.

* Please check that the component "xyz" is active (check on the Components list in the OSGI webconsole).

Jörg

Translate
smacdonald2008
Level 10
Apr 23, 2019 10:55 AM UTC

Issue is how session is obtained. You need to use a system user and give correct permissions. This works....

Component(immediate=true,

service= EventListener.class)

public class SimpleResourceListener implements EventListener{

 

    Logger log = LoggerFactory.getLogger(this.getClass());

     private Session adminSession;

     

    

     @Reference

     org.apache.sling.jcr.api.SlingRepository repository;

     

     @Activate

     public void activate(ComponentContext context) throws Exception {

     log.info("activating ExampleObservation");

     try {

         adminSession = repository.loginService("datawrite",null);

         adminSession.getWorkspace().getObservationManager().addEventListener(

          this, //handler

          Event.PROPERTY_ADDED|Event.NODE_ADDED, //binary combination of event types

          "/apps/example", //path

          true, //is Deep?

          null, //uuids filter

          null, //nodetypes filter

          false);

     

         

     } catch (RepositoryException e){

      log.error("unable to register session",e);

      throw new Exception(e);

     }

    }

    @Deactivate

    public void deactivate(){

     if (adminSession != null){

      adminSession.logout();

     }

    }

     

    public void onEvent(EventIterator eventIterator) {

      try {

        while (eventIterator.hasNext()){

          log.info("something has been added : {}", eventIterator.nextEvent().getPath());

        }

       } catch(RepositoryException e){

       log.error("Error while treating events",e);

      }

     }

    }

Translate
Level 2
Apr 24, 2019 9:37 AM UTC

Hi smacdonald2008​ , this is what we are doing. so you suggest us to write @Activate to get the session & @Deactivate to destroy the session ?

package com.xyz.help.conteenginecore.listener;

import java.util.List;

import java.util.Optional;

import com.adobe.cq.social.community.api.CommunityConstants;

import com.xyz.help.conteenginecore.Constants;

import com.xyz.help.conteenginecore.ContentModel;

import com.xyz.help.conteenginecore.ContentModelService;

import com.google.common.annotations.VisibleForTesting;

import javax.annotation.Nonnull;

import org.apache.felix.scr.annotations.Component;

import org.apache.felix.scr.annotations.Properties;

import org.apache.felix.scr.annotations.Property;

import org.apache.felix.scr.annotations.Reference;

import org.apache.felix.scr.annotations.Service;

import org.apache.sling.api.resource.LoginException;

import org.apache.sling.api.resource.ModifiableValueMap;

import org.apache.sling.api.resource.PersistenceException;

import org.apache.sling.api.resource.Resource;

import org.apache.sling.api.resource.ResourceResolver;

import org.apache.sling.api.resource.ResourceResolverFactory;

import org.apache.sling.api.resource.ValueMap;

import org.apache.sling.api.resource.observation.ResourceChange;

import org.apache.sling.api.resource.observation.ResourceChangeListener;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

/**
* Listens changing of resources, and in case when was added "articelNo"
* property, adding generated "articleId" property to the same node.
*/
@Component(immediate = true)

@Service
@Properties(value = { @Property(name = ResourceChangeListener.PATHS, value = { CommunityConstants.CONTENT_ROOT_PATH }),

   @Property(name = ResourceChangeListener.CHANGES, value = { "ADDED", "CHANGED" }, propertyPrivate = true) })

public class GenerateArticleIdOnAddingArticleNumber implements ResourceChangeListener {

   private static final Logger LOG = LoggerFactory.getLogger(GenerateArticleIdOnAddingArticleNumber.class);

   @Reference
   private ResourceResolverFactory resourceResolverFactory;

   @Reference
   private ContentModelService contentModelService;

   @Override
   public void onChange(@Nonnull List<ResourceChange> changes) {

   try (ResourceResolver resolver = resourceResolverFactory
   .getServiceResourceResolver(Constants.CONTENT_ENGINE_AUTH_INFO)) {

  changes.stream().filter(resourceChange -> resourceChange.getAddedPropertyNames() != null)

  .filter(resourceChange -> !resourceChange.getAddedPropertyNames().isEmpty())

  .filter(resourceChange -> resourceChange.getAddedPropertyNames()

  .contains(ContentModel.HelpArticle.PN_ARTICLE_NUMBER))

  .forEach(resourceChange -> {

  addArticleIdProperty(resourceChange, resolver);

  addDefClassificationProperty(resourceChange, resolver);

  });

  resolver.commit();

  } catch (LoginException e) {

   LOG.error("Can't perform action", e);

  } catch (PersistenceException e) {

   LOG.error("Can't perform action", e);

  }

  }

   private void addArticleIdProperty(ResourceChange resourceChange, ResourceResolver resourceResolver) {

  Resource resource = resourceResolver.resolve(resourceChange.getPath());

  Optional.ofNullable(resource.adaptTo(ModifiableValueMap.class)).ifPresent(valueMap -> valueMap

  .put(ContentModel.HelpArticle.PN_ARTICLE_ID, contentModelService.generateArticleId(resource)));

  }

   private void addDefClassificationProperty(ResourceChange resourceChange, ResourceResolver resourceResolver) {

  Resource resource = resourceResolver.resolve(resourceChange.getPath());

  Optional.ofNullable(resource.adaptTo(ModifiableValueMap.class)).ifPresent(

  valueMap -> valueMap.put(ContentModel.HelpArticle.PN_CLASSIFICATION, "ArticleClassification:help"));

  }

   @VisibleForTesting
   void bindResourceResolverFactory(ResourceResolverFactory resolverFactory) {

   this.resourceResolverFactory = resolverFactory;

  }

   @VisibleForTesting
   void bindContentModelService(ContentModelService contentModelService) {

   this.contentModelService = contentModelService;

  }

}

Translate