Drools 6 and EJB

This is about how to package an ear file so that it includes Drools rules. If that sentence means nothing at all to you then you might want to skip this.

We have an existing application, packaged in an ear file and it has a load of EJBs. I’ve never had to have much to do with EJBs, I mostly rejected the whole horrible business long ago and made my way using Spring injection. However this application took a different route. It has a directory structure (in the ear file) that looks like this:

  • lib
  • META-INF
  • xzy.ejb3
  • xyz.war

This is all normal enough. The lib directory contains the dependent jar files, META-INF contains the usual xml files, the war file contains normal war file things and the ejb3 file contains all the ejbs.

The ejb3 file is the interesting one. It is a ‘shade’ file, built by pulling apart various jar files and repackaging them into this ejb3 file. Internally it looks like a jar file. I find this kind of ugly but it seems to be necessary for the EJBs inside it to work.

Also in that ejb3 file is a bunch of drl files that define the Drools rules, and some support code to ensure they get compiled and deployed correctly. Actually this is quite complicated stuff because the objective (more of a hope than an objective really) is to be able to distribute different rules packages for different sites and the code has to select and deploy the right set of rules based on external parameters. It has never worked.

But with the advent of Drools V6 there was the opportunity to rework this. We planned to keep the rules outside the ear file and deploy them as maven artifacts which Drools V6 can load dynamically. We could then distribute a single ear file to all sites and only vary the maven artifacts.

I got this working but the deployment issues (ie deploying that repo) proved too scary so I reverted to keeping the rules inside the ear file. However, they are in their own jar files, so that means to build for a different site we just invoke a different maven profile that refers to slightly different dependencies. Now we have different ear files, but they are easy enough to build and we have no deployment issues. Good.

Well, it was good until I tried to build the ear file. As I said I have the rules in their own jar files, and I have projects for those jar files with unit tests and all that good stuff. They build their jars and publish them to maven ready for the main application build to pull them in as dependencies. And that’s where it goes wrong.

To be clear, if there were only drl files in my rules projects, there would have been no problem. The rules jarfiles would get put into the lib directory and everything would work. But I also have some Java code in there. It needs to be in that project because, like the rules, it is site specific. But it refers to various entity beans etc that are inside the ejb3 file. When I run this with unit tests I just have the relevant jar files that go into the ejb3 file as dependencies, but I’m not using EJB in my unit tests so there aren’t any EJB complications.

I tried putting the rules+code jar files into the lib directory and they refused to find various objects defined in ejb3. I tried putting them into ejb3 and that would have worked if I had only one rules jar file but I actually have two. When repackaged into an ejb3 file I get only one kmodule.xml file in META-INF because they overwrite. Fair enough. Drools expects you to keep the jar packaging intact not mess with it like this (I did say that ejb3 file was ugly). And I do need both of those kmodule files.

It takes me a while to see what is now obvious. I needed to split the outputs of the rules projects into java and rules and package the two differently. Here’s what I put in my pom.xml file:

<plugin>
<artifactid>maven-jar-plugin</artifactid>
<executions>
<execution>
<id>only-library</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>only-library</classifier>
<includes>
<include>**/*.class</include>
</includes>
</configuration>
</execution>
<execution>
<id>only-rules</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>only-rules</classifier>
<excludes>
<exclude>**/*.class</exclude>
</excludes>
</configuration>
</execution>
</executions></plugin>

The result is two jar files identified by their classifiers. The build of the ear file is too gory to go into in any depth here but the /lib directory needs to contain the only-rules jar and the ejb3 needs to contain the only-library jar (unpacked and repackaged).

To tell maven which one you want is quite simple:

<dependency>

<classifier>only-rules</classifier>
</dependency>

As a solution this is all pretty horrid. There are plenty of people who will tell you splitting the output into two jar file is some kind of heresy, but sometimes you have to do this kind of thing to make it work.

Leave a Reply

Your email address will not be published. Required fields are marked *