[jboss-jira] [JBoss JIRA] Commented: (JBRULES-1212) Rete throws NoClassDefFoundError when asserting facts with classess loaded by inaccessible classloader.

Edson Tirelli (JIRA) jira-events at lists.jboss.org
Mon Oct 1 18:31:41 EDT 2007


    [ 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

        



More information about the jboss-jira mailing list