Agent

Process provides a system to plan the tasks execution. It is the “Agent” classes. These agent classes are very simple Java classes that can be planned from the administration.

Write a non stoppable agent

To create an agent, you just have to create a class that branch off BaseAgent (the RunnableAgent class is then obsolete). By branching off the class BaseAgent, you have to implement the execute() method.

The class com.axemble.vdoc.sdk.agent.base.BaseAgent is the class of any agent inside the Process system. By branching off this base class, your class will automatically be known as agent and may be planned or manually executed via the administration interface. This agent class gives direct access to the APIs. It permits also to register information or error messages in the agent execution log.

Methods of the BaseAgent class:

public abstract class BaseAgent extends ...

// method to implement
protected abstract void execute();

// helper methods

final protected IWorkflowModule getWorkflowModule()

final protected void printInfo( String message )

final protected void printError( String message )

final protected void printSeparator()

final protected void printLine()

Code extract of the LogAgent class (the following code recovers every document of an application and registers their reference and title in the agent execution log):

public class LogAgent extends BaseAgent {
    public void execute() {
        IContext processContext = getWorkflowModule().getContextByLogin("sysadmin");
        ICatalog catalog = getWorkflowModule().getCatalog(processContext, "Education");
		// recover an external reference (you must define it)!
        IJdbcReference jdbcReference = getWorkflowModule().getJdbcReference(processContext, "vdocDatabase");
		// recover a controller to perform searches
        ISearchController searchController = getWorkflowModule().getSearchController(jdbcReference);
		// recover all the documents
        this.printSeparator();
        this.printInfo("Recovering all documents of the specified database");
        this.printSeparator();
        this.printLine();
        Collection worflowInstances = searchController.findElements( IWorkflowInstance.class, "select id from vdp_treatments where ref_catalog=?", new Object[] { catalog.getId().toString() } );
        for (Iterator iter = worflowInstances.iterator(); iter.hasNext(); ) {
            IWorkflowInstance workflowInstance = (IWorkflowInstance) iter.next();
            this.printInfo("REFERENCE : " + (String) workflowInstance.getValue("sys_Reference"));
            this.printInfo("TITLE : " + (String) workflowInstance.getValue("sys_Title"));
            this.printInfo("IDENTIFIER : " + workflowInstance.getId().toString());
            this.printLine();
        }
        this.printInfo("Operation ended successfully");
        this.printSeparator();
    }
}

To create an agent, you just have to create a class that branch off BaseAgent (the RunnableAgent class is then obsolete). By branching off the class BaseAgent, you have to implement the execute() method.

The class com.axemble.vdoc.sdk.agent.base.BaseAgent is the class of any agent inside the Process system. By branching off this base class, your class will automatically be known as agent and may be planned or manually executed via the administration interface. This agent class gives direct access to the APIs. It permits also to register information or error messages in the agent execution log.

Methods of the BaseAgent class:

public abstract class BaseAgent extends ...

// method to implement
protected abstract void execute();

// helper methods

final protected IWorkflowModule getWorkflowModule()

final protected void printInfo( String message )

final protected void printError( String message )

final protected void printSeparator()

final protected void printLine()

Code extract of the LogAgent class (the following code recovers every document of an application and registers their reference and title in the agent execution log):

public class LogAgent extends BaseAgent {
    public void execute() {
        IContext processContext = getWorkflowModule().getContextByLogin("sysadmin");
        ICatalog catalog = getWorkflowModule().getCatalog(processContext, "Education");
		// recover an external reference (you must define it)!
        IJdbcReference jdbcReference = getWorkflowModule().getJdbcReference(processContext, "vdocDatabase");
		// recover a controller to perform searches
        ISearchController searchController = getWorkflowModule().getSearchController(jdbcReference);
		// recover all the documents
        this.printSeparator();
        this.printInfo("Recovering all documents of the specified database");
        this.printSeparator();
        this.printLine();
        Collection worflowInstances = searchController.findElements( IWorkflowInstance.class, "select id from vdp_treatments where ref_catalog=?", new Object[] { catalog.getId().toString() } );
        for (Iterator iter = worflowInstances.iterator(); iter.hasNext(); ) {
            IWorkflowInstance workflowInstance = (IWorkflowInstance) iter.next();
            this.printInfo("REFERENCE : " + (String) workflowInstance.getValue("sys_Reference"));
            this.printInfo("TITLE : " + (String) workflowInstance.getValue("sys_Title"));
            this.printInfo("IDENTIFIER : " + workflowInstance.getId().toString());
            this.printLine();
        }
        this.printInfo("Operation ended successfully");
        this.printSeparator();
    }
}

Since Process18.0.0, the agent models have been modified to make them stoppable. For this, 2 new interfaces have been created “IStoppableAgentProcessing” and “IAgentProcessing”. The previous base class (“BaseAgent”) has been deprecated and will be removed in a future release.

The new interfaces impose an execute method that carries the execution context (“IAgentProcessingContext”) as a parameter.

This context allows to retrieve the different modules, the agent and its configuration, as well as the execution report.

Implementing the “IAgentProcessing” interface allows to write a classic non-stoppable agent. The stop button will not appear in the administration of this agent.

Example :

package ...;

import com.axemble.vdoc.sdk.interfaces.IAgentProcessing;
import com.axemble.vdoc.sdk.interfaces.IAgentProcessingContext;

public class NonStoppableAgent implements IAgentProcessing
{
	
	@Override
	public void execute(IAgentProcessingContext executionContext)
	{
		long t = System.currentTimeMillis();
		long end = t + 11000;
		int sec = 0;
		while (System.currentTimeMillis() < end) {
			if (System.currentTimeMillis() > t + 1000 * (sec + 1)) {
			    // Do some work
			    executionContext.getReport().addInfo("I do my job");
				sec += 1;
			}
		}
	}
}

Write a stoppable agent

Since Process18.0.0

The agent models have been modified to make them stoppable. For this, 2 new interfaces have been created “IStoppableAgentProcessing” and “IAgentProcessing”. The previous base class (“BaseAgent”) has been deprecated and will be removed in a future release.

The new interfaces impose an execute method that carries the execution context (“IAgentProcessingContext”) as a parameter.

This context allows to retrieve the different modules, the agent and its configuration, as well as the execution report.

The “IStoppableAgentProcessing” interface allows to display a stop button in the agent’s administration. The agent’s implementation is responsible for regularly checking the IAgentProcessingContext.isAbortSignalReceived() return value and stop his treatment in case of true.

A stoppable agent, when it stops, is responsible for properly closing the resources it is using (database connection, etc…)

Example :

package ...;

import com.axemble.vdoc.sdk.interfaces.IAgentProcessingContext;
import com.axemble.vdoc.sdk.interfaces.IStoppableAgentProcessing;

public class AgentStoppable implements IStoppableAgentProcessing
{
	
	@Override
	public void execute(IAgentProcessingContext executionContext)
	{
		long t = System.currentTimeMillis();
		long end = t + 11000;
		int sec = 0;
		while (System.currentTimeMillis() < end) {
			if (System.currentTimeMillis() > t + 1000 * (sec + 1)) {
			    // Do some work
			    executionContext.getReport().addInfo("I do my job");
				if (executionContext.isAbortSignalReceived()) {
				    // A request to stop was sent to me. So I stop my treatment.
				    executionContext.getReport().addError("I was asked to stop. So I stop my treatment.");
					throw new IllegalStateException();
					break;
				}
				sec += 1;
			}
		}
	}
}

Managing transactions

The agents are executed, by default, in a non-transactional context. If you want to process treatments inside a transaction, you should use the methods beginTransaction, commitTransaction and rollbackTransaction of the IWorkflowModule module.

Code extract using transactions

The following code shows the implementation of a transaction inside the workflow module:

try {
	// starting a transaction getWorkflowModule().beginTransaction( this ); ...
	// validating the transaction getWorkflowModule().commitTransaction( this );
} catch( Exception e ) {
	// in case of exception, cancel the treatment getWorkflowModule().rollbackTransaction( this );
}

Running the agents by programming

From the Process APIs, it is possible to trigger the processing of an agent defined in the Process management.

Example of executing an agent by API

This code extract enables to show how to retrieve an agent by its name and execute it:

// retrieving an agent by its name
IAgent agent = getWorkflowModule().getAgent( getWorkflowModule().getLoggedOnUserContext(), "Name of the agent" );
// executing the retrieved agent
getWorkflowModule().execute( agent );

Running a packaging class from an agent

This code shows how to execute a packaging class from an agent:

@Override
protected void execute() {
	IPortalModule pmodule = Modules.getPortalModule();
	Map<String, String> parameters = new HashMap<>();
	//parameters = null;

	parameters.put( "login", "dummy1" );
	parameters.put( "password", "manager" );
	parameters.put( "name", "dummy" );
	parameters.put( "firstname", "user" );

	try {
		pmodule.executeTask( com.axemble.vdoc.workflow.extension.TestPackaginExtension.class, parameters );
	} catch( PortalModuleException e ) {
		// TODO Auto-generated catch block
		throw new VDocException( e.getMessage() );
	}
}