[
http://jira.jboss.com/jira/browse/JBRULES-1212?page=comments#action_12379736 ]
Edson Tirelli commented on JBRULES-1212:
----------------------------------------
Alexander,
I just fixed
http://jira.jboss.com/jira/browse/JBRULES-1239 and I think your use case is
covered now. I developed 2 tests, as you can see bellow: one using thread context API and
the other using drools configuration classes:
public void testClassLoaderSwitchsUsingConf() throws Exception {
try {
// Creates first class loader and use it to load fact classes
ClassLoader loader1 = new SubvertedClassLoader( new
URL[]{getClass().getResource( "/" ).toURI().toURL()},
this.getClass().getClassLoader() );
Class cheeseClass = loader1.loadClass( "org.drools.Cheese" );
PackageBuilderConfiguration conf = new PackageBuilderConfiguration( loader1
);
PackageBuilder builder = new PackageBuilder( conf );
builder.addPackageFromDrl( new InputStreamReader(
getClass().getResourceAsStream( "test_Dynamic1.drl" ) ) );
// must set the classloader for rulebase conf too
RuleBaseConfiguration rbconf = new RuleBaseConfiguration( loader1 );
RuleBase ruleBase = RuleBaseFactory.newRuleBase( rbconf );
Package pkg = builder.getPackage();
ruleBase.addPackage( pkg );
StatefulSession wm = ruleBase.newStatefulSession();
wm.insert( cheeseClass.newInstance() );
wm.fireAllRules();
// Creates second class loader and use it to load fact classes
ClassLoader loader2 = new SubvertedClassLoader( new
URL[]{getClass().getResource( "/" ).toURI().toURL()},
this.getClass().getClassLoader() );
cheeseClass = loader2.loadClass( "org.drools.Cheese" );
conf = new PackageBuilderConfiguration( loader2 );
builder = new PackageBuilder( conf );
builder.addPackageFromDrl( new InputStreamReader(
getClass().getResourceAsStream( "test_Dynamic1.drl" ) ) );
rbconf = new RuleBaseConfiguration( loader2 );
ruleBase = RuleBaseFactory.newRuleBase( rbconf );
pkg = builder.getPackage();
ruleBase.addPackage( pkg );
wm = ruleBase.newStatefulSession();
wm.insert( cheeseClass.newInstance() );
wm.fireAllRules();
} catch ( ClassCastException cce ) {
cce.printStackTrace();
fail( "No ClassCastException should be raised." );
}
}
public void testClassLoaderSwitchsUsingContext() throws Exception {
try {
// Creates first class loader and use it to load fact classes
ClassLoader original = Thread.currentThread().getContextClassLoader();
ClassLoader loader1 = new SubvertedClassLoader( new
URL[]{getClass().getResource( "/" ).toURI().toURL()},
this.getClass().getClassLoader() );
Thread.currentThread().setContextClassLoader( loader1 );
Class cheeseClass = loader1.loadClass( "org.drools.Cheese" );
PackageBuilder builder = new PackageBuilder( );
builder.addPackageFromDrl( new InputStreamReader(
getClass().getResourceAsStream( "test_Dynamic1.drl" ) ) );
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
Package pkg = builder.getPackage();
ruleBase.addPackage( pkg );
StatefulSession wm = ruleBase.newStatefulSession();
wm.insert( cheeseClass.newInstance() );
wm.fireAllRules();
// Creates second class loader and use it to load fact classes
ClassLoader loader2 = new SubvertedClassLoader( new
URL[]{getClass().getResource( "/" ).toURI().toURL()},
this.getClass().getClassLoader() );
Thread.currentThread().setContextClassLoader( loader2 );
cheeseClass = loader2.loadClass( "org.drools.Cheese" );
builder = new PackageBuilder( );
builder.addPackageFromDrl( new InputStreamReader(
getClass().getResourceAsStream( "test_Dynamic1.drl" ) ) );
ruleBase = RuleBaseFactory.newRuleBase();
pkg = builder.getPackage();
ruleBase.addPackage( pkg );
wm = ruleBase.newStatefulSession();
wm.insert( cheeseClass.newInstance() );
wm.fireAllRules();
Thread.currentThread().setContextClassLoader( original );
} catch ( ClassCastException cce ) {
cce.printStackTrace();
fail( "No ClassCastException should be raised." );
}
}
public class SubvertedClassLoader extends URLClassLoader {
private static final long serialVersionUID = 400L;
public SubvertedClassLoader(final URL[] urls,
final ClassLoader parentClassLoader) {
super( urls,
parentClassLoader );
}
protected synchronized Class loadClass(String name,
boolean resolve) throws
ClassNotFoundException {
// First, check if the class has already been loaded
Class c = findLoadedClass( name );
if ( c == null ) {
try {
c = findClass( name );
} catch( ClassNotFoundException e ) {
c = super.loadClass( name, resolve );
}
}
return c;
}
}
Can you please try out and let us know if it covers your scenarios?
Thanks,
Edson
Rete throws NoClassDefFoundError when asserting facts with classess
loaded by inaccessible classloader.
--------------------------------------------------------------------------------------------------------
Key: JBRULES-1212
URL:
http://jira.jboss.com/jira/browse/JBRULES-1212
Project: JBoss Drools
Issue Type: Bug
Security Level: Public(Everyone can see)
Components: Reteoo
Affects Versions: 4.0.1
Reporter: Alexander Gavrilov
Assigned To: Mark Proctor
Fix For: 4.0.2
Attachments: ReteShadowProxyTest.java
We using drools as part of security enfocement engine in our application, based on
Tapestry4 framework. Tapestry4 pages and components is abstract classes with some abstract
methods, for which tapestry generates implementation at runtime. For example, if i declare
page
public abstract SomePage extends BasePage {
}
Tapestry will generate class in default package like
public SomePage$_0 extends BasePage {
}
On page loading whe using instantiated page objects ans Drools Facts to ensure, that
current user has permissions to load this page. In the previos verions we used (3.0.6) all
worked fine. After update to version 4.0.1 whe got the NoClassDefFoundError when triyng
to assert Page object into working memory.
This is becouse tapestry creates classes for pages in private classloader, which is child
of the application classloader. When Drools tries to generate shadowing proxy for
generated Page class it generate code like
public class SomePage$_0ShadowProxy extends SomePage$_0 {
}
Later, when it tries to load this class with MapBackedClassLoader, it can not find
definition for class SomePage$_0 and throws NoClassDefFoundError. This type of error does
not handled correctly by drools.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira