Using Java to start/stop workflow in Maximo

Sometimes you may need to start a workflow automatically but the standard functionality of escalation is not satisfying the needs of business logic.
For such situations you can use a cron task to search the records and system service WorkFlowService to start a workflow.

For instance, we need to start a workflow (process name PMWF) for periodical maintenance record (custom mbo PMCUST) when there comes a time specified in PLANNEDYEAR, PLANNEDWEEK attributes.
Here is an example of the cron task:

package custom.app.permaint.workflow;

import java.rmi.RemoteException;
import java.util.Calendar;
import psdi.mbo.MboConstants;
import psdi.mbo.MboRemote;
import psdi.mbo.MboSetRemote;
import psdi.server.MXServer;
import psdi.server.SimpleCronTask;
import psdi.util.MXException;
import psdi.util.logging.MXLogger;
import psdi.util.logging.MXLoggerFactory;
import psdi.workflow.WorkFlowServiceRemote;

public class PerMaintScheduleWFCron extends SimpleCronTask implements MboConstants {

    MXLogger logger;
    public static final String APPLOGGER = "maximo.custom.app.permaint";
    
    public PerMaintScheduleWFCron() {
        logger = MXLoggerFactory.getLogger(APPLOGGER);
    }

    @Override
    public void cronAction() {
        try {
            Calendar now = Calendar.getInstance();
            int thisyear = now.get(Calendar.YEAR);
            int thisweek = now.get(Calendar.WEEK_OF_YEAR);
            // get PMCUST mbo set
            MboSetRemote pmSet = MXServer.getMXServer().getMboSet("PMCUST", getRunasUserInfo());
            // filter mbo set according to conditions of starting workflow
            pmSet.setWhere("historyflag=0 and plannedyear=" + thisyear + " and plannedweek< =" + thisweek + "+1)");
            pmSet.reset();
            for (MboRemote pm = pmSet.moveFirst(); pm != null; pm = pmSet.moveNext()) {
                WorkFlowServiceRemote wfs = (WorkFlowServiceRemote) MXServer.getMXServer().lookup("WORKFLOW");
                wfs.initiateWorkflow("PMWF", pm); // PMWF is the name of the workflow process
            }
        } catch (RemoteException e) {
            logger.error("PerMaintScheduleWFCron", e);
        } catch (MXException e) {
            logger.error("PerMaintScheduleWFCron", e);
        } catch (RuntimeException e) {
            logger.error("PerMaintScheduleWFCron", e);
        }
    }
}

If you need to stop a workflow in java code, first you should get the workflow instance.
It is possible using the “&WFINSTANCE&” virtual relationship that is created when workflow is initializing.
Since the relationship exists only while workflow is running, you need to be aware of the “norelationship” exception.

Here is the approach:

WFInstanceRemote wfinst = null;
try {
    if (mbo.getMboSet("&WFINSTANCE&").getMbo(0) != null) {
        wfinst = (WFInstance) mbo.getMboSet("&WFINSTANCE&").getMbo(0);
    }
} catch (MXSystemException e) {
    if (e.getErrorKey().equals("norelationship")) {
    } else {
        throw e;
    }
}
if (wfinst != null) {
    wfinst.stopWorkflow("Cancel order"); // "Cancel order" is a memo of the transaction
}