Plugin API - Overview

The Imixs Plugin API is a powerful concept to extend the Imixs Workflow Engine with the technical aspects of a workflow management system. A plugin can provide platform specific functionality to be executed during a workflow process. You can find a general overview about the plugin concepts here.

The Imixs Workflow Engine provides a set of plugins with different workflow functionality like email notification, access control, versioning or process documentation. You can extend plugin classes to implement additional behavior for your own project.

The Abstract JEE Workflow Plugin

Most Imixs Plugins extend from the AbstractPlugin class. This class provides a set of methods to be used by a plugin. If you like to implement your own Imixs Plugin it is a good starting point to subclass the class:

  org.imixs.workflow.jee.plugins.AbstractPlugin

This abstract class implements a basic set of methods to simplify implementing Java EE specific functionality. The plugin provides the following methods:

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 plugin 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.jee.ejb.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.jee.util.PropertyService</remote>
            </ejb-ref>
    ....
    </session>
... 

How to access the WorkflowService EJB from a Plugin

Implementing a Imixs Workflow Plugin is an easy way to extend the behavior of the Workflow Management System. A plugin is a simple Java Class (POJO) which makes it easy to implement.

The WorkflowKernel provides a plugin with informations about the environment the plugin runs in. Each plugin class gets an instance of the interface WorkflowContext during the initialization of the plugin. This interface represents the context the plugin currently runs in. The context depends on the concrete WorkflowManager implementation which is calling a plugin to process a workitem.

If a plugin runs in the Imixs JEE 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 plugin.

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 latest model version....
                String slw=ws.getModelService().getLatestVersion();
                .....
        }
}

Before you cast the WorkflowContext to the interface org.imixs.workflow.jee.ejb.WorkflowSerice you should make sure that your plugin runs in an instance of the Imixs WorkflowService EJB. This can be done with a simple test:

        if (actx instanceof WorkflowService) 
          .....

How to lookup a EJB from a Plugin

Because of the fact that a Imixs Workflow plugin is independend from the Workflow implementation you can not directly make use of the injection Feature from EJB 3.0 even if you plugin runs in the Imixs JEE Workflow. This is because the Plugin Class is typical not part of the Servlet Context nor it is implemented as a Session EJB. For that reason it is not possible to inject an Session EJB with an annotation like it is typical done in EJB 3.0:

@EJB
        org.imixs.workflow.jee.ejb.EntityService entityService;

To get a reference to a existing EJB in your Plugin Class, you can do a JNDI Lookup. The JNDI Lookup fetches the EJB from the EJB Container provided by the JEE Appliction Server. So this is the typical way to get an EJB Instance inside a POJO Class. The following example shows how you can lookup an EJB during the init() method of a plugin:

public void init(WorkflowContext actx) throws Exception {
        super.init(actx);

        String jndiName="java:comp/env/ejb/MyService";
        InitialContext ictx = new InitialContext();
        Context ctx = (Context) ictx.lookup("java:comp/env"); 
        jndiName="ejb/MyServiceBean";
        myService= (org.foo.ejb.MyService)ctx.lookup(jndiName);
}

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 you need to add this reference to the WorkflowManager EJB which is calling the Plugin. So you need to extend the ejb definition of the WorkflowServiceBean in the ejb-jar.xml file:

        <session>
                <ejb-name>WorkflowServiceBean</ejb-name>
                <ejb-class>org.imixs.workflow.jee.ejb.WorkflowServiceBean</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 Ressource from a Plugin

Similar to a EJB JNDI Lookup a Plugin class can also lookup an existing JDBC Ressource to query a database using SQL statements. The same principle explaind 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 Plugin 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>WorkflowServiceBean</ejb-name>
                <ejb-class>org.imixs.workflow.jee.ejb.WorkflowServiceBean</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>WorkflowServiceBean</ejb-name>
                <jndi-name> ejb/MyWorkflowServiceBean</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.

PluginStack

The WorkflowKernel defines a so-called PluginStack when forwarding a WorkItem to a plug-in. The PluginStack provides information about the current processing state of the WorkItem in relation to the plug-in.

The stack is organized as follows:

 Itemname=$PluginStack
 Itemvalue=Pluginname|ProcessStartTime|ProcessEndTime

Example:

 org.foo.MyPlugin | 1/1/04 03:30 AM:30| 1/1/04 03:30 AM:31;
 org.foo.SimplePlugin | 1/1/04 03:30 AM:31| 1/1/04 03:30 AM:32;