I want to trigger listener which which further sends email whenever any async job is completed on AEM Cloud.
But whatever event I am trying is not hitting the listener
org/apache/sling/event/notification/job/FINISHED Or
com/adobe/granite/async/job/SUCCEEDED.
or I have the 2nd approach where I can check /var/asyncjobs where if any new node creates I can trigger listener but in that node I see no property to differentiate between jobs( like I only want for asset
import or zip unarchive).
can someone please help here.
Topics help categorize Community content and increase your ability to discover relevant content.
Views
Replies
Total Likes
Hello @RinkiShahi
You may also consider :
For OOTB Async Jobs, AEMaaCS already sends Inbox and Email notifications (if configured) when any built‑in asynchronous job finishes.
You can do so by setting emailEnabled to 'true' in respective OSGi Configurations
Views
Replies
Total Likes
Thanks Muskann for replying,
I know about email notification for async jobs but that only goes to admins.
And that is why I need this listener to send to a specific group.
And when I used org/apache/sling/event/notification/job/FINISHED, the listener triggered email but for other jobs not for my async job. It did not print the logger which was first line in the handle event method.
@component(
service = EventHandler.class,
immediate = true,
property = {
EventConstants.EVENT_TOPIC + "=org/apache/sling/event/notification/job/FINISHED"
}
)
public class AssetUploadListener implements EventHandler {
private static final Logger log = LoggerFactory.getLogger(AssetUploadListener.class);
private static final String EMAIL_TEMPLATE= "/etc/notification/email/brandportal-asset-import-notification.html";
private static final String LIBRARIAN_GROUP= "asset-manager-dam-librarian";
private static final String UNKNOWN= "Unknown";
@reference
private EmailSenderService emailSenderService;
@reference
private ResourceResolverFactory resolverFactory;
private boolean enableListener;
@Override
public void handleEvent(Event event) {
String[] propertyNames = event.getPropertyNames();
for (String key : propertyNames) {
log.info("Event property: {} = {}", key, event.getProperty(key));
}
String jobStatus = (String) event.getProperty("job.status");
String jobTitle = (String) event.getProperty("job.title");
String jobDescription = (String) event.getProperty("job.description");
log.info("Async Job Event -> Status: {}, Title: {}, Description: {}", jobStatus, jobTitle, jobDescription);
// Flexible condition for UNZIP jobs
log.info("UNZIP job completed successfully for folder: {}", jobDescription);
try (ResourceResolver resolver = resolverFactory.getServiceResourceResolver(
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, "emailService"))) {
// For testing, hardcoded email
List<String> emailIds = Collections.singletonList("rinki.shahi@aaaa.com");
if (!emailIds.isEmpty()) {
Map<String, String> emailParams = new HashMap<>();
emailParams.put("brandName", extractBrandName(jobDescription));
emailParams.put("brandFolderPath", jobDescription != null ? jobDescription : UNKNOWN);
emailParams.put("subject", "UNZIP Job Success");
emailSenderService.sendEmailWithAttachment(EMAIL_TEMPLATE, emailParams, Collections.emptyMap(), resolver, emailIds.toArray(new String[0]));
log.info("Email sent successfully to {}", emailIds);
} else {
log.warn("No email recipients found in group: {}", LIBRARIAN_GROUP);
}
} catch (Exception e) {
log.error("Failed to send UNZIP job notification email", e);
}
}
Views
Replies
Total Likes
Hi @RinkiShahi
Here is my 2 cents.
Why not listen at the overall async job level
The async job framework (com.adobe.granite.async) in AEM Cloud aggregates tasks from multiple domains — asset ingestion, unarchiving, launch copy, metadata extraction, etc.
If you hook at the global level (e.g. com/adobe/granite/async/job/SUCCEEDED or under /var/asyncjobs), you’ll only get coarse “job completed” events with no context on what triggered them — no asset ID, user, or business intent. That makes it impossible to tailor messaging because the payload and semantics differ per job type.
Recommended pattern
Use domain‑specific completion listeners registered at the level where the job’s outcome is meaningful. For instance:
Views
Likes
Replies