RulesTomcat

Using JBoss Rules with JBoss or Tomcat

 

When you use JBoss Rules within an EAR or WAR file for deployment within JBoss or Tomcat you may encounter problems that are related to classpath issues between the version of the JDT that Tomcat uses (including the Tomcat embedded in JBoss Application Server) and the version of the JDT that JBoss Rules uses (specifically drools-compiler) to compile the Java snippets that make up the consequences in an XML or DRL file.

 

Symptoms

A typical message and stack trace will look something like the following:

11:09:02,671 ERROR [STDERR] java.lang.NoSuchMethodError: org.eclipse.jdt.internal.compiler.CompilationResult.getProblems
()[Lorg/eclipse/jdt/core/compiler/CategorizedProblem;
11:09:02,671 ERROR [STDERR]     at org.apache.commons.jci.compilers.EclipseJavaCompiler$2.acceptResult(EclipseJavaCompil
er.java:237)
11:09:02,671 ERROR [STDERR]     at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:335)
11:09:02,687 ERROR [STDERR]     at org.apache.commons.jci.compilers.EclipseJavaCompiler.compile(EclipseJavaCompiler.java
:268)
11:09:02,687 ERROR [STDERR]     at org.drools.compiler.PackageBuilder.compileAll(Unknown Source)
11:09:02,687 ERROR [STDERR]     at org.drools.compiler.PackageBuilder.addPackage(Unknown Source)
11:09:02,687 ERROR [STDERR]     at org.drools.compiler.PackageBuilder.addPackageFromDrl(Unknown Source)

and will occur at the point in your code where you attempt to add a package using the default package builder.

 

Solution

JBoss Rules uses the Apache JCI to interface to compilers which means we can switch to other compilers or versions.

 

There are several ways to enable the Janino compiler instead of JDT for Java semantics.

 

Using a Command Line Switch

 

Set the System property drools.compiler to JANINO. For example, -Ddrools.compiler=JANINO as a command line switch.

 

In Java Code

 

Use the following in your code in place of the default package builder:

 

Using Drools 3.x:

import org.drools.compiler.PackageBuilder;
import org.drools.compiler.PackageBuilderConfiguration;

PackageBuilderConfiguration pkgBuilderCfg = new PackageBuilderConfiguration();
pkgBuilderCfg.setCompiler(PackageBuilderConfiguration.JANINO);
PackageBuilder builder = new PackageBuilder(pkgBuilderCfg);
builder.addPackageFromDrl( source );

 

Using Drools 4.x:

import org.drools.compiler.PackageBuilder;
import org.drools.compiler.PackageBuilderConfiguration;

PackageBuilderConfiguration pkgBuilderCfg = new PackageBuilderConfiguration();
JavaDialectConfiguration javaConf = (JavaDialectConfiguration) pkgBuilderCfg.getDialectConfiguration( "java" );
javaConf.setCompiler( JavaDialectConfiguration.JANINO );
PackageBuilder builder = new PackageBuilder(pkgBuilderCfg);
builder.addPackageFromDrl( source );

 

Modifying your classloader config to use the JDT compiler

Include the following in the jboss-app.xml in the META-INF directory of the ear archive:

(for more details see ClassLoadingConfiguration)

 

<jboss-app>

  <loader-repository>org.jdt.eclipse:loader=unique-archive-name</loader-repository>

</jboss-app>

 

When using this method you might introduce other classloader issues you will have to resolve. For example, your EAR/WAR archive should not contain a copy of commons-logging.jar

 

Comments

 

It is expected that in future this should be resolved, as JCI will use whatever version of JDT is available on the classpath (Tomcat makes JDT available to applications running in it).

 

If you are building the rules externally to the app server, and then deploying them as binary objects (serialized RuleBase or Package, for instance) then this will not be an issue for you.