Persistent Human Task in jBPM 5

Leave a comment

June 5, 2011 by huionn

jBPM 5.0 (formerly known as Drools Flow) has been released a few months ago.

I played with its jBPM console and it is equipped with  necessary task management features. I also tried to play with its examples and found that it is very extensible. However as it is new, there are no much resources (books, tutorial and articles) about it. jBPM has comprehensive document but it is not so use case oriented.

As a result, I find it hard to implement some common use cases. For example, based on the “evaluation” example, I would like to dynamically assign task to user. Instead of hardcoded ‘mary’ as ActorId in the user task node, I want to assign the task based on the result of previous node. In jBPM 4, there is a concept of AssignmentHandler to assign task which is not available in jBPM 5. Finally, I figured out ActionId (and other attributes) can accept expression language in #{supervisor} form. So, I can bind the variable supervisor in a script task or “On Exit Action” of previous node. But I am still not sure whether this is the best practice.

Then I tried to use persistence for “evaluation”. After hours of trial & error and googling, I found that I should use org.jbpm.process.workitem.wsht.CommandBasedWSHumanTaskHandler for persistent human task. It is actually written in the jBPM document but I didn’t notice it. I got it from http://community.jboss.org/people/bpmn2user/blog/2011/03/25/jbpm5–persistence-hello-process-example.

public class ProcessTest { 
    public static final void main(String[] args) {
        try {
            setupDataSource();
            // create the entity manager factory and register it in the environment
            EntityManagerFactory emf =
                Persistence.createEntityManagerFactory( "org.jbpm.persistence.jpa" );
            Environment env = KnowledgeBaseFactory.newEnvironment();
            env.set( EnvironmentName.ENTITY_MANAGER_FACTORY, emf );
            env.set( EnvironmentName.TRANSACTION_MANAGER,
                     TransactionManagerServices.getTransactionManager() );
            env.set( EnvironmentName.GLOBALS, new MapGlobalResolver() );             
            // create a new knowledge session that uses JPA to store the runtime state
            KnowledgeBase kbase = readKnowledgeBase();
            StatefulKnowledgeSession ksession =
                JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
            int sessionId = ksession.getId();
            System.out.println("Session ID: " + sessionId); 
            // load up the knowledge base
            KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newThreadedFileLogger(ksession, "test", 1000);
            ksession.getWorkItemManager().registerWorkItemHandler("Human Task",
                    new CommandBasedWSHumanTaskHandler(ksession));
            // start a new process instance
            Map params = new HashMap();
            params.put("employee", "krisv");
            UserTransaction ut = (UserTransaction) new InitialContext()
                    .lookup("java:comp/UserTransaction"); 
            ut.begin();
            ksession.startProcess("com.sample.evaluation", params);
            logger.close(); 
            // commit the transaction
            ut.commit();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    } 
    private static void setupDataSource() {
        PoolingDataSource ds = new PoolingDataSource();
        ds.setUniqueName("jdbc/processInstanceDS");
        ds.setClassName("org.h2.jdbcx.JdbcDataSource");
        ds.setMaxPoolSize(3);
        ds.setAllowLocalTransactions(true);
        ds.getDriverProperties().put("user", "sa");
        ds.getDriverProperties().put("password", "");
        ds.getDriverProperties().put("URL", "jdbc:h2:tcp://localhost/data/process-instance-db");
        ds.init();
    } 
    private static KnowledgeBase readKnowledgeBase() throws Exception {
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newClassPathResource("Evaluation.bpmn"), ResourceType.BPMN2);
        return kbuilder.newKnowledgeBase();
    } 
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: