Plug-in API - Overview

The Imixs Plug-in API is an extension concept provided by the Imixs-Workflow Engine. The business logic of an application as also technical interfaces can be implemented by plug-ins which can easily be activated through the workflow model. Read more about plug-in concept in the section Core API.

The Imixs-Workflow Engine provides a set of plug-ins providing different workflow functionality like email notification, access control, versioning or process documentation.

The Abstract Plug-in Class

Most plug-ins provided by the Imixs-Workflow engine are extending the AbstractPlugin class. This class provides a set of convenient methods to access the Imixs-Worklfow environment and processing logic. For custom implementation this is a good starting point to subclass from the class:

org.imixs.workflow.engine.plugins.AbstractPlugin

This abstract Plug-in class provides the following methods:

  • getWorklfowService - returns an instance of the Worklfow Engine
  • replaceDynamicValues - replacing string values
  • formatItemValues - formats a string object depending of an attribute type
  • getCtx - returns the current workflow context

Replacing static Strings with workitem values

The AbstractPlugin provides a method to replace a static string with properties provided by the processed workitem. This is useful if you need a string constant to be updated with values from your workitem. For example if you look at the MailPlugin which sends messages, the property ‘rtfMailBody’ provides the mail message text. This static message text can be automatically replaced with the values ​​from the current wokitem if the tag “itemvalue” is used.

For example the message text

 The invoice was generated by <itemValue>namcreator</itemValue> 
 at <itemValue format="EEE, MMM d, yyyy">$created</itemvalue>

will be replaced with the workitem properties ‘namcreator’ and ‘$created’ into:

 The invoice was generated by Ralph 
 at Wed, Jul 4, 2010

The attribute ‘format’ can be used to format a date/time value.

Format multi-value lists

If a workitem value contains multi-values list you can also use the attribute ‘separator’ to separate single values. For example the message text

The following item has been ordered: <itemValue separator=", ">_parts</itemValue>

will be replaced with:

The following item has been ordered: pants, shirt, jacket

Format date values by locale

To format a date value in language specific format you can use the ‘locale’ attribute to define the preferred locale. See the following example to format a date value in german format:

 The Date in german format is: <itemvalue format=\"EEEE, d. MMMM yyyy\" locale=\"de_DE\">datdate</itemvalue>.";

Replacing static Strings with properties values

In addition to the possibility replacing text blocks with workitem values​​, the Plug-in also provides the ability to replace text blocks with values stored in the imixs.property file. A static message text will be automatically replaced with the values ​​from the imixs.property file if the tag “propertyvalue” is used.

Please use the following Link to open the Application: 
<propertyValue>dbRootURL</propertyvalue>

The values from the imixs.prperties file are accessed by the PropertyService. To activate this feature it is necessary that a ‘ejb-ref’ is defined for the Imixs WorkflowService EJB. See the following example from the ejb-jar.xml file:

... 
    <session>
         <ejb-name>WorkflowService</ejb-name>
         <ejb-class>org.imixs.workflow.engine.WorkflowService</ejb-class>
         <session-type>Stateless</session-type>
           <ejb-ref>
                    <ejb-ref-name>ejb/PropertyService</ejb-ref-name>
                    <ejb-ref-type>Session</ejb-ref-type>
                    <remote>org.imixs.workflow.engine.PropertyService</remote>
            </ejb-ref>
    ....
    </session>
... 

How to access the WorkflowService EJB from a Plug-in

Implementing a Imixs-Workflow Plug-in is an easy way to extend the behavior of the Imixs-Workflow engine. A plug-in is a simple Java Class (POJO) which makes it easy to implement. The WorkflowKernel provides a plug-in with informations about the environment the plug-in runs in. Each Plug-in class gets an instance of the interface WorkflowContext during the initialization of the plug-in. This interface represents the context the Plug-in currently runs in. The context depends on the concrete WorkflowManager implementation which is calling a plug-in to process a workitem.

If a plug-in runs in the Imixs-Workflow Engine, the WorkflowContext is an instance of the WorkflowService EJB. This behavior makes it easy to access the functionality provided by the WorkflowEngine directly through a Plug-in. The following example shows how to access the WorkflowService and ModelService EJBs to determine the latest model version used in the WorkflowInstance:

public void init(WorkflowContext actx) throws Exception {
    super.init(actx);
    // check for an instance of WorkflowService
    if (actx instanceof WorkflowService) {
       // yes we are running in a WorkflowService EJB
       WorkflowService ws=(WorkflowService)actx;
       // get the model service....
       ModelService modelService=ws.getModelService();
       List<String> versions = modelService.getVersions();
       .....
    }
}

CDI Support

Imixs-Workflow supports CDI for the plug-in API. So an EJB or Resource can be injected into a Plug-in class by the corresponding annotation. See the following example:

public class DemoPlugin extends AbstractPlugin {
    // inject services...
    @EJB
    ModelService modelService;
    ...
}

How to lookup a EJB from a Plug-in

An alternative way to get a reference to an existing EJB in a Plug-in Class, is to use a JNDI Lookup. The JNDI Lookup fetches the EJB from the EJB Container provided by the application server. So this way it is possible to get an EJB Instance inside a POJO Class without CDI support. The following example shows how to lookup an EJB during the init() method of a Plug-in:

@Override
public void init(WorkflowContext actx) throws PluginException {
    super.init(actx);

    try {
       InitialContext ictx = new InitialContext();
       Context ctx = (Context) ictx.lookup("java:comp/env");
       myService = (MyService) ctx.lookup("ejb/MyServiceBean");
    } catch (NamingException e) {
       throw new PluginException(this.getClass().getName(), "JNDI_LOOKUP_ERROR", e.getMessage());
    }
}

In this case a reference to the MyService Interface was created by JNDI Lookup. The Lookup fetches an EJB Reference with the name “ejb/MyServiceBean”. To get this Interface returned from the JNDI Context it is necessary to add this reference to the WorkflowService EJB which is calling the Plug-in. This can be done in the ejb-jar.xml file:

    <session>
       <ejb-name>WorkflowService</ejb-name>
       <ejb-class>org.imixs.workflow.engine.WorkflowService</ejb-class>
       <session-type>Stateless</session-type>
       <ejb-ref>
           <ejb-ref-name>ejb/MyServiceBean</ejb-ref-name>
           <ejb-ref-type>Session</ejb-ref-type>
           <remote>org.foo.ejb.MyService</remote>
       </ejb-ref>
    </session>

How to lookup a JDBC Resource from a Plug-in

Similar to a EJB JNDI Lookup a Plug-in class can also lookup an existing JDBC Resource to query a database using SQL statements. The same principle explained in this section is applicable to all resources (such as JMS destinations, JavaMail sessions, and so on). The resource-ref element in the sun-ejb-jar.xml deployment descriptor file maps the JNDI name of a resource reference to the resource-ref element in the ejb-jar.xml J2EE deployment descriptor file. This is similar to a EJB lookup explained before. The resource lookup in the Plug-in code looks like this:

    public void init(WorkflowContext actx) throws Exception {
       super.init(actx);
       InitialContext ic = new InitialContext();
       String dsName = "java:comp/env/jdbc/HelloDbDs";
       DataSource ds = (javax.sql.DataSource)ic.lookup(dsName);
       Connection connection = ds.getConnection();
       ....
       .....
    }

The resource being queried is listed in the res-ref-name element of the ejb-jar.xml file as follows:

   ....
    <session>
       <ejb-name>WorkflowService</ejb-name>
       <ejb-class>org.imixs.workflow.engine.WorkflowService</ejb-class>
       <session-type>Stateless</session-type>

       <!-- JDBC ressource -->
       <resource-ref>
         <res-ref-name>jdbc/HelloDbDs</res-ref-name>
         <res-type>javax.sql.DataSource</res-type>
         <res-auth>Container</res-auth>
       </resource-ref>

    </session>
    ....

The resource-ref section in a Sun Java System specific deployment descriptor, for example sun-ejb-jar.xml, maps the res-ref-name (the name being queried in the application code) to the JNDI name of the JDBC resource. The JNDI name is the same as the name of the JDBC resource as defined in the resource file when the resource is created.

   ....
    <ejb>
       <ejb-name>WorkflowService</ejb-name>
       <jndi-name>ejb/WorkflowService</jndi-name>
       <!-- JDBC ressource -->
       <resource-ref>
                <res-ref-name>jdbc/HelloDbDs</res-ref-name>
          <jndi-name>jdbc/HelloDbDs</jndi-name>
       </resource-ref>
    </ejb>
    .....

The JNDI name in the Sun Java System specific deployment descriptor must match the JNDI name you assigned to the resource when you created and configured it.