A prototype play! plugin for activiti integration

Nowadays, i am back on play! trying to do things with somewhat less-documented feature of plugins. There is a project on the horizon which needs tight integration with a BPM engine, namely activiti, so i thought it’s a good time to try and deal with it as a play plugin or play module.

I said “plugin or module” deliberately, because i wasn’t aware of a plugin system other than the module system, which is basically described as just another play application. Actually i was wondering how it was possible to inject guice or spring dependencies into my application using just-another-application. Then i found out about the file play.plugins and saw that it was not magic at all (ability to code scala is still magic though).

I am also new to activiti and BPM, but i’ll try to explain what i made of it, at least the part that interested me. It is an application that uses a database to store some process definitions and ongoing processes, while executing everything according to the definition. Processes may be defined with a language called BPMN 2.0 which supposedly can be written by business-people so we shouldn’t care about the complexity or validity of them! We register these definitions into activiti which in turn may be instantiated into process instances using a Java API. Then, we may monitor and/or act on those instances using the same API. Activiti also provides a REST API which is marked as experimental so i didn’t touch it. Simple enough.

I still am not sure how will i use it in my future project but there is a point which will be needed anyway so i tried to cover that in this primitive plugin: initializing activiti. This means getting the hold of a ProcessEngine instance.

A play module may put any classpath dependency in its lib/ directory but its not created with $ play new-module. I mkdired it first and copied activiti related jars here. Activiti itself comes in a single jar named activiti-engine and this was the first jar to be copied. Because it has been developed using spring, it requires some spring jars to be on the classpath. It is possible to get them using spring module but i wasn’t sure if it works with 1.1 or is compatible with what activiti requires. I simply copied spring-core, spring-beans and spring-asm. It uses MyBatis to access the required database so its jar is to be included too. The last state of lib is like

  • activiti-engine-5.0.jar
  • mybatis-3.0.1.jar
  • spring-asm-3.0.3.RELEASE.jar
  • spring-beans-3.0.3.RELEASE.jar
  • spring-core-3.0.3.RELEASE.jar

$ play new-module created some unnecessary directories [for this example] like app/ and conf/ so i removed them before starting anything.

Activiti documentation states that ProcessEngine is thread-safe and it will be OK to initialize and destroy it upon container boot and shutdown. It gives an example for plain Servlet environments which seems easy to translate to a play plugin.

A play plugin is a class that extends PlayPlugin which is able to modify just about everything framework does, by overriding the methods. In order to function, it needs to have a default constructor and has to be enabled by a play.plugins file which should be somewhere in the root of the classpath. $ play new-module creates such a file in src/ so i edited it to put my plugin classname.

1100:play.modules.activiti.ActivitiPlugin

The number before the colon defines the priority of the plugin which simply defines the order that plugins are run. I’ll explain why i picked 1100 shortly. The class is as simple as it gets.

package play.modules.activiti;

import org.activiti.engine.ProcessEngines;
import play.PlayPlugin;

public class ActivitiPlugin extends PlayPlugin {
  @Override
  public void onApplicationStart() {
    ProcessEngines.init();
  }     
  @Override
  public void onApplicationStop() {
    ProcessEngines.destroy();
  }     
}

We have successfully initialized our ProcessEngines per activiti documentation. But it is obvious that this is less than useful. We should find a way to get a ProcessEngine instance in our controllers. I don’t know if it’s OK here but i am a huge fan of dependency injection so i would love to be able to just @Inject it. I knew that there is a @javax.inject.Inject support in play but i had to peek at the source code of guice module to figure out how to make it work. It turned out to be the simplest modification ever.

public class ActivitiPlugin extends PlayPlugin implements BeanSource {
  @Override
  public void onApplicationStart() {
    ProcessEngines.init();
    Injector.inject(this);
  }     
  @Override
  public  T getBeanOfType(Class clazz) {
    if (clazz.equals(ProcessEngine.class))
      return (T) ProcessEngines.getDefaultProcessEngine();
    return null;
  }     
  //...   
}

The Injector.inject() in second line crawles our classes for @Inject annotated static fields and applies getBeanOfType() method to its type when it finds one. And my methods gives the ProcessEngine instance if the type of the field is actually a ProcessEngine. Now it is possible to get it in any controller, mailer or job

public class Application extends Controller {
  @Inject
  static ProcessEngine pe;

  public static void index() {
    List pdl = pe.getRepositoryService()
      .createProcessDefinitionQuery().list();
    render(pdl);
  }     
}

That example gets the list of registered (deployed) process definitions. After getting that ProcessEngine, rest is details about how you want to use it which i will figure out after getting into the project.

On that priority 1100; since i am utilizing @Inject here, there is a huge possibility that guice or spring plugin will interfere. Both of the plugins’ priorities are 1000 so activiti plugin will be loaded after them and overwrite anything that has been injected by them. I am still not sure about this whole mechanism and i feel i’ll probably be forced to depend on spring plugin sooner or later.

For the completeness of the example, just in case anyone wants to work with it, there is one more step. Activiti offers you the easy way of defining your activiti database in a configuration file named activiti.cfg.xml. You should obtain one from the documentation and modify it under your conf/ directory. But be careful about it as you would probably need h2 or jdbc-driver jar in your lib/.

About that module/plugin confusion in the beginning i think it is more clear now. From what i understood, a module is just another play application, more precisely a web application, that you may want to include in several projects. Like a google-maps widget for a yabe. Or an authentication system that sits on top your application, saying hello to logged-in users and showing login controls for others. Plugins on the other hand, extend the framework for developer needs. Like my primitive activiti integration, or a hypothetical drools integration which may fire rules upon a valid request using a simple annotation.

Plugins also reminded me of a recent chat with @mozcelebi and @burakdalgic, about whether it is possible in play to do things like django middlewares are able to do. It seems they are the way to go for request pre/post processing and more. I am thinking about a middlewares plugin for example.

Next post will be is about a simple activiti application on this.

Notes

  1. chelsae-snyder reblogged this from agaoglu
  2. trampoline3n reblogged this from agaoglu
  3. istoselidon9t reblogged this from agaoglu
  4. agaoglu posted this