To achieve this, it is necessary that we listen to the workflow events in our code and perform our business logic as that event is triggered. In this post, we will see how we can achieve this using an EventHandler.
Since AEM has a rich set of APIs, we are fortunate that it has also an API through which we can listen to workflow-related events.
Steps:
Below are the steps through which we can listen to workflow events -
Step #1
Create an Event Handler (WorkflowEventsHandler, in our case) which implements the org.osgi.service.event.EventHandler interface and implement its handleEvent(Event event) method.
Step #2
Since any EventHandler needs some topic to listen to, in our case, we will provide the topic as com.day.cq.workflow.event.WorkflowEvent.EVENT_TOPIC. WorkflowEvent provides an extension of Event that is used for propagating workflow-related information as OSGI events.
Step #3
We will implement the handleEvent(Event event) method and get the event topic. We will check if the received topic is of type WorkflowEvent and if it is true then we will proceed further.
Step #4
Now, we will get the event type from the Event object. The event type gives us information about what kind of event our EventHandler has received. Since we can get multiple types of events in a workflow such as WORKFLOW_STARTED, WORKFLOW_COMPLETED, WORKFLOW_RESUMED, etc. Based on our requirements, we can implement our business logic.
Code
The complete code for this EventHandler is below -
package org.redquark.demo.core.listeners;
import java.util.HashMap;
import java.util.Map;
import javax.jcr.Session;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.osgi.framework.Constants;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.day.cq.workflow.WorkflowException;
import com.day.cq.workflow.WorkflowService;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.event.WorkflowEvent;
import com.day.cq.workflow.exec.Workflow;
import com.day.cq.workflow.exec.WorkflowData;
/**
* @author Anirudh Sharma
*
*/
@Component(service = EventHandler.class, immediate = true, property = {
Constants.SERVICE_DESCRIPTION
+ "= This event handler listens to the events that occur in the life cycle of a Workflow",
EventConstants.EVENT_TOPIC + "=" + WorkflowEvent.EVENT_TOPIC })
public class WorkflowEventsHandler implements EventHandler {
private final Logger LOG = LoggerFactory.getLogger(this.getClass());
@Reference
private ResourceResolverFactory resourceResolverFactory;
@Reference
private WorkflowService workflowService;
/**
* This method returns the workflow session
*
* @return {@link WorkflowSession}
*/
private WorkflowSession getWorkflowSession() {
try {
// Creating and getting the service user map
Map<String, Object> serviceUserMap = new HashMap<>();
serviceUserMap.put(ResourceResolverFactory.SUBSERVICE, "eventingService");
// Get the reference of ResourceResolver from the ResourceResolverFactory and
// the Service User map
ResourceResolver resourceResolver = resourceResolverFactory.getServiceResourceResolver(serviceUserMap);
// Adapting ResourceResolver to the Session object
Session session = resourceResolver.adaptTo(Session.class);
WorkflowSession workflowSession = workflowService.getWorkflowSession(session);
return workflowSession;
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
return null;
}
@Override
public void handleEvent(Event event) {
LOG.info("Received event of topic: {}", event.getTopic());
WorkflowSession workflowSession = null;
try {
// Get the workflow session
workflowSession = getWorkflowSession();
// Get the received topic
String topic = event.getTopic();
// Check if the received topic is of type Workflow event
if (topic.equals(WorkflowEvent.EVENT_TOPIC)) {
// Get the type of event
Object eventType = event.getProperty(WorkflowEvent.EVENT_TYPE);
// Check for each types of events in a workflow
if (eventType.equals(WorkflowEvent.WORKFLOW_STARTED_EVENT)) {
LOG.info("Workflow has started");
String instanceId = (String) event.getProperty(WorkflowEvent.WORKFLOW_INSTANCE_ID);
try {
// Get the reference of the Workflow object
Workflow workflow = workflowSession.getWorkflow(instanceId);
// Get the workflow data
WorkflowData workflowData = workflow.getWorkflowData();
LOG.info("Data in workflow: {}", workflowData.getPayload().toString());
} catch (WorkflowException e) {
LOG.error(e.getMessage(), e);
}
} else if (eventType.equals(WorkflowEvent.WORKFLOW_COMPLETED_EVENT)) {
LOG.info("Workflow has completed");
} else if (eventType.equals(WorkflowEvent.WORKFLOW_RESUMED_EVENT)) {
LOG.info("Workflow is resumed");
} else if (eventType.equals(WorkflowEvent.WORKFLOW_ABORTED_EVENT)) {
LOG.info("Workflow is aborted");
} else if (eventType.equals(WorkflowEvent.WORKFLOW_SUSPENDED_EVENT)) {
LOG.info("Workflow is suspended");
} else if (eventType.equals(WorkflowEvent.WORKITEM_DELEGATION_EVENT)) {
LOG.info("Workflow is delegated");
} else {
LOG.warn("Something is wrong with the workflow");
}
}
} catch (Exception e) {
LOG.error(e.getMessage(), e);
} finally {
if (workflowSession != null) {
workflowSession.getSession().logout();
}
}
}
}
Testing
For testing, the following steps can be taken -
Step #1
Choose a workflow and run it.
Step #2
You should be able to see logs getting printed as -
2020-03-01 13:25:19.407 INFO [org.redquark.demo.core.listeners.WorkflowEventsHandler] Received event of topic: com/day/cq/workflow/event
2020-03-01 13:25:19.409 INFO [org.redquark.demo.core.listeners.WorkflowEventsHandler] Workflow has started
2020-03-01 13:25:19.412 INFO [org.redquark.demo.core.listeners.WorkflowEventsHandler] Data in workflow: /content/dam/we-retail/en/activities/biking/mountain-biking.jpg
Conclusion
In this post, we saw how can we create an EventHandler and perform our business logic when our required event triggers.
You can find the code to this in my GitHub repository.
No comments:
Post a Comment
If you have any doubts or questions, please let us know.