[rules-users] how to specify classpath dependencies in .drl files.

Godmar Back godmar at gmail.com
Tue Oct 2 09:40:34 EDT 2007


I don't know how to switch the compiler, but lLooking at the source, I
see that janino uses ClassLoaderIClassLoader,
http://fisheye.codehaus.org/browse/~raw,r=1.6/janino/janino/src/org/codehaus/janino/ClassLoaderIClassLoader.java
which in fact uses a reflection-based loader.

I believe I had already pointed out the problem with using reflection
to resolve external references: it can lead to unexpected first active
uses (in other words, using a class as a reference in compilation
could trigger the class's static {} initializer.) which may or may not
be tolerable (if the class is already loaded or has no static
initializer, it's not a problem - otherwise, it's a nightmare.)

In any event, this is all besides the point (at least the point I was
trying to make). I argue that a sound design should separate runtime
and compilation classpath (or at least provide the option of doing
so), but I acknowledge that the current approach is pragmatic and
probably works for a large number of cases.

To return to the original point of discussion, I'm wondering how to
make it easy for different .drl files to refer to each other. You had
brought up the Rule Agent, though it wasn't clear to me whether you
meant that the rule agent implementation as it currently exists
already has a way of specifying such dependencies, and if so, how - or
whether you are consider this a future addition.

>From my (admittedly brief) examination of the the rule agent, it
appears to be a tool that monitors filesystem or network-based sources
of rules in pre-compiled packages, then loads them.  What I am seeking
is a simple way for one rulebase to refer to a set of classes and
rules on which it depends, similar to how, for instance, an XML file
can refer to an external DTD or Schema.

 - Godmar

On 10/2/07, Mark Proctor <mproctor at codehaus.org> wrote:
>
>  try using janino instead of eclipse jdt
>
>
>  Godmar Back wrote:
>  PS: it turns out that Drool's class loader in
> org/drools/rule/PackageCompilationData.java falls back to
> getResource
> also (that's why I had to delete .class file in my first attempt at
> RLoader.) Installing a class loader that fails getResource() for
> .class files makes it even simpler to see that Drools's compilation
> machinery relies on it. So, to convince yourselves, use this loader:
>
> // RLoader.java, v2
> import java.io.File;
> import java.net.URL;
>
> public class RLoader extends ClassLoader {
>  public RLoader() { }
>  public RLoader(ClassLoader parent) { super(parent); }
>  public Class loadClass(String name) throws ClassNotFoundException {
>  return getParent().loadClass(name);
>  }
>
>  public URL getResource(String name) {
>  if (name.endsWith(".class")) {
>  System.out.println("Classloader asked for .class file as
> resource URL: " + name);
>  new Throwable().printStackTrace();
>  return null;
>  }
>  return getParent().getResource(name);
>  }
> }
>
> and you can observe the same failure - maybe this convinces you.
>
>  - Godmar
>
>
> On 9/27/07, Godmar Back <godmar at gmail.com> wrote:
>
>
>  On 9/27/07, Mark Proctor <mproctor at codehaus.org> wrote:
>
>
>  Godmar Back wrote:
>  I agree that it may not belong into the .drl file, though loading
> bytecode through the classloader via getResourceAsStream() also seems
> a rather ad-hoc solution.
>
>
>  I've already told you, that you are mistaken here. You do not need to keep
> bytecode hanging around, and available via getResourceAsStream() for any
> compilation to work. I can generate a class at runtime, in memory, add it
> to a classloader and have the engine compile against it without
> getResourceAsStream() being able to search for and return the .class'
> bytecode.
>
>
>  Ok - here's an experiment you can perform.
>
> Write a class loader RLoader.java as follows:
>
> // RLoader.java
> import java.io.File;
> import java.io.InputStream;
>
> public class RLoader extends ClassLoader {
>  public RLoader() { }
>  public RLoader(ClassLoader parent) { super(parent); }
>  public Class loadClass(String name) throws ClassNotFoundException {
>  return getParent().loadClass(name);
>  }
>  public InputStream getResourceAsStream(String name) {
>  if (name.endsWith(".class")) {
>  System.out.println("Classloader asked for .class file as
> resource: " + name);
>  new Throwable().printStackTrace();
>
>  // delete the .class file to ensure that no other part of
> drools attempts to read it.
>  new File(name).delete();
>  return null;
>  }
>  return getParent().getResourceAsStream(name);
>  }
> }
>
> Now use this class as your system class loader. Specify:
> -Djava.system.class.loader=RLoader
>
> When you then run your application, you will see output such as:
>
> Classloader asked for .class file as resource:
> org/enhancementpatterns/castor/CastorEnhancements/AddVisitor.class
> java.lang.Throwable
>  at RLoader.getResourceAsStream(RLoader.java:13)
>  at
> org.drools.rule.PackageCompilationData$PackageClassLoader.getResourceAsStream(PackageCompilationData.java:386)
>  at
> org.drools.commons.jci.compilers.EclipseJavaCompiler$2.isPackage(EclipseJavaCompiler.java:282)
>  at
> org.drools.commons.jci.compilers.EclipseJavaCompiler$2.isPackage(EclipseJavaCompiler.java:313)
>  at
> org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.isPackage(LookupEnvironment.java:1157)
>  at
> org.eclipse.jdt.internal.compiler.lookup.PackageBinding.findPackage(PackageBinding.java:75)
>  at
> org.eclipse.jdt.internal.compiler.lookup.PackageBinding.getTypeOrPackage(PackageBinding.java:190)
>  at
> org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope.findImport(CompilationUnitScope.java:438)
>  at
> org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope.findSingleImport(CompilationUnitScope.java:492)
>  at
> org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope.faultInImports(CompilationUnitScope.java:356)
>  at
> org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope.faultInTypes(CompilationUnitScope.java:425)
>  at
> org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:589)
>  at
> org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:411)
>  at
> org.drools.commons.jci.compilers.EclipseJavaCompiler.compile(EclipseJavaCompiler.java:353)
>  at
> org.drools.commons.jci.compilers.AbstractJavaCompiler.compile(AbstractJavaCompiler.java:51)
>  at
> org.drools.rule.builder.dialect.java.JavaDialect.compileAll(JavaDialect.java:332)
>  at
> org.drools.compiler.DialectRegistry.compileAll(DialectRegistry.java:60)
>  at
> org.drools.compiler.PackageBuilder.addPackage(PackageBuilder.java:288)
>  at
> org.drools.compiler.PackageBuilder.addPackageFromDrl(PackageBuilder.java:158)
>
> Leading to failures such as:
> Exception in thread "main"
> org.drools.rule.InvalidRulePackage: Rule
> Compilation error : [Rule name=Add Visitors, agendaGroup=MAIN,
> salience=0, no-loop=false]
> org/enhancementpatterns/castor/test/Rule_Add_Visitors_0.java
> (3:127) : Only a type can be imported.
> org.enhancementpatterns.castor.CastorEnhancements.AddVisitor
> resolves
> to a package
>
>  - Godmar
>
>
>  _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>
>
>
>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>
>



More information about the rules-users mailing list