Bug 827624

Summary: ClassCastException when fetching a package from Guvnor
Product: [JBoss] JBoss Enterprise BRMS Platform 5 Reporter: Hao Wu <hwu>
Component: BRM (Guvnor)Assignee: manstis
Status: VERIFIED --- QA Contact:
Severity: urgent Docs Contact:
Priority: unspecified    
Version: BRMS 5.3.0.GACC: manstis, mproctor
Target Milestone: ER9   
Target Release: BRMS 5.3.0.GA   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
The pkg file of the package snapshot none

Description Hao Wu 2012-06-01 21:32:41 UTC
Description of problem:
Using a simple test:
        @Test
        public void testDownloadPkg () throws Exception {
            String s = "http://localhost:8080/jboss-brms/org.drools.guvnor.Guvnor/package/TestPkg/snap";
            KnowledgePackage pkg = new KnowledgePackageImp(new HttpClientImpl().fetchPackage(new URL(s), true, "admin", "admin"));
        }

Got exception:
        java.lang.ClassCastException: [Lorg.drools.rule.Package; cannot be cast to org.drools.rule.Package
            at org.drools.agent.HttpClientImpl.fetchPackage(HttpClientImpl.java:82)
            at test.redhat.test.TestDownloadPkg.testDownloadPkg(TestDownloadPkg.java:15)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:601)
            at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
            at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
            at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
            at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
            at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
            at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
            at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
            at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
            at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
            at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
            at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
            at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
            at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
            at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
            at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
            at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
            at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
            at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Using classes in:
drools-core-5.3.0.BRMS-ER8.jar

Version-Release number of selected component (if applicable):
ER8

How reproducible:


Steps to Reproduce:
    1. Create a new package in Guvnor
    2. Create a new DRL rule and put something generic like
        when
        then
            System.out.println("test");
    3. Build and create a snapshot
    4. Run test
    5. Got exception
  
Actual results:
Exception show above

Expected results:
Download package successfully


Additional info:

Comment 1 Hao Wu 2012-06-03 03:07:50 UTC
Created attachment 588769 [details]
The pkg file of the package snapshot

Comment 2 Prakash Aradhya 2012-06-07 14:47:44 UTC
This is a customer bug and needs to be a blocker...

Comment 3 Geoffrey De Smet 2012-06-12 14:57:57 UTC
Michael,

I 've reproduced the issue in a unit test on master:
  https://github.com/droolsjbpm/guvnor/commit/e5a710e75fd37c5fea617d140487a023b6318699

Hao,

Normally, users/customers shouldn't use internal classes like HttpClientImpl and KnowledgePackageImp. They have no backwards compatibility guarantees.
Have you tried using the normal api in the knowledge-api module to fetch that KnowledgePackage? I am not sure which classes to use exactly, but Mark or Edson should know.

Comment 4 Geoffrey De Smet 2012-06-12 15:02:44 UTC
The bug is that the o on this line is an array of Package, instead of a Package:
  return (Package) o;

The L on this line signifies that actually:
[Lorg.drools.rule.Package; cannot be cast to org.drools.rule.Package

Comment 5 Mark Proctor 2012-06-12 15:28:51 UTC
HttpClassImpl is very old and only meant for the old RuleAgent class, which was deprecated some time ago. As a result it seems fixes made to KnowledgeAgentImpl to handle alternative serialised formats where not apply to HttpClassImpl. We will be removing legacy classes very soon, so I don't think we should fix this.

My first question though is why not use the KnowlegeAgent directly, rather than doing this sort of thing manually.

Anyway if you wish to continue doing manual serialisation, I would recommend using the ResourceFactory and then rip the relevant helper method from KnowledgeAgentImpl. I haven't checked that this compiles, but it shows you the idea:

private Collection<KnowledgePackage> createPackageFromResource(Resource resource)       
    InputStream is = null;
    Collection<KnowledgePackage> kpkgs = null;
    try {
        is = resource.getInputStream();
        Object object = DroolsStreamUtils.streamIn( is );
        if ( object instanceof Collection ) {
            kpkgs = (Collection<KnowledgePackage>) object;
        } else if ( object instanceof KnowledgePackageImp ) {
            kpkgs = Collections.singletonList( (KnowledgePackage) object );
        } else if( object instanceof Package ) {
            kpkgs = Collections.singletonList( (KnowledgePackage) new KnowledgePackageImp( (Package) object ) );
        } else if( object instanceof Package[] ) {
            kpkgs = new ArrayList<KnowledgePackage>();
            for( Package pkg : (Package[]) object ) {
                kpkgs.add( new KnowledgePackageImp( pkg ) );
            }
        } else {
            throw new RuntimeException("Unknown binary format trying to load resource "+resource.toString());
        }
    } catch ( Exception ex ) {
        this.listener.exception( new RuntimeException( "KnowledgeAgent exception while trying to deserialize KnowledgeDefinitionsPackage  ",
                                                       ex ) );
    } finally {
        try {
            if ( is != null ) {
                is.close();
            }
        } catch ( IOException e ) {
            this.listener.exception( new RuntimeException( "KnowledgeAgent exception while trying to close KnowledgeDefinitionsPackage  ",
                                                           e ) );
        }
    }
}

Comment 6 Mark Proctor 2012-06-12 15:46:57 UTC
I would add that RuleAgent at the moment is completely brocken. That this is the first time a problem has occured, is a good thing, it means no one has used it until now. And it is considered deprecated.

We can fix RuleAgent and related classes. But it involves changing method signatures and lots of instanceofs. Should we do this for a deprecated class, if this is the first customer who has a problem, and they now have a work around anyway?

Comment 7 Geoffrey De Smet 2012-06-12 15:55:36 UTC
Here's the code to build the Resource parameter in Mark's post from an URL:

        Resource res = ResourceFactory.newUrlResource(url);
        KnowledgeAgentConfiguration conf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
        Authenticator.setDefault(new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("admin", "admin".toCharArray());
            }
        });

Comment 8 manstis 2012-06-12 19:24:36 UTC
Recommendation is to move to use of KnowledgeAgent or use code based on KnowledgeAgentImpl (comment #5). No further action required by engineering.

Comment 9 Ryan Zhang 2012-06-13 09:32:53 UTC
This issue's fixes  have been picked by ER9. Please verify them on ER9.

Comment 10 Sona Mala 2012-06-19 14:59:16 UTC
Workaround is verified for ER9. 
The code of workaround:
  - the body of testDownloadPkg is comment #7
  - testDownloadPkg calls createPackageFromResource (comment #5)