Use jBPM5 embedded within a Java EE 6 application

Since the first final release of jBPM5 at the beginning of 2011 a little more than one year has passed. Despite of being a final release there have been a couple of bugs and the documentation was having many deficiencies. During the last year, however, jBPM5 was quickly moving forward and many bugs were fixed and the documentation has significantly improved.

Notwithstanding the improvements there are still some points which are not covered by the documentation of which the most important one for us is the integration of jBPM5 into a Java EE6 application. In the past we had multiple Java EE 5 projects where jBPM3 could be easily integrated. This is something we want for the current amazing Java EE 6 stack. Unfortunately there is no documentation on how to achieve this goal – maybe because no one succeeded in implementing it? Therefore, we took on this challenge and found a solution which meets our requirements. In this blog post we will describe this solution. Before we start to describe our solution we want to briefly lay out the requirements of the integration of jBPM5 into a Java EE 6 application.

Requirements

The main requirement is that we want to develop a modern web application based on the current Java EE 6 technology stack. As a result, there is a minimum set of technologies we want jBPM5 to support: JPA2.0 and JTA. In addition, we want to make use of CDI.  Unfortunately there are some challenges connected to these requirements.

Challenges

The challenges stem from the integration of jBPM5 with JPA2.0 and JTA.

With regard to JPA2.0 the challenge is that jBPM5 is using JPA1.0 for the persistence. This might not be a problem because the mapping of JPA1.0 and JPA2.0 are very similar (nevertheless you should not rely on that similarity). With regard to JTA the challenge is the absence of documentation about the configuration of the process engine (StatefulKnowledgeSession). We had to figure out, therefore, how to make it use container-managed transactions on our own.

Solution

First we will describe the solution we build in order to make use of JPA2.0 in the jBPM5 process engine. Doing so required creating some patches. This documentation refers to the version 5.2.0.Final of jBPM5. We refer you to our forked repository on github which contains all subsequently described patches (https://github.com/akquinet/jbpm). In the second part of the solutions we will show how to configure the process engine in order to use JTA.

Add JPA2.0 support

As already mentioned jBPM5 uses JPA1.0 for the persistence. This is not necessarily a problem because many of the JPA1.0 annotation mappings did not change from version 1.0 to 2.0. Therefore, you will not need any changes if you have exclusively used annotations which are present in both versions.  Unfortunately, this is not the case with jBPM5.

Actually, there is just one place where jBPM5 uses an annotation which is neither present in JPA2.0 nor in Hibernate 4. This is the class org.jbpm.persistence.processinstance.ProcessInstanceInfo. Here you will find a java.util.Set annotated with the annotation @CollectionOfElements. This annotation is part of hibernate 3 and is used to map a collection of elements or a collection of embedded objects. This annotation prevents us from using JPA2.0 as well as changing the persistence provider .

Fortunately for us there is an equivalent annotation in JPA2.0 – @ElementCollection. The easiest solution would be to replace the proprietary annotation by the one from JPA2.0 and to adapt the dependencies in the maven pom file of the jbpm-persistence-jpa project. However, this is not a good solution because it has a side-effect which would make the solution useless: it would tie jBPMN5 to JPA2.0, preventing it from working with JPA1.0 or hibernate 3.

After we had come to this realization we were left with two ways which would let us preserve support for JPA2.0 without breaking backward compatibility. You can call them the easy way and the clean/correct way.

The easy way consists of cloning the project jbpm-persistence-jpa and renaming the clone to jbpm-persistence-jpa2. In this case all changes will be done in the new project and will not affect the original project. The drawback of this solution is that we have to duplicate java code. If there are changes in the code in future we will have to maintain the code twice – once in each project.

The clean way requires a little more effort. The first step would be to split up the original project jbpm-persistence-jpa into several projects. The first of the new projects will contain all entity classes without any JPA annotation, while the second project contains the services which make use of the model. The second step is the creation of two new projects which contain nothing more than the XML JPA mapping files for JPA1.0 and JPA2.0. Therefore, this solution would result in four projects:

  • jbpm-persistence-jpa
  • jbpm-persistence-model
  • jbpm-persistence-mappings-jpa1
  • jbpm-persistence-mappings-jpa2

Since our main goal was to create a proof-of-concept we chose to implement the easy solution, simply because it required less effort and let us concentrate on the main goal. The solution can be found on github (https://github.com/akquinet/jbpm). We implemented this patch for the last final release 5.2.0.Final. If you check it out from our repository you will have to switch to the branch 5.2.0.Final-withJpa2Patch. Here you will find jbpm-persistence-jpa and jbpm-persistence-jpa2.

In addition to replacing the hibernate 3 annotation in the class org.jbpm.persistence.processinstance.ProcessInstanceInfo we had to apply some further changes .

  • remove all dependencies to hibernate 3
  • add dependencies to hibernate 4
  • patch class: org.jbpm.persistence.processinstance.ProcessInstanceInfo
  • replace hibernate 3 annotations and with jpa2.0 annotations (@CollectionOfElements -> @ElementCollection)
  • set version from 1.0 to 2.0 in orm.xml
  • exclude persistence-api:1.0 from drools persistence

Beyond this another patch was necessary:

  • JpaProcessPersistenceContextManager
    • adapt method  getProcessPersistenceContext to use command scoped entity manager from environment. Otherwise we get a NullPointerException .

As already mentioned you can download the source code from our github repository https://github.com/akquinet/jbpm/tree/5.2.0.Final-withJpa2Patch.

We are waiting eagerly for the next release (5.3.0.Final) where JPA2.0 support is part of the developed features. At a first glance the approach looks correct and promising. For example the JPA mappings are implemented by XML. This means that the model becomes agnostic to the used persistence framework.

Add JTA support

Before we describe how we integrated JTA in jBPM5 we would like to take a look at the core engine and the appertaining components. The following diagram shows the core engine.
jBPM5 core engine

The  StatefulKnowledgeSession is the central figure of the core engine. In order to start a process or to execute operations on existing/running processes we need an instance of this class. You can create a new knowledge session using  JPAKnowledgeService based on a knowledge base and an environment. The  KnowledgeBase is a component from drools which is reused in jBPM5 (due to the fact that jBPM5 bases on Drools). A  KnowledgeBase can be viewed as a container which provides information and different kind of resources. In case of jBPM5 the  KnowledgeBase contains the process definitions. The environment is used to configure the persistence of the process engine. The environment must contain a reference to the  EntityManager defined in the persistence unit for jBPM5. Usually the name of this persistence unit is ‚org.jbpm.persistence.jpa’ . Additionally we must register a transaction manager at the environment. Note that we want here to use the transaction manager from the apllication server and do not want to make use of user defined transactions.

Now we are ready to show the code. Let’s start with the CDI component which produces the KnowledgeBase:

public class KnowledgeBaseProducer implements Serializable {

@Produces
@Named
@KBase
@ApplicationScoped
public KnowledgeBase produceKnowledgeBase() {

    KnowledgeBuilder kbuilder =
             KnowledgeBuilderFactory.newKnowledgeBuilder();

    Iterator<Resource> iterator = loadYourProcessDefinitions();

    while (iterator.hasNext()) {
        Resource resource = iterator.next();
        kbuilder.add(resource, ResourceType.BPMN2);
    }

    return kbuilder.newKnowledgeBase();
}

 

@Retention(RetentionPolicy.RUNTIME)
@Qualifier
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface KBase { }

Here is the component providing the environment:

@ApplicationScoped
public class EnvironmentProvider implements Serializable {

    @PersistenceUnit(unitName = "org.jbpm.persistence.jpa")
    private EntityManagerFactory emf;

    @Resource(mappedName = "java:jboss/TransactionManager")
    private TransactionManager tm;

    private transient Environment env = null;

    public Environment getEnvironment() {

        if(environment == null){

          env = KnowledgeBaseFactory.newEnvironment();
          env.set(EnvironmentName.CMD_SCOPED_ENTITY_MANAGER, em);
          env.set(EnvironmentName.APP_SCOPED_ENTITY_MANAGER, em);

          JpaProcessPersistenceContextManager manager =
                new JpaProcessPersistenceContextManager(env);
          env.set(EnvironmentName.PERSISTENCE_CONTEXT_MANAGER,
                  manager);

          JtaTransactionManager transactionManager =
                new JtaTransactionManager(null, null, tm);
          env.set(EnvironmentName.TRANSACTION_MANAGER,
                  transactionManager);
        }

        return environment;
    }
}

In this case we implemented an application scoped provider which provides the environment. At this point we must consider that the Environment class does not implement the Serializable interface. And as we use a CDI component which corresponds to a stateful session bean we must take into account that this bean must be passivation capable. Hence we must declare the global attribute which contains the environment as transient. After deserialization of our provider the environment variable will be null. But the environment will be recreated on first access.

Finally all we need to do is to screw together all involved components and create the StatefulKnowledgeSession.

@ApplicationScoped
public class KnowledgeSessionProvider implements Serializable {

    @Inject
    private EnvironmentProvider environmentProvider;

    @Inject
    @KBase
    private KnowledgeBase kBase;

    private transient StatefulKnowledgeSession ksession = null;

    public KnowledgeSessionDelegate createKnowledgeSession() {

        Environment env = environmentProvider.getEnvironment();

        if(ksession == null){

            ksession = JPAKnowledgeService.newStatefulKnowledgeSession(kBase,null,env);

            // You have to implement a method where your
            // work item handlers are registered
            registerYourWorkItemHandlers(ksession.getWorkItemManager());
        }

        return ksession;
    }
}

The attentive reader will have noticed that the provider CDI components are declared for the CDI application scope. We do this because the KnowledgeBase is shared across the entire application and is initialized just once. If you want to add new process definitions to the KnowledgeBase you need to inject the delegate, fetch the KnowledgeBase from it and add a new process definition to it – That’s it! Very easy, right? Concerning the StatefulKnowledgeSession the provider and the knowedge session are application scoped as well. This has several reasons. The first reason is that it is the easiest way. But is this solution correct? What happens if there are multiple user sessions working concurrently with the StatefulKnowledgeSession? Well, this is not a problem because the StatefulKnowledgeSession is multithreading capable (as described in the user guide).

Finally let’s take a look at the last code snippet where you can see how a process can be started from a service of your application.

@Named
@SessionScoped
public class YourProcessManagementService implements Serializable {

    @Inject
    private KnowledgeSessionProvider ksessionProvider;

    public void startNewProcess(String processDefinitionId) {

        StatefulKnowledgeSession ksession =
                              ksessionProvider.getKSession();
        ksession.startProcess(processDefinitionId);
    }

    ...
}

All you need to do here ist to inject the knwoledge session provider, fetch the contained StatefulKnowledgeSession and perform operations on it. Until now we have shown you all the necessary patches and code you need in your application. But before you start with the implementation of your application you need to set up your project.

Set up your maven project

In order to reconstruct the described solution you will have to checkout or download our patched version from github and build it with maven. After you have done this you have to create a maven project containing the following maven dependencies:

<properties>
  <project.base.dir>${project.parent.basedir}</project.base.dir>
  <jbpm.version>5.2.0.Final-withJpa2Patch</jbpm.version>
  <drools.version>5.3.1.Final</drools.version>
</properties>

<dependencies>

  <!—- jBPM5 start -->
  <dependency>
    <groupId>org.jbpm</groupId>
    <artifactId>jbpm-bam</artifactId>
    <version>${jbpm.version}</version>
  </dependency>
  <dependency>
    <groupId>org.jbpm</groupId>
    <artifactId>jbpm-human-task</artifactId>
    <version>${jbpm.version}</version>
  </dependency>
  <dependency>
    <groupId>org.jbpm</groupId>
    <artifactId>jbpm-workitems</artifactId>
    <version>${jbpm.version}</version>
  </dependency>
  <dependency>
    <groupId>org.jbpm</groupId>
    <artifactId>jbpm-bpmn2</artifactId>
    <version>${jbpm.version}</version>
  </dependency>
  <dependency>
    <groupId>org.jbpm</groupId>
    <artifactId>jbpm-persistence-jpa2</artifactId>
    <version>${jbpm.version}</version>
  </dependency>
  <!-- jBPM5 end -->

  <!-- drools start -->
  <dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-compiler</artifactId>
    <version>${drools.version}</version>
    <exclusions>
      <exclusion>
        <artifactId>antlr</artifactId>
        <groupId>antlr</groupId>
      </exclusion>
    </exclusions>
  </dependency>
  <dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-core</artifactId>
    <version>${drools.version}</version>
  </dependency>
  <dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-persistence-jpa</artifactId>
    <version>${drools.version}</version>
    <exclusions>
      <exclusion>
        <artifactId>hibernate-annotations</artifactId>
        <groupId>org.hibernate</groupId>
      </exclusion>
      <exclusion>
        <artifactId>hibernate-commons-annotations</artifactId>
        <groupId>org.hibernate</groupId>
      </exclusion>
      <exclusion>
        <artifactId>dom4j</artifactId>
        <groupId>dom4j</groupId>
      </exclusion>
    </exclusions>
  </dependency>
  <dependency>
    <groupId>org.drools</groupId>
    <artifactId>knowledge-api</artifactId>
    <version>${drools.version}</version>
  </dependency>
  <!-- drools End -->

</dependencies>

Furthermore you must provide a persistence.xml file with a persistence unit for the jBPM5 process engine.

<?xml version="1.0" encoding="UTF-8"?>
<persistence
    version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
        http://java.sun.com/xml/ns/persistence/orm
        http://java.sun.com/xml/ns/persistence/orm_1_0.xsd">

  <persistence-unit name="org.jbpm.persistence.jpa"
                    transaction-type="JTA">

    <jta-data-source>
        java:jboss/datasources/ExampleDS
    </jta-data-source>

    <mapping-file>META-INF/jbpm_orm.xml</mapping-file>

    <class>org.jbpm.task.Attachment</class>
    <class>org.jbpm.task.Content</class>
    <class>org.jbpm.task.BooleanExpression</class>
    <class>org.jbpm.task.Comment</class>
    <class>org.jbpm.task.Deadline</class>
    <class>org.jbpm.task.Escalation</class>
    <class>org.jbpm.task.Group</class>
    <class>org.jbpm.task.I18NText</class>
    <class>org.jbpm.task.Notification</class>
    <class>org.jbpm.task.EmailNotification</class>
    <class>org.jbpm.task.EmailNotificationHeader</class>
    <class>org.jbpm.task.Reassignment</class>
    <class>org.jbpm.task.Task</class>
    <class>org.jbpm.task.SubTasksStrategy</class>
    <class>org.jbpm.task.OnParentAbortAllSubTasksEndStrategy</class>
    <class>org.jbpm.task.OnAllSubTasksEndParentEndStrategy</class>
    <class>org.jbpm.task.User</class>

    <class>org.drools.persistence.info.WorkItemInfo</class>
    <class>org.drools.persistence.info.SessionInfo</class>
    <class>org.jbpm.persistence.processinstance.ProcessInstanceEventInfo</class>
    <class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class>

    <properties>
      <property name="hibernate.dialect"
                value="org.hibernate.dialect.H2Dialect" />

      <property name="hibernate.hbm2ddl.auto"
                value="create-drop" />
    </properties>

  </persistence-unit>
</persistence>

 

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings
    xmlns="http://java.sun.com/xml/ns/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
    version="2.0">
      <named-query name="ProcessInstancesWaitingForEvent">
          <query>
select
    processInstanceInfo.processInstanceId
from
    ProcessInstanceInfo processInstanceInfo join processInstanceInfo.eventTypes eventTypes
where
    eventTypes = :type
          </query>
      </named-query>
</entity-mappings>

Summary

This blog post shows how to embed jBPM5 in a Java EE 6 web application. Unfortunately we had to build some patches. We hope that these patches will be unnecessary in future releases. Having the patch for the JPA2.0 support we were able to quickly create the described solution. Addtionally we find that with the means of CDI we have achieved/build a very fancy solution. With this solution we have to work directly with the process engine and you have to take care of the state of your processes on your own. Unfortunately That’s half the battle, because it depends on your process definitions if the described solution is applicable for your application. If you have user tasks / human tasks in your process definitions you will hardly implement the maintenance of the process and it’s task nodes on your own – this is too complex and too expensive. And why should you do this as jBPM5 already provides a TaskService which you can integrate and use. Unfortunately the integration of the TaskService is not easily done. Therefore we point to our Flux project.

We have implemented an CDI module (Flux) where all aspects described in this blog post and other additional aspects like the integration of the TaskService are covered. With this CDI module you can easily embed jBPM5 in your web application and use arbitrary process definitions. The first demo version will be published soon. You will find it on github (https://github.com/akquinet/flux). This will be the initial version and there will be features missing. For example we are just planning and designing the support of a business scope and a forge plugin for generating code from a process definition. A blog post and a tutorial for our framework will follow as well. Beyond that we refer to the BPM Service component from SwitchYard (https://docs.jboss.org/author/display/SWITCHYARD/BPM+Services) which will provide an API to control processes. Unfortunately these BPM services are closely linked with SwitchYard.  We will keep an eye on this…

Feel free to contact us for any questions or feedback.

marek.iwaszkiewicz@akquinet.de
pascal.schaerf@akquinet.de

12 thoughts on “Use jBPM5 embedded within a Java EE 6 application

  1. i’m trying to compile jbpm5-flux-tdoservice and i got error below. any idea how to resolved this?

    ——————————————————————————-
    Test set: de.akquinet.jbosscc.flux.tdoservice.service.TestTaskDataObject
    ——————————————————————————-
    Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.011 sec <<< FAILURE!
    initializationError(de.akquinet.jbosscc.flux.tdoservice.service.TestTaskDataObject) Time elapsed: 0.002 sec <<< ERROR!
    java.lang.Exception: No runnable methods
    at org.junit.runners.BlockJUnit4ClassRunner.validateInstanceMethods(BlockJUnit4ClassRunner.java:177)
    at org.junit.runners.BlockJUnit4ClassRunner.collectInitializationErrors(BlockJUnit4ClassRunner.java:122)
    at org.junit.runners.ParentRunner.validate(ParentRunner.java:269)
    at org.junit.runners.ParentRunner.(ParentRunner.java:66)
    at org.junit.runners.BlockJUnit4ClassRunner.(BlockJUnit4ClassRunner.java:58)
    at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:13)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)
    at org.apache.maven.surefire.junit4.JUnit4TestSet.(JUnit4TestSet.java:45)
    at org.apache.maven.surefire.junit4.JUnit4DirectoryTestSuite.createTestSet(JUnit4DirectoryTestSuite.java:56)
    at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.locateTestSets(AbstractDirectoryTestSuite.java:96)
    at org.apache.maven.surefire.Surefire.createSuiteFromDefinition(Surefire.java:209)
    at org.apache.maven.surefire.Surefire.run(Surefire.java:156)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345)
    at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009)

  2. Unfortunatly I’v got next exceptions during deployment:

    org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [XHumanTaskClient] with qualifiers [@Default] at injection point [[field] @Inject @HumanTaskClient private de.akquinet.jbosscc.flux.bpmservice.WorkflowManagementServiceBean.htcManagerService]
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:311)
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:280)
    at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:143)
    at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:163)
    at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:382)
    at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:367)
    at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:380)
    at org.jboss.as.weld.WeldContainer.start(WeldContainer.java:83)
    at org.jboss.as.weld.services.WeldService.start(WeldService.java:76)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)
    Exception 0 :
    org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [XHumanTaskClient] with qualifiers [@Default] at injection point [[field] @Inject @HumanTaskClient private de.akquinet.jbosscc.flux.bpmservice.TaskFormServiceBean.humanTaskClient]
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:311)
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:280)
    at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:143)
    at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:163)
    at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:382)
    at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:367)
    at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:380)
    at org.jboss.as.weld.WeldContainer.start(WeldContainer.java:83)
    at org.jboss.as.weld.services.WeldService.start(WeldService.java:76)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)

  3. hi.. if i need to create some lakhs of processes, say for performance testing, should i use a single session for concurrent threads doing creation of processes. As last notified time is updated for every process completion. This could be a bottleneck for me r8?

  4. Hi, really nice post.

    About the Task service you should look at the CDI version of the task module called: jbpm-human-task-services and jbpm-human-task-workitems, both using CDI and ready to work on a JEE container.
    The JPA 2 is almost ready, so with version 5.4.0.Final it should be there and working.

    As a suggestion, You should join the community channels to apply all these patches to the community project instead of having a separate fork to maintain and distribute 🙂

    Cheers

  5. How can we use Struts2/JSF to create forms in jBPM5??
    Please provide your valuable help.

  6. Hello,
    tried to “mvn install” on actual akquinet-flux\jbpm5-flux-examples\myHoliday\myHoliday-dao:
    [ERROR] Failed to execute goal on project myHoliday-dao: Could not resolve dependencies for project de.akquinet:myHoliday-dao:jar:0.0.1-SNAPSHOT: Could not find artifact org.jboss.seam.solder:seam-solder:jar:3.0.0.Final in central (http://repo1.maven.org/maven2)
    Any ideas and solutions please?
    Thanks,
    Michael

  7. Hi, when will you udpate your source code on github?
    I’m looking forward to it.

    1. Yes, it is possible. This is exactly what we do in our Flux framework. We will provide the source code as soon as possible.

Comments are closed.