Keep informed?
Subscribe for our newsletter now!

Remember Seam and jBPM? – Try out CDI and Activiti

Outdated!

Please note that this blog post is outdated, since we forked Activiti in March 2013 and started a new Open Source BPM project called camunda BPM (www.camunda.org). You will find this topic and loads of more best practices, blueprints etc. there, so you should just have a look :-)

activiti-jeeRemember the nice Seam 2jBPM 3 integration? We did it with Activiti and CDI. “We” being myself and Ronald van Kuijk, whom you may remember as  kukeltje from the jBPM days. The good news first: Now you can easily embed Activiti in your Java EE 6 applicaton!

CDI (Context and Dependency Injection, JSR-299) is a part of the Java EE 6 specification and provides services like dependency injection, contextual lifecycle management or  interceptors to beans. Beans are Java classes which follow the POJO-programming model. This means that in CDI almost everything is a “bean”, including EJBs.

One interesting feature of  CDI is that it provides well-defined extension mechanisms as part of its SPI. The most prominent extension point is the possibility to implement custom contexts which are contextual bean-stores.  The activiti-cdi extension provides just that: a context for process-scoped beans. It enables you to reference CDI-managed beans from your processes and store instances of process-scoped beans in the process execution. In greater detail, currently the following features are supported:

  • A custom ELResolver allowing to reference beans (ManagedBeans, EJBs, …) in the processes.
  • Start/Stop of the ProcessEngine and deployment of processes.
  • Exposure of the ProcessEngine as a bean.
  • The possibility to associate a ProcessInstance with the current Conversation.
  • The possibility to associate a Task with the current Conversation.
  • A custom context (@BusinessProcessScoped) for storing process-scoped data.
  • @ProcessVariable: a qualifier for injecting process variables into beans.
  • Declarative control over the process (@StartProcess, @CompleteTask, …).

As always with CDI, its “take as much a you need”.

Let’s look at some examples! Note: The examples are taken from the travel-expenses demo-application available alongside the CDI-extension. The application is driven by the following process:

Simple business trip authorization process

Starting a new Process Instance

Processes can be declaratively started using the @StartProcess-annotation on a bean-method:

@StartProcess("authorizeBusinessTripRequest")
public String submitRequest() {
...
}

In the example application, this method is called when a user submits a JSF form, which is a common pattern in human-workflow driven applications. In a more service-orchestration-like setting, such an annotation could be placed on @MessageDriven beans, starting a new process instance upon the reception of a message.

Referencing Beans from the Process

After the process is started, the request needs to be authorized by a manager. This means that the manager responsible for authorizing the business trip needs to be retrieved. Using the Activiti CDI extension, beans (EJBs, CDI-managed beans, …) can be referenced using Unified Expression Language:

<userTask id=”approveBusinessTrip” name=”Approve Business Trip”>
   <humanPerformer>
      <resourceAssignmentExpression>
         <formalExpression>#{authorizingManager.account.username}</formalExpression>
      </resourceAssignmentExpression>
   </humanPerformer>
</userTask>

In a Bean, we produce the „authorizingManager“ (in this simple example by querying the database):

@Inject
@ProcessVariable
String businessTripRequesterUsername;

@Produces
@Named
public Employee authorizingManager() {
	TypedQuery query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.account.username='"
             + businessTripRequesterUsername + "'", Employee.class);
	Employee employee = query.getSingleResult();
	return employee.getManager();
}

This allows us to hide the way how the authorizingManager is determined from the process. We do not need to write an Expression of the sort

   #{authService.getAuthorizingManager(…)}

On the contrary, it is provided to the process as contextual data.

When implementing business processes, it is important to distinguish process-scoped data (data objects the lifecycle of which is tied to a process instance) from data objects which are simply required by the process. The lifecycle of the authorizingManager-object is not tied to the lifecycle of the process. For example, the authorizingManager can change while the process is executing. Because a process is potentially long running, it is important not to store such objects as process variables. Consider the following process-fragment:

Fragment: treating required data as process-scoped data

The intended interpretation is that the manager is provided with a list of employees absent at the same dates as the requesting employee. If the list is retrieved and stored in the process execution, like shown above, the manager is potentially presented an outdated list when he completes the task.

The Activiti-CDI extension allows us to simply reference the list of absent employees in the JSF-form (or any other presentation layer technology that can be plugged-in) presented to the manager.

Managing process-scoped Data

Process-scoped data can be marked-up as such and thus be tied to a process instance by its lifecycle. In the example application, the BusinessTripRequest is process-scoped:

@Named
@BusinessProcessScoped
public class BusinessTripRequest implements Serializable { ... }

Beans annotated with @BusinessProcessScoped are stored in the process execution using a custom CDI Context implementation.
A welcome side-effect of using CDI is that tools can leverage CDI’s type-safety to provide services like content-assist (See Screenshot of editing a BPMN-Process in Eclipse with JBoss CDI Tools enabled.)Content assis when editing BPMN processes using Eclipse and JBoss tools.

Whats Next?

These are just a few examples of what is currently possible. Eventually the goal is to provide two different modules: a CDI-core module which provides roughly the functionality outlined above and a JSF-module providing a set of generic, reusable JSF components for managing Tasks, Tasklists, Forms etc.

In addition, illustrative examples and POCs are developed. The first example is already available, a simple business-trip authorization manager implemented as a JavaEE 6 application with JPA, EJB, CDI, JSF and an embedded Activiti.

On the TODO –list we have (among others) the following Items:

  • Merge Ronald’s JSF Components and Explorer-like-Example.
  • Looking into configuration options: basically there are two possibilities: Activiti uses the same datasource as the application, Activiti and the application(s) use different (xa-)datasources. Activiti is configured to participate in application-managed transactions.
  • Currently, the cdi-extension directly instantiates the ProcessEngine. Aditionally: use resolution of a managed, maybe MBean-like, ProcessEngine-instance.

Where can I get it?

Ok, so by now you probably *really* want to give this a test-drive. The activiti-cdi integration is an opesource project provided as an incubating component of camunda fox. Find it in the fox-ce-trunk under ‘incubator’. It should be noted that the current code is still in an alpha-like proof-of-concept state.

Summary

As already stated, the activiti-cdi extension is still in alpha state. The goal is to provide an infrastructure for process implementation and embedding the process engine in custom applications. This will allow applications to leverage the provided business process context as an execution context for long running, multi-user or multi-system interactions. From the process implementation perspective, the contextual programming model provided by CDI promotes an intuitive separation of process-level and application-level concerns. Business processes are executed inside a contextual environment, satisfying data- and service-dependencies, minimizing the dependencies between the application and the process.

About the author

danielThis is my first entry on bpm-guide.de so a small introduction is in order :) I am Daniel Meyer and a BPM-Consultant with camunda services GmbH. I am Activiti-committer mainly focussed on Activiti Cycle development. I like to think and talk about business process driven software engineering and software architecture.

Daniel Meyer

About Daniel Meyer, camunda BPM Project Lead

Daniel Meyer is project lead for camunda BPM. He is passionate about BPM with a particular focus on process automation and process engines. His mission is to deliver the best possible experience to developers who want to use BPM technology in their applications. He is a Java EE 6 aficionado and believes in polyglot technology stacks based on open standards.

Already read?

CMMN – The BPMN for Case Management?

New Whitepaper: The Zero-Code BPM Myth

2 Responses

Leave a reply

Powered by WP Hashcash