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.