Expand my Community achievements bar.

Join expert-led, customer-led sessions on Adobe Experience Manager Assets on August 20th at our Skill Exchange.

Event handler fails to activate properly- it needs to be restarted frequently to make it work

Avatar

Level 1

Hi,

 

Event handlers are failing to activate properly in higher environments. They work immediately after deployment, but after a day or two, they stop functioning again. I need to restart them manually to get them working.

I investigated the issue and found that starting the event handler before its referenced service is fully initialized could be a potential cause. To address this, I added @reference(policyOption = ReferencePolicyOption.GREEDY), but it didn’t resolve the issue.

Any help or suggestions would be greatly appreciated.

 

import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

 

@component(
immediate = true,
service = EventHandler.class,
property = {
"event.topics" + "=" + "org/apache/sling/api/resource/Resource/*"
}
)
public class AbcEventHandler implements EventHandler {

private final Logger logger = LoggerFactory.getLogger(this.getClass());

private ExecutorService executorService;

@reference (policyOption = ReferencePolicyOption.GREEDY)
private AbcService abcService;

@Override
public void handleEvent(Event event) {
if (abcService == null) {
logger.warn("Notifier service not available — skip event.");
return;
}
if (abcService.isValidEvent(event, false)) {
executorService.execute(new Runnable() {
@Override
public void run() {
abcService.doSomething(event, false);
}
});
} else if (abcService.isValidPageChange(event, false)) {
executorService.execute(new Runnable() {
@Override
public void run() {
abcService.doSomeTask(event, false);
}
});
}
logger.info("Event received: {} for path: {}", event.getTopic(), event.getProperty("path").toString());
}


@activate
protected void activate(ComponentContext componentContext) {
forceClose();
executorService = Executors.newFixedThreadPool(1);
logger.info("Created aaa Executor Service with 1 dedicated thread.");
}

@deactivate
protected void deactivate() {
forceClose();
}

private void forceClose() {
logger.debug("aaa Executor Service :" + executorService);
if (executorService != null) {
logger.debug("executorService Shutdown? :" + executorService.isShutdown());
if (!executorService.isShutdown()) {
executorService.shutdownNow();
logger.info("Shutdown aaa Executor Service.");
}
}
}
}

4 Replies

Avatar

Community Advisor

Hi @LalithaM,

Try using proper OSGi declarative service patterns to handle dynamic binding/unbinding of the service:

Instead of just a field reference with @Reference, define explicit bind/unbind methods:

@Component(
    immediate = true,
    service = EventHandler.class,
    property = {
        "event.topics=org/apache/sling/api/resource/Resource/*"
    }
)
public class AbcEventHandler implements EventHandler {

    private static final Logger logger = LoggerFactory.getLogger(AbcEventHandler.class);

    private ExecutorService executorService;

    private volatile AbcService abcService;

    @Reference(policyOption = ReferencePolicyOption.DYNAMIC, policy = ReferencePolicy.DYNAMIC)
    protected void bindAbcService(AbcService service) {
        this.abcService = service;
        logger.info("AbcService bound.");
    }

    protected void unbindAbcService(AbcService service) {
        if (this.abcService == service) {
            this.abcService = null;
            logger.warn("AbcService unbound.");
        }
    }

    @Activate
    protected void activate(ComponentContext componentContext) {
        executorService = Executors.newFixedThreadPool(1);
        logger.info("Executor Service created.");
    }

    @Deactivate
    protected void deactivate() {
        if (executorService != null) {
            executorService.shutdownNow();
            logger.info("Executor Service shut down.");
        }
    }

    @Override
    public void handleEvent(Event event) {
        if (abcService == null) {
            logger.warn("AbcService not available - skipping event.");
            return;
        }

        if (abcService.isValidEvent(event, false)) {
            executorService.execute(() -> abcService.doSomething(event, false));
        } else if (abcService.isValidPageChange(event, false)) {
            executorService.execute(() -> abcService.doSomeTask(event, false));
        }

        logger.info("Event received: {} for path: {}", event.getTopic(), event.getProperty("path"));
    }
}

Let me know if it works.


Santosh Sai

AEM BlogsLinkedIn


Avatar

Level 1

Thanks for your reply @SantoshSai 

 

As far as I understand, dynamic binding would keep the component (in this case, the event handler) active even if the service temporarily disappears. However, since the event handler is dependent on the service here, dynamic binding is unlikely to be helpful in this scenario.

 

Please let me know if I'm wrong or if you have any other solutions in mind.

Avatar

Community Advisor

Hi @LalithaM 

If The Event handler taking more time to execute then there are chances that it will be blacklisted, this is known behviour.

https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/monitor-alert-when-listene... 

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

 

You must use sling job/Job Manager to execute event async.

Arun Patidar

AEM LinksLinkedIn

Avatar

Administrator

@LalithaM Did you find the suggestions helpful? If you need more information, please let us know. If a response resolved your issue, kindly mark it as correct to help others in the future. Alternatively, if you discovered a solution on your own, we'd appreciate it if you could share it with the community. Thank you.



Kautuk Sahni