Introduction

In AEM(CQ) 5.6 the Workflow JMX MBean support has been added in order to maintain workflow system. The Workflow is registered in the OSGi Service Registry as MBean service. This MBean is available in the JMX Console which exposes the workflow operations. There are 15 operation that can be performed that are listed under section Supported featutres. Some of the ways to monitor workflow are

  • Using user interface through Felix console
  • Using CURL
  • Creating JMX client that uses Workflow MBean

Supported features

Workflow JMX

Purge Completed Workflows

  • After a certain number of days since workflow has been completed. 
  • With an option per model after a certain number of days since workflow of the model has been completed.
  • Also can perform a Dry Run to preview a completed workflow that would be purged.

Purge Active Workflows

  • After a certain number of days since workflow has been Active. 
  • With an option per model after a certain number of days since workflow of the model has been running.
  • Also can perform a Dry Run to preview an running workflow that would be purged.

Count stale workflow

  • Return the count of stale workflows in the system.
  • With an option to return the count of stale workflows per model.

Restart stale workflow

  • All the stale workflows in the system.
  • With an option to restart all the stale workflows per model.
  • Also can perform a Dry Run to preview an stale workflow that would be restarted.

Workflow model list

  • Returns all the workflow model info with id & name in the system.

Count running workflow

  • Return the count of running workflows in the system.
  • With an option to return the count of running workflows per model.

Count completed workflow

  • Return the count of completed workflows in the system.
  • With an option to return the count of completed workflows per model.

Running Workflow model list

  • List all the workflow count per model that are running in the system.

Completed Workflow model list

  • List all the workflow count per model that are completed in the system.

Workflow queue information

  • From the time system was started retrieve information such as Jobs, Queue Name, Active jobs, Average processing time, Average waiting time, Cancelled jobs, Failed jobs, Finished jobs, Processed jobs & Queued jobs.

Workflow job topic information

  • Retrieve workflow job topic information such as Topic Name, Average processing time, Average waiting time, Cancelled jobs, Failed jobs, Finished jobs & Processed jobs

Count failed workflow

  • Return the count of failed workflows in the system.
  • With an option to return the count of failed workflows per model.

Failed Workflow model list

  • List all the workflow count per model that are failed in the system.

Failed Instances

  • Terminate all the failed workflow instances in the system.
  • With an option to terminate all the failed workflows instances per model.
  • Perform a Dry Run to preview a failed workflow instances that would be terminated.
  • Restart all the failed workflow instances in the system.
  • With an option to restart all the failed workflows instances per model.
  • Perform a Dry Run to preview a failed workflow instances that would be restarted.

Failed Workitems

  • Retry failed workitems in the system.
  • With an option to Retry all failed workitems per model in the system.
  • Perform a Dry Run to preview a failed workitems that would be retried.

Note:

Currently you can purge the workflows that are greater than a day.

Input parameters

There are 15 operations in total & some operation may have any of the following five parameters. Namely

  • model [optional] :- This is optional & the value should be the workflow model id. Ex:- /etc/workflow/models/request_for_activation/jcr:content/model 
  • number of days since workflow has been completed :- This is mandatory field for purgeCompleted operation. This should be equal or greater than one.
  • number of days since workflow started :- This is mandatory field for purgeActive operation. This should be equal or greater than one.
  • dry run :- The value can be true or false. Default is false. 
  • restart the instance :- The value can be true or false. Default is false.

Options to monitor workflow

There are three ways namely

User interface through Felix console

Using your favourite Web Browser access felix console either by

  • http://localhost:4502/system/console/jmx/com.adobe.granite.workflow:type=Maintenance OR Web console > Main > JMX > com.adobe.granite.workflow > Maintenance
  • Select any one of 15 operation you would like to execute.
  • Input the parameters & Invoke.
Purge Completed

cURL

Replace all the value between brackets with actual value. Ex:- <dryRun> with true

Purge Completed Workflows

curl -u <UID>:<PASSWORD> -X POST --data "model [optional]=<modelId>&number of days since workflow has been completed=<numberOfDays>&dry run=<dryRun>" http://<host>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/purgeCompleted/java.lang.String,java.lang.Integer,java.lang.Boolean

Ex:- The cURL command to preview all the workflow that are in request_for_activation model in a day that would be purged is

curl -u admin:admin -X POST --data "model [optional]=/etc/workflow/models/request_for_activation/jcr:content/model&number of days since workflow has been completed=1&dry run=true" http://localhost:4502/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/purgeCompleted/java.lang.String,java.lang.Integer,java.lang.Boolean

Purge Active Workflows

curl -u <UID>:<PASSWORD> -X POST --data "dry run=<dryRun>&model [optional]=<modelId>&number of days since workflow started=<numberOfDays>" http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/purgeActive/java.lang.String,java.lang.Integer,java.lang.Boolean

Count stale workflow

curl -u <UID>:<PASSWORD> -X POST --data "model [optional]=<modelId>" http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/countStaleWorkflows/java.lang.String

Restart stale workflow

curl -u <UID>:<PASSWORD> -X POST --data "dry run=<dryRun>&model [optional]=<modelId>" http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/restartStaleWorkflows/java.lang.String,java.lang.Boolean

Workflow model list

curl -u <UID>:<PASSWORD> -X POST http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/fetchModelList/

Count running workflow

curl -u <UID>:<PASSWORD> -X POST --data "model [optional]=<modelId>" http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/countRunningWorkflows/java.lang.String

Count completed workflow

curl -u <UID>:<PASSWORD> -X POST --data "model [optional]=<modelId>" http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/countCompletedWorkflows/java.lang.String

Running Workflow model list

curl -u <UID>:<PASSWORD> -X POST http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/listRunningWorkflowsPerModel/

Completed Workflow model list

curl -u <UID>:<PASSWORD> -X POST http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/listCompletedWorkflowsPerModel/

Workflow queue information

curl -u <UID>:<PASSWORD> -X POST http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/returnWorkflowQueueInfo/

Workflow job topic information

curl -u <UID>:<PASSWORD> -X POST http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/returnWorkflowJobTopicInfo/

Count failed workflow

curl -u <UID>:<PASSWORD> -X POST --data "model [optional]=<modelId>" http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/returnFailedWorkflowCount/java.lang.String

Failed Workflow model list

curl -u <UID>:<PASSWORD> -X POST http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/returnFailedWorkflowCountPerModel/

Failed Instances

curl -u <UID>:<PASSWORD> -X POST --data "dry run=<dryRun>&model [optional]=<modelId>&restart the instance=<restartInstance>" http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/terminateFailedInstances/boolean,boolean,java.lang.String

Failed Workitems

curl -u <UID>:<PASSWORD> -X POST --data "dry run=<dryRun>&model [optional]=<modelId>" http://<HOST>:<PORT>/system/console/jmx/com.adobe.granite.workflow:type=Maintenance/op/retryFailedWorkItems/boolean,java.lang.String

Creating JMX client that uses Workflow MBean

Below is Sample jmx client code that executes all the 15 workflow operations and prints the output.The input parameter are dry run, numberOfDays to 1 & for all models.

import javax.management.DynamicMBean;
import java.util.Hashtable;

import javax.management.openmbean.TabularData;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeType;


public class WorkflowJMXSampleClient {

	public static void main(String[] args) throws Exception{
		String userid = "admin";
		String password = "admin";
		String serverUrl = "service:jmx:rmi:///jndi/rmi://localhost:9000/jmxrmi";
		String OBJECT_NAME = "com.adobe.granite.workflow:type=Maintenance";
		String[] buffer = new String[] { userid, password };
		Hashtable<String, String[]> attributes = new Hashtable<String, String[]>();
		attributes.put("jmx.remote.credentials", (String[]) buffer);		
		MBeanServerConnection server = (MBeanServerConnection) JMXConnectorFactory.connect(new JMXServiceURL(serverUrl), attributes).getMBeanServerConnection();
		ObjectName name = new ObjectName(OBJECT_NAME);
		WorkflowMBean workflow = (WorkflowMBean) MBeanServerInvocationHandler.newProxyInstance(server, name, WorkflowMBean.class,false);

		/* Execute all the methods*/
		String model = "";
		Integer numberOfDays = 1 ;
		Boolean dryRun = true;
		boolean restartInstance = false;

		logTabularData("purgeCompleted",workflow.purgeCompleted( model, numberOfDays, dryRun));
		logTabularData("purgeActive",workflow.purgeActive( model,  numberOfDays,  dryRun));
		logCount("countStaleWorkflows",workflow.countStaleWorkflows( model));
		logTabularData("restartStaleWorkflows",workflow.restartStaleWorkflows( model, dryRun) );
		logTabularData("fetchModelList",workflow.fetchModelList() );
		logCount("countRunningWorkflows",workflow.countRunningWorkflows( model) );
		logCount("countCompletedWorkflows",workflow.countCompletedWorkflows( model) );
		logTabularData("listRunningWorkflowsPerModel",workflow.listRunningWorkflowsPerModel() );
		logTabularData("listCompletedWorkflowsPerModel",workflow.listCompletedWorkflowsPerModel() );
		logTabularData("returnWorkflowQueueInfo",workflow.returnWorkflowQueueInfo() );
		logTabularData("returnWorkflowJobTopicInfo",workflow.returnWorkflowJobTopicInfo() );
		logCount("returnFailedWorkflowCount",workflow.returnFailedWorkflowCount( model) );
		logTabularData("returnFailedWorkflowCountPerModel",workflow.returnFailedWorkflowCountPerModel() );
		logTabularData("terminateFailedInstances",workflow.terminateFailedInstances( restartInstance, dryRun, model) );
		logTabularData("retryFailedWorkItems",workflow.retryFailedWorkItems( dryRun, model)); 
		
	}
	
	public static void logTabularData(String operation, TabularData data) {
		System.out.println("-----Operation "+operation+"--------------");
		try {
			System.out.println("Number of records "+data.size());
			int counter = 0;
			for (Object o : data.values()) {
				System.out.println("Record Number "+(++counter));
				CompositeData row = (CompositeData) o;
			    CompositeType type = row.getCompositeType();
			    	for (Object k : type.keySet()) {
			    		String key = k.toString();
						System.out.println(key + " -- "+ row.get(key));
			    }
			}
		} catch (Exception e) {
			System.out.println("-----Error during operation "+operation+"--------------"+e.getMessage());		
		}
		System.out.println("-----Completed "+operation+"--------------");		
		System.out.println("       ");		

	}

	public static void logCount(String operation, int counter) {
		System.out.println("--------------"+operation+"--------------");
		try {
			System.out.println("count is "+counter);
		} catch (Exception e) {
			System.out.println("-----Error during operation "+operation+"--------------"+e.getMessage());		
		}
		System.out.println("-----Completed "+operation+"--------------");		
		System.out.println("       ");		
	}
	
	public static interface WorkflowMBean extends DynamicMBean {
		public TabularData purgeCompleted(String model,Integer numberOfDays,Boolean dryRun);
		public TabularData purgeActive(String model, Integer numberOfDays, Boolean dryRun);
		public int countStaleWorkflows(String model);
		public TabularData restartStaleWorkflows(String model,Boolean dryRun) ;
		public TabularData fetchModelList() ;
		public int countRunningWorkflows(String model) ;
		public int countCompletedWorkflows(String model) ;
		public TabularData listRunningWorkflowsPerModel() ;
		public TabularData listCompletedWorkflowsPerModel() ;
		public TabularData returnWorkflowQueueInfo() ;
		public TabularData returnWorkflowJobTopicInfo() ;
		public int returnFailedWorkflowCount(String model) ;
		public TabularData returnFailedWorkflowCountPerModel() ;
		public TabularData terminateFailedInstances(boolean restartInstance,boolean dryRun,String model) ;
		public TabularData retryFailedWorkItems(boolean dryRun,String model); 
    }
}

Video

Note:

If trouble playing video watch from you tube at http://youtu.be/aXQgd-Vuqzg

Video on Monitoring Workflow via JMX

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License  Twitter™ and Facebook posts are not covered under the terms of Creative Commons.

Legal Notices   |   Online Privacy Policy