Expand my Community achievements bar.

Event handler triggered twice in AEM as Cloud Service or Not getting Triggered at all.

Avatar

Level 4

HI Team,

We have a requirement :
when Page got activated or deactivated  we need to send the page info( path, title ,uuid) to other systems.
We are writing a event handler for it. It is working as expected. But, Event handler is getting Triggered twice. Below is the code.


@Slf4j
@component( service = EventHandler.class, immediate = true,
property = { EventConstants.EVENT_TOPIC + "=" + ReplicationAction.EVENT_TOPIC, })
public class ReplicationEventHandler implements EventHandler {

If we subscribe to org/apache/sling/event/notification/job/FINISHED or org/apache/sling/distribution/agent/package/distributed
Then Event handler is not getting triggered at all. Below is the code.

@Slf4j
@component(immediate = true, service = EventHandler.class,

property = { "event.topics=org/apache/sling/event/notification/job/FINISHED",
"event.filter=(|(distribution.type=ADD)(distribution.type=DELETE))" })
public class ReplicationEventHandler implements EventHandler {

OR
@Slf4j @component(immediate = true, service = EventHandler.class, property = { "event.topics=org/apache/sling/distribution/agent/package/distributed",
"event.filter=(|(distribution.type=ADD)(distribution.type=DELETE))" })
public class ReplicationEventHandler implements EventHandler {


Could you please review the sample code and provide guidance on resolving this issue?

26 Replies

Avatar

Community Advisor

Event Handler triggering twice generally happens with multiple events trigger when a page is activated (like one ReplicationAction event and/or ResourceEvent for any change in resources etc.)

To handle this - write a condition to handle your ReplicationAction event only

@Slf4j
@component( service = EventHandler.class, immediate = true,
property = { EventConstants.EVENT_TOPIC + "=" + ReplicationAction.EVENT_TOPIC, })
public class ReplicationEventHandler implements EventHandler {

ReplicationAction action = ReplicationAction.fromEvent(event);
if (action != null && (action.getType() == ReplicationAction.Type.ACTIVATE || action.getType() == ReplicationAction.Type.DEACTIVATE)) {
// Handle the event
}
 
==== Event handler is not getting triggered=====
 
Job Finished event or distributed event - These events are not part of the Page Activate or DeActivate actions - these events are related to Sling - please check more details on Sling Job System / Sling Distribution System.

Avatar

Level 4

Hi Suresh, Thanks for the response.
I wrote the same kind of code. Still it is triggered twice. Because in Cloud it is cluster and it will have minimum 2 clusters at any time. This issue occurs only in cloud but not in local. 

ReplicationAction action =ReplicationAction.fromEvent(event);
ReplicationActionType actionType =action.getType();
if (actionType != ReplicationActionType.DELETE && actionType != ReplicationActionType.ACTIVATE
&& actionType != ReplicationActionType.DEACTIVATE) {
log.error("The action type {} is not allowed for the page {}.", actionType.getName(), actionPath);
return;
}

Avatar

Community Advisor

@Rudra-2024  For the case where the event handler is not getting triggered, could it be due to the fact that your event handler execution takes more than 5000 ms and hence causing it become blacklisted. Once that happens, your event handler is no longer functional.  We ran into this type of scenario recently. 

If that is the case, you might want to look at your implementation and see if there is anything that is potentially causing this.

You can read more on this in a similar discussion thread - 

https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/lt-critical-gt-event-handl...

 

Avatar

Level 4

Thanks for the response. I restarted the instance. Still the same issue.

Avatar

Level 4

Hi @SureshDhulipudi  , Please find below code

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.discovery.DiscoveryService;
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.JobManager;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;

/**
* The Class ReplicationEventHandler.
*/
@Slf4j
@Component(
service = EventHandler.class,
immediate = true,
property = {
EventConstants.EVENT_TOPIC + "=" + ReplicationAction.EVENT_TOPIC,
})
public class ReplicationEventHandler implements EventHandler {

 

/**
* The DiscoveryService.
*/
@Reference
private DiscoveryService discoveryService;

/**
* The RunModeConfigService.
*/
@Reference
private RunModeConfigService runModeConfigService;

/**
* The jobManager service.
*/
@Reference
private JobManager jobManager;


/**
* {@inheritDoc}
*/
@Override
public void handleEvent(Event event) {
ReplicationAction action = getAction(event);
String actionPath = action.getPath();
log.debug("\n Replication Event occurred at the path {} and the action is {}", actionPath,
action.getType().getName());
String instanceName =
discoveryService.getTopology().getLocalInstance().getProperty("org.apache.sling.instance.name");
String ins = runModeConfigService.getInstance();
log.debug("instanceName from Topology {}", instanceName);
log.debug("Is it Local instance {}", discoveryService.getTopology().getLocalInstance().isLocal());
log.debug("Is it Leader instance {}", discoveryService.getTopology().getLocalInstance().isLeader());
log.debug("instanceName from Run mode {}", ins);

syncAemContentToExternalSystem(action, actionPath);

}

private void syncAemContentToExternalSystem(ReplicationAction action, String actionPath) {

//actual Business logic
}

}

Avatar

Administrator

@Rudra-2024 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

Avatar

Level 4

Hi @kautuk_sahni  I didn't find the answer yet. Could you please help me on this.

Avatar

Level 4

Hi @arunpatidar 

Thanks for the response.

I pretty much followed the same as below article.
https://sudeshaempodcast.wordpress.com/2021/07/04/aemaacs-slingjobs/

Only problem is when the topic is EventConstants.EVENT_TOPIC + "=" + ReplicationAction.EVENT_TOPIC, It is getting triggered twice.



when the topic is"event.topics=org/apache/sling/distribution/agent/package/distributed", or 
 "event.topics=org/apache/sling/event/notification/job/FINISHED
is not triggered at all.

Avatar

Community Advisor

HI @Rudra-2024 
Are you doing this on publish or author?

Can you check the number of events at http://localhost:4502/system/console/events 



Arun Patidar

Avatar

Level 4

ON Author instance only.

I tried below logs 

String instanceName =discoveryService.getTopology().getLocalInstance().getProperty("org.apache.sling.instance.name");
String ins = runModeConfigService.getInstance();
log.debug("instanceName from Topology {}", instanceName);
log.debug("Is it Local instance {}", discoveryService.getTopology().getLocalInstance().isLocal());
log.debug("Is it Leader instance {}", discoveryService.getTopology().getLocalInstance().isLeader());
log.debug("instanceName from Run mode {}", ins);


Every time it is printing the same answer 2 times in author instance.

Avatar

Community Advisor

@Rudra-2024 

 

Please verify is Sling Jobs would suit your need. They are better suited to work on AEMaaCS Clusters.

https://techrevel.blog/2023/11/06/enhancing-efficiency-and-reliability-by-sling-jobs/


Aanchal Sikka

Avatar

Level 4

Hi @aanchal-sikka 

Thank you for your response. In my scenario, it's crucial to react to both page activation and deactivation events. While Sling jobs might not directly address this requirement, I've devised the following approach:

  1. Implement an event handler to capture page activation/deactivation events.
  2. Within the event handler, incorporate logic to trigger a job.
  3. Utilize a Sling job to execute the necessary business logic.

However, if you believe that Sling jobs will directly listen page activation and deactivation events, I would greatly appreciate any reference links or sample code you could provide.




Avatar

Level 4

HI @joerghoh,Good Evening.

Any insights or leads regarding this matter?

Thanks in advance.

Avatar

Level 4

@SureshDhulipudi @arunpatidar @aanchal-sikka @Harwinder-singh 

I tried 

@Component(immediate = true, service = EventHandler.class, property = {EVENT_TOPIC + "=" + AGENT_PACKAGE_DISTRIBUTED,
"event.filter=(|(distribution.type=ADD)(distribution.type=DELETE))"})
public class ContentDistributionEventHandler implements EventHandler {

 


I tried below options. Still it is printing the logs twice.

@Component(immediate = true, service = EventHandler.class, property = {EVENT_TOPIC + "=" + AGENT_PACKAGE_DISTRIBUTED,
"event.filter=(|(distribution.type=ADD)(distribution.type=DELETE))"})
public class ContentDistributionEventHandler implements EventHandler {

 

 

@Slf4j
@Component(service = ResourceChangeListener.class, immediate = true, property = {
ResourceChangeListener.PATHS + "=" + GlobalConstants.ONTENT_ROOT_PATH,
ResourceChangeListener.CHANGES + "=" + "ADDED",
ResourceChangeListener.CHANGES + "=" + "CHANGED",
ResourceChangeListener.PROPERTY_NAMES_HINT + "=" + "cq:lastReplicated"
})
@ServiceDescription("TEST REPLICATION PROPERTY")
public class ReplicationChangeListener implements ResourceChangeListener {

 

 Any suggestions/leads on this?

 

 

Avatar

Community Advisor

can you keep a condition for resourceType (I,e if the replication action happened only on Page) something like that?

or filter the resourceType or filter based on the page path.

duplicate events might be with any of the node properties also getting replicated??

Avatar

Level 4

Hi Suresh,

 

Thanks for the response.

 

I tried the same. still it is getting triggered twice.

Avatar

Level 2

@Rudra-2024 
Hello. I have faced the same issue both of EventListener and EventHandler.
You can try one of the following options mentioned below.

1) Add this in your OSGi filter !(event.application=*). This makes sure, that the event is emitted only once, on clustered authors.
2) Use org.apache.sling.discovery.DiscoveryService#getTopology().getLocalInstance().isLeader() - this will make sure that the event processing will be handled only on master/leader pod.

P.S Sample OSGi Filter - (&(|(distribution.type=ADD)(distribution.type=DELETE))(!(event.application=*)))

Hope this helps.