Blog Posts Process Management

jBPM 3 annotations

Blog: PlanetjBPM's Weblog

Everybody using seam probably knows about the fact that Seam provides access to process instances, tasks and a (kind of) process context via annotations. But the seam process context does not always play nice with the plain jbpm context.

A few months ago, I was working on a ‘new’ JSF/Seam based jBPM web console and needed the real JbpmContext.  Now everybody using jBPM knows about the basic try/finally block

public void myMethod() {
    // Lookup the pojo persistence context-builder that is configured above
    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
    try {
      // Do work on the jBPM context
    } finally {
      // Tear down the pojo persistence context.
      // This includes flush the SQL for inserting the process definition  
      // to the database.
      jbpmContext.close();
    }
  }
}

Since I had many classes and inside that many methods where I needed the jBPM context, I decided to take a quick look at creating a custom annotation. Well, it turned out to be very simple. The result is:

  @Jbpm3Method
  public void myMethod() {
    //Do work on the jBPM context
  }

Much cleaner isn’t it? Since I created this as a proof of concept and I am not an expert in this area, it is (most likely) not optimized and dependent on seam (tips are of course welcome to make it better and more generic). You also need a @Jbpm3 annotation on the class level and have to annotate a variable of type JbpmContext. But when you put this in a base class:

  @Jbpm3
  public abstract class Jbpm3AbstractBaseClass {

  @Jbpm3Context
  public JbpmContext jBPMContext;

  }

All you have to do is extend this base class.

For everybody who is interested, the code off all classes:

Jbpm3Interceptor.java
package org.jboss.jbpm.console.interceptor;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.intercept.AroundInvoke;
import org.jboss.seam.annotations.intercept.Interceptor;

import org.jboss.seam.intercept.AbstractInterceptor;
import org.jboss.seam.intercept.InvocationContext;
import org.jboss.seam.log.Log;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;

@Interceptor
public class Jbpm3Interceptor extends AbstractInterceptor implements Serializable {

  /**
  *
  */
  private static final long serialVersionUID = 9077871878937632746L;

  @Logger
  Log                       log;

  JbpmContext               jBPMContext      = null;

  @AroundInvoke
  public Object aroundInvoke(InvocationContext invocationContext) throws Exception {

    Method method = invocationContext.getMethod();

    if (method.isAnnotationPresent(Jbpm3Method.class)) {

      Field jBPM3Context = null;
      Object invocationTarget = invocationContext.getTarget();
      Field[] fields = invocationTarget.getClass().getFields();

      for (Field field : fields) {

        if (field.isAnnotationPresent(Jbpm3Context.class)) {

          jBPM3Context = field;
          JbpmContext jBPMContext = JbpmConfiguration.getInstance().createJbpmContext();
          field.set(invocationTarget, jBPMContext);

          Object returnVal = invocationContext.proceed();

          if (jBPMContext != null) jBPMContext.close();

          return returnVal;
        }
      }
      if (jBPM3Context == null) {
        log.warn("Class " + invocationContext.getClass().getName()
        + " has Jbpm3 annotation, but no field public field has @Jbpm3Context annotation");
      }
    }

    return invocationContext.proceed();

  }

  public boolean isInterceptorEnabled() {
    log.debug("isInterceptorEnabled() = " + true + " for " + getComponent().getName() );
    return getComponent().beanClassHasAnnotation(Jbpm3.class);
  }

}

Jbpm3.java

  package org.jboss.jbpm.console.interceptor;

  import java.lang.annotation.Documented;
  import java.lang.annotation.ElementType;
  import java.lang.annotation.Inherited;
  import java.lang.annotation.Retention;
  import java.lang.annotation.RetentionPolicy;
  import java.lang.annotation.Target;

  import org.jboss.seam.annotations.intercept.Interceptors;

  @Target({ElementType.TYPE})
  @Retention(RetentionPolicy.RUNTIME)
  @Interceptors(Jbpm3Interceptor.class)
  @Documented
  @Inherited
  public @interface Jbpm3 {}

Jbpm3Context.java

  package org.jboss.jbpm.console.interceptor;

  import java.lang.annotation.Documented;
  import java.lang.annotation.ElementType;
  import java.lang.annotation.Inherited;
  import java.lang.annotation.Retention;
  import java.lang.annotation.RetentionPolicy;
  import java.lang.annotation.Target;

  @Target({ElementType.FIELD})
  @Retention(RetentionPolicy.RUNTIME)
  @Documented
  @Inherited
  public @interface Jbpm3Context {}

JbpmMethod.java

  package org.jboss.jbpm.console.interceptor;

  import java.lang.annotation.Documented;
  import java.lang.annotation.ElementType;
  import java.lang.annotation.Inherited;
  import java.lang.annotation.Retention;
  import java.lang.annotation.RetentionPolicy;
  import java.lang.annotation.Target;

  import org.jboss.seam.annotations.intercept.Interceptors;

  /**
   * Opens a JbpmContext before the method is called and closes it afterwards.
   */
  @Target({ElementType.METHOD})
  @Retention(RetentionPolicy.RUNTIME)
  @Interceptors(Jbpm3Interceptor.class)
  @Documented
  @Inherited
  public @interface Jbpm3Method {}

Leave a Comment

Get the BPI Web Feed

Using the HTML code below, you can display this Business Process Incubator page content with the current filter and sorting inside your web site for FREE.

Copy/Paste this code in your website html code:

<iframe src="https://www.businessprocessincubator.com/content/jbpm-3-annotations/?feed=html" frameborder="0" scrolling="auto" width="100%" height="700">

Customizing your BPI Web Feed

You can click on the Get the BPI Web Feed link on any of our page to create the best possible feed for your site. Here are a few tips to customize your BPI Web Feed.

Customizing the Content Filter
On any page, you can add filter criteria using the MORE FILTERS interface:

Customizing the Content Filter

Customizing the Content Sorting
Clicking on the sorting options will also change the way your BPI Web Feed will be ordered on your site:

Get the BPI Web Feed

Some integration examples

BPMN.org

XPDL.org

×