Friday, July 29, 2011

jBPM5 on AS7: Lightning !

Most of you probably know that JBoss Application Server 7 has recently been released in the community. Due to its lightweight and modular approach, concurrency and much more, the startup time has descreased significantly, which is always nice to hear for developers! Although I still have to figure out how to get a cup of coffee in only 3 seconds now ;)

During my holiday break, I took some time to play with it, and see how difficult it would be to get jBPM5 running on AS7. It took me some time, but in the end I managed to get the jBPM console running on AS7. I'll describe the steps I took to get there now, but we'll try to get this integrated in the installer in the near future, so other people can start playing with this stuff more easily as well (any volunteers?).

I started with downloading JBossAS 7.0.0.Final and took the jBPM 5.1.0.Final jbpm console wars as a starting point.

  • Biggest change probably is the fact that as7 ships with JPA2 and hibernate4, while jBPM is still using JPA1 and hibernate3. Due to it's modular design, we can however still run hibernate3 applications on as7, we just need to add these dependencies ourselves now (and exclude hibernate4).

    • Add the following jars from the jBPM runtime to the WEB-INF/lib folder of the server war: hibernate-core, hibernate-entitymanager, hibernate-commons-annotations, hibernate-annotations, dom4j, javassist

    • Make sure to exclude the hibernate4 jars, by adding the following WEB-INF/jboss-deployment-structure.xml in the server war:
      <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
      <deployment>
      <exclusions>
      <module name="org.hibernate"/>
      </exclusions>
      <deployment>
      </jboss-deployment-structure>

    • I got an error with my persistence.xml and JPA2 so I disabled JPA2 scanning by commenting out the JPA module (org.jboss.as.jpa) and subsystem (urn:jboss:domain:jpa:1.0) in the standalone.xml configuration file.

  • Data sources are no longer specified by dropping a *ds.xml in the deploy folder but as part of the configuration. In configuration/standalone.xml, add the following datasource:
    <datasource enabled="true" context="true" name="java:jboss/datasources/jbpmDS">
    <connection-url>jdbc:h2:tcp://localhost/~/test</connection-url>
    <driver>h2</driver>
    <pool></pool>
    <security>
    <user-name>sa</user-name>
    <password></password>
    </security>
    <validation></validation>
    <timeout></timeout>
    <statement></statement>
    </datasource>
    Notice that we also changed the jndi name of the datasource as we need to use one of the known domains (jboss in this case). This means you also need to change the name of the datasource in your persistence.xml.

  • The security configuration is also different, you should now add a security domain in the standalone.xml and copy the users.properties and roles.properties file in the WEB-INF/classes folder:
    <security-domain name="jbpm-console" cache-type="default">
    <authentication>
    <login-module code="UsersRoles" flag="required"/>
    </authentication>
    </security-domain>

  • Add your database driver (in our case h2.jar) to WEB-INF/lib of the server war.

  • The default transaction manager lookup no longer works (as its jndi name has changed) so I registered a custom transaction manager lookup
    • In persistence.xml, add
      <property name="hibernate.transaction.manager_lookup_class"
      value="org.jbpm.JBPMTransactionManager" />

    • Create the JBPMTransactionManager class and add it to the WEB-INF/classes or lib folder
      package org.jbpm;
      import java.util.Properties;
      import javax.naming.InitialContext;
      import javax.naming.NamingException;
      import javax.transaction.Transaction;
      import javax.transaction.TransactionManager;
      import org.hibernate.HibernateException;
      import org.hibernate.transaction.TransactionManagerLookup;

      public class JBPMTransactionManager implements TransactionManagerLookup {
      public Object getTransactionIdentifier(Transaction transaction) {
      return transaction;
      }
      public TransactionManager getTransactionManager(Properties properties) throws HibernateException {
      try {
      return (TransactionManager) new InitialContext()
      .lookup("java:jboss/TransactionManager");
      } catch (NamingException e) {
      throw new RuntimeException(e);
      }
      }
      public String getUserTransactionName() {
      return null;
      }
      }

  • There is another persistence.xml file in the jbpm-human-task jar (which is also bundled in the server war) which actually shouldn't be there, and is picked up by as7 at deploy time, so you should just delete that persistence.xml file (as for example discussed in this blog).

  • Finally, there was a problem in the FormProcessingFacade of the bpm console code. It was no longer picking up correctly when a form was sending data as plain/text, as there were now new properties in the media type related to encoding that made the equals fail. So I had to change line 228 in FormProcessingFacade to this (checking only for plain/text mediatype and simply ingoring properties:
    if("text".equals(mediaType.getType()) && "plain".equals(mediaType.getSubtype()))

Ok, this might sound a little scary, but don't worry, you won't have to do all this manually yourself, once we update the build to generate as7-compatible wars and update install script, it should be able to handle most of this! I just wanted to share this with anyone who might be trying to do something similar.

Still need to check how to deploy the BIRT reporting engine on as7 and then the jbpm-console is fully functional. Tihomir has already looked at deploying the designer on as7 and generated a customized war in the build for that.

8 comments:

  1. Hi!! Awesome post! Yeah, It took me some hard work to put jbpm working fine with AS 7 (and also I was using JBoss Seam stuff with that). Thanks for the tips!! :)
    BTW, Seam 2 jar is really necessary at human-task module? I had some problems with that (which I described here -> http://hannelita.wordpress.com/2011/07/27/jbpm-seam-3-jboss-as-7-solved-2/ )

    ReplyDelete
  2. What do you mean by "server war"?

    ReplyDelete
  3. @nitoro81: jbpm-gwt-console-server.war

    ReplyDelete
  4. When do you expect to have these changes available?

    ReplyDelete
  5. Hi,

    thank you for the comprehensive explanation. It helped me a lot. May I point out 2 mistakes though?

    1) In the xml for the datasource, the corresponding attribute is called jndi-name, not name. You also mention it as the JNDI name in the text. Another attribute named pool-name is also required, making the element look like this: <datasource jndi-name="java:jboss/datasources/jbpmDS" pool-name="jbpmDS" enabled="true">...

    2) little typo: in the xml for the security-domain, the closing tag lacks a slash to be closing ;)

    ReplyDelete
  6. @Michèl: Thanks, it seems they changed the name of the jndi-name attribute in jboss-as-7.0.2. The other one is indeed a typo, thx. I'm automating these steps as part of the jbpm-installer as we speak.

    ReplyDelete
  7. Could you please upload the modified .WAR somewhere?

    ReplyDelete
  8. WEB-INF/jboss-deployment-structure.xml is missing a / from a closing deployment tag :)

    ReplyDelete