4 Replies Latest reply on Sep 12, 2005 12:36 PM by reidmp

    How to deal with dependencies between JCA adaptors?

    reidmp

      I've run into a wierd problem with a pair of JCA adaptors that I created and have working on Weblogic, and kinda working on JBoss. By "kinda" I mean (described below) I can coax the adaptors into working, but normally I get an IllegalAccessException.

      Background
      --------------

      Adaptor 1: RealConnector (name changed to protect the guilty)
      Adaptor 2: ProxyConnector (ditto about the name)

      The idea is that RealConnector is deployed on a J2EE instance that really has access to some device or service. On the other hand ProxyConnector is deployed for instances that don't have direct access to the device. A servlet is deployed with RealConnector that ProxyConnector can talk to. Both the RealConnector and ProxyConnector have rar files and *-service.xml files for configuration.

      Both rar files have almost identical collections of Java files, because both RealConnector and ProxyConnector do a lot of the same things (except for the actual mechanics of talking to the external device).

      The easiest and most obvious way of testing this is to deploy RealConnector, ProxyConnector, and the servlet all on the same J2EE instance and create JUnit tests to stuff requests through the proxy to see what happens. The problem is that this causes an IllegalAccessException in JBoss (3.2.7), but only in one particular situation (the situation you'd most likely want to use).

      If you put both rar files and both *-service.xml files in the deploy directory and start JBoss then you get IllegalAccessException.

      If you put both rar files in deploy, but not the service files, start JBoss, and *slowly* put first one and then the other service file in deploy (waiting until log messages prove the mbean deployment is done), then both the JCA adaptor mbeans initialize just fine. YOU HAVE TO DO THIS EVERY TIME YOU START JBOSS. Restarting after you have the adaptors working just gets you back to the original problem of IllegalAccessException.

      What I've tried:

      * made sure there aren't library compatibility issues between JBoss and the code (it really only depends on its own code and standard Java/J2EE packages).

      * piles of code changes, like commenting out the place where the IllegalAccessException appears - but it just moves around

      * clean builds to make sure it wasn't a compilation problem, also tried two different JDK 1.4 compilers just in case of a compiler bug

      * specifying a loader-repository in the *-service.xml files for each adaptor

      * specifying a dependency between the *-service.xml files in the hope that it would cause one to cleanly deploy before the second one even started, but it didn't seem to work.

      I'm running out of ideas. Not having mucked around that much with the details of JBoss mbean xml file configuration, one thing I'm wondering is if I specified the dependency information properly. Below is a (slightly altered) initial portion of the file for RealConnector. The file for ProxyConnector is identical except for obvious word substitutions (Real/Proxy, real/proxy) and the fact that the proxy service doesn't specify a dependency on the real service. Right about now somebody is probably about to jump up and say "that dependency is backwards"; I know. By experiment I found that deploying the Proxy first, then the Real version was what consistently worked, not the other way around (I have no idea why).

      My attempt at specifying a dependency is just above the RARDeployer dependency.

      <?xml version='1.0' encoding='UTF-8'?>
      <server>
       <loader-repository>
       com.mycompany:loader=connector-real.rar
       <loader-repository-config>
       java2ParentDelegation=false
       </loader-repository-config>
       </loader-repository>
       <mbean code='org.jboss.resource.connectionmanager.NoTxConnectionManager'
       name='jboss.jca:service=NoTxCM,name=connectorReal'>
       <attribute name='JndiName'>ra/connectorReal</attribute>
       <depends>jboss.jca:service=NoTxCM,name=connectorProxy</depends>
       <depends>jboss.jca:service=RARDeployer</depends>
       <depends optional-attribute-name='ManagedConnectionPool'>
       <mbean code='org.jboss.resource.connectionmanager.JBossManagedConnectionPool'
       name='jboss.jca:service=NoTxPool,name=connectorReal'>
       <depends optional-attribute-name='ManagedConnectionFactoryName'>
       <mbean code='org.jboss.resource.connectionmanager.RARDeployment'
       name='jboss.jca:service=NoTxPF,name=connectorReal'>
      







          • 1. Re: How to deal with dependencies between JCA adaptors?
            khawkins

            Make sure you don't have classes from the same package in different jar files. Each jar file in each resource adapter will be loaded by a different class loader. If a class in jarA tries to access a package private member of a class in the same package but in jarB you will get an IllegalAccessException because the classes were loaded by different class loaders.

            • 2. Re: How to deal with dependencies between JCA adaptors?
              reidmp

              That sounds like the problem, although one aspect of your description of the situation confuses me. If each adapter has its own classloader, then doesn't it have its own copies of the classes? Maybe I'm running into the JBoss classloader-vs-repository distinction. I'm wondering if maybe I didn't set up the loader repository definitions properly, and that is causing the same stuff to be visible to both classloaders. In one adapter I have:


              <loader-repository>
               com.mycompany:loader=connector-real.rar
              <loader-repository>
              


              In the other adapter I have:

              <loader-repository>
               com.mycompany:loader=connector-proxy.rar
              <loader-repository>
              


              I'd assumed that the whole string determined the repository name. Is it just the portion before ":" that determines the repository name? If so, then I probably needed "com.mycompany.real" versus "com.mycompany.proxy" or some such.


              • 3. Re: How to deal with dependencies between JCA adaptors?
                khawkins

                Each JAR file in each of your RAR files will have its own class loader. If two RARs contain a common jar, each has its own copy of the classes in that jar: shouldn't be a problem. The IllegalAccessException can occur like this:

                RarA contains JarA and JarB.

                JarA contains class:

                package com.mycompany;
                public class ClassA {
                 int packagePrivateInt = 0;
                }
                


                JarB contains class:
                package com.mycompany;
                public class ClassB {
                 ClassA classA;
                 ClassB(ClassA a) {
                 classA = a;
                 }
                 void someMethod() {
                 classA.packagePrivateInt = 1; // (il)legal!
                 }
                }
                


                The statement in someMethod is generally legal: both classes are in the same package and can access each other's default (package private) members.

                However, if they are loaded by different class loaders they are no longer considered in the same package and the statement in someMethod will throw an IllegalAccessException at run time.


                • 4. Re: How to deal with dependencies between JCA adaptors?
                  reidmp

                  Unfortunately, even though each RAR does have its own
                  JAR, I am still hitting the IllegalAccessException. I tried
                  also changing names on the class repositories to see if
                  that helped, but it didn't. I'm inclined to think that this
                  may be a JBoss bug.