ResourceChangeListener onChange event not getting trigger | Community
Skip to main content
Level 2
April 23, 2019

ResourceChangeListener onChange event not getting trigger

  • April 23, 2019
  • 1 reply
  • 8807 views

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.

1 reply

joerghoh
Adobe Employee
Adobe Employee
April 23, 2019

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

smacdonald2008
Level 10
April 23, 2019

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);

      }

     }

    }

Level 2
April 24, 2019

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;

  }

}


when I install the bundle, I see null pointer exception

24.04.2019 09:49:34.993 *INFO* [Background Update com.xyz.help.content-engine-core-bundle (833)] com.xyz.help.conteenginecore.listener.GenerateArticleIdOnAddingArticleNumber activating ExampleObservation

24.04.2019 09:49:35.162 *ERROR* [FelixDispatchQueue] org.apache.sling.resourceresolver FrameworkEvent ERROR (java.lang.NullPointerException)