2 Replies Latest reply on Aug 22, 2006 8:00 AM by worenk

    Classloader separation between Webtier, EJBs and Container:

    worenk

      Hello everyone,

      I'm having troubles with JBoss 4.0.4 and its classloading mechanism in the default configuration.

      1) We are using several 3rd party libs that the JBoss container itself is using another version of (in server/default/lib). We'd prefer if JBoss libraries would not be visible to our applications, so we can use our own versions. Is this possible?

      2) Our EJB-client-classes are traditionally contained in both the WAR and our EJBs. Because there is no clear classloader separation between J2EE modules in JBoss, the classloader has troubles loading those (shared) classes, unless I exclude them from the WAR (which is client of our EJB). Is it possible to switch on clear classloader separation for J2EE modules, too?

      Regards,

      Andreas

        • 1. Re: Classloader separation between Webtier, EJBs and Contain
          asack

           

          "worenk" wrote:

          1) We are using several 3rd party libs that the JBoss container itself is using another version of (in server/default/lib). We'd prefer if JBoss libraries would not be visible to our applications, so we can use our own versions. Is this possible?


          I'm pretty you can't override system level dependencies. For example, when JBoss starts, the root classpath with have everything in $JBOSS_HOME/lib such as dom4j. If you want to use let's say XPath, i.e. jaxen.jar, you need to add that dependency in lib if you want it accessible.

          You can turn off JavaToParent delegation via a JBoss XML parameter (forgot what it was but look up ClassLoading in the WIKI Knowledge Base under the application server portal page) which may get around it, not sure.

          Its a shame classloading is so obscure in the spec.


          2) Our EJB-client-classes are traditionally contained in both the WAR and our EJBs. Because there is no clear classloader separation between J2EE modules in JBoss, the classloader has troubles loading those (shared) classes, unless I exclude them from the WAR (which is client of our EJB). Is it possible to switch on clear classloader separation for J2EE modules, too?


          Andreas, its good practice to not have the same classes laying around in different deployable entities (because to the classloader they will BE DIFFERENT classes causing all kinds of havoc).

          What you SHOULD DO is turn on EAR isolation/call by value during JBoss install (or edit the deployer.xml file afterward) so EARs are at least scoped.
          Besides being scoped, you can use JBoss specific parameters to setup a classloader repository per EAR (though if they are scoped, I'm not sure why this is neccessary).

          • 2. Re: Classloader separation between Webtier, EJBs and Contain
            worenk

             

            "asack" wrote:
            You can turn off JavaToParent delegation via a JBoss XML parameter (forgot what it was but look up ClassLoading in the WIKI Knowledge Base under the application server portal page) which may get around it, not sure.


            I tried this by adding

            <loader-repository>
             com.my:loader=my-ear
             <loader-repository-config>java2ParentDelegation=false</loader-repository-config>
            </loader-repository>


            to my jboss-app.xml.


            Andreas, its good practice to not have the same classes laying around in different deployable entities (because to the classloader they will BE DIFFERENT classes causing all kinds of havoc).


            Problem is that our J2EE come from a separate deployment environment, where everything is perfectly isolated by different JVMs. Of course in such an environment, some classes must be duplicate (e.g. EJB-client classes). Also, we have different versions of 3rd party libs in webtier and EJB tier.


            What you SHOULD DO is turn on EAR isolation/call by value during JBoss install (or edit the deployer.xml file afterward) so EARs are at least scoped.
            Besides being scoped, you can use JBoss specific parameters to setup a classloader repository per EAR (though if they are scoped, I'm not sure why this is neccessary).


            I tried this, but I always get an exception on EJB invocation:

            Caused by: java.lang.ClassCastException: $Proxy80
             at $Proxy56.create(Unknown Source)
             at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
             at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
             at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
             at java.lang.reflect.Method.invoke(Method.java:585)
             at
            org.springframework.ejb.access.AbstractSlsbInvokerInterceptor.create(AbstractSlsbInvokerInterceptor.java:174)


            I'm using Spring's SimpleRemoteStatelessSessionProxyFactoryBean pattern on the client side, but the DTOs that are being marshalled should not be replaced by a proxy, only the business interface itself. Strange.