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.");
}
}
}
}
Views
Replies
Total Likes
Hi @LalithaM,
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.
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.
Views
Replies
Total Likes
Hi @LalithaM
If The Event handler taking more time to execute then there are chances that it will be blacklisted, this is known behviour.
You must use sling job/Job Manager to execute event async.
@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.
Views
Replies
Total Likes
Views
Likes
Replies
Views
Likes
Replies
Views
Likes
Replies
Views
Likes
Replies