9 Replies Latest reply on Jan 28, 2009 2:54 PM by 7rond

    Class loading and Scoping issue with multiple wars outside of ear

    7rond

      Hello


      I've run into some issues here that I'm not quite sure I am going to go about figuring out. I'm working with implementing a CMS based on the Seam framework and so far it has been going great - but this issue with class loading is bothering me.


      First, how we're building and deploying our applications. The thought behind this is that we want the framework of the CMS to be deployed in a EAR on the server, and we want the web applications built on the CMS to be deployed as single, standalone WARs for easy and quick deployments. I've structured the problem a little something like this;


      - cms-framework.ear - this contains all the framework code for the CMS, including JPA entities, seam home implementations, seam query implementations and other CMS-specific code


      cms-admin.war - this contains the administration tool webapp for the CMS, it uses mostly code from cms-framework.ear, but it has some custom code, namely a overidden Identity class, defined as such (and deployed into WEB-INF/classes/ of this project):


      @Name("org.jboss.seam.security.identity")
      @Scope(ScopeType.SESSION)
      @Install(precedence = Install.DEPLOYMENT)
      @BypassInterceptors
      @Startup
      public class AdminIdentity extends Identity { }



      cms-testsite.war - this contains a simple site implementation based on the code in cms-framework.ear.


      I don't bundle any dependencies with my app, such as Seam and other dependent projects, all those dependencies are deployed into server/default/lib/ on my JBoss instance (4.2.3.GA)


      Now, about the actual problem. If I, inside my cms-testsite, for instance try to get a instance of the current Identity using either this in a Java file;


      @In private Identity identity




      ..or this in a JSF template;


      #{identity}




      I get a instance of the AdminIdentity class that's only deployed within the cms-admin.war. I've been going through the log data from the Seam initialization phase for both webapps, and I can clearly see that the overriden AdminIdentity is -not- loaded for the cms-testsite, but it is for the cms-admin.


      Now, my impression of this was that each webapp is supposed to be completely isolated. I have the following in the jboss-web.xml on both webapps;


      <!DOCTYPE jboss-web PUBLIC
          "-//JBoss//DTD Web Application 4.2//EN"
          "http://www.jboss.org/j2ee/dtd/jboss-web_4_2.dtd">
      <jboss-web>
      
              <class-loading java2ClassLoadingCompliance="false">
                      <loader-repository>
                              my.org:loader=<site id>
                              <loader-repository-config>java2ParentDelegation=false</loader-repository-config>
                      </loader-repository>
              </class-loading>
          
          <depends>jboss.j2ee:service=EARDeployment,url='cms-framework.ear'</depends>
          
      </jboss-web>




      I have no loader-repository defined in jboss-app.xml inside the EAR as that seems to break everything with the webapps not being able to read the classes inside the EAR.


      I'm not very familiar with how class loading internally works, and forgive me if I've made some apparent mistakes here, but I cannot understand why this is behaving the way it is. I've tested this on multiple versions of Seam, both 2.0.2, 2.0.3 and the new 2.1.0.CR1 and they all behave somewhat the same way.


      Will this way of bundling the project not work with Seam? Or am I doing anything wrong? I'm going to try to reproduce this by writing a small sample of the projects and uploading somewhere for people to see if they wish, I just wanted to post here beforehand to perhaps get some input on some mistakes I may have made that's leading to this.

        • 1. Re: Class loading and Scoping issue with multiple wars outside of ear
          gjeudy

          Have you checked out this info ?



          Note: As of at least JBoss 4.2.1, the <class-loading> tag appears to no longer be supported as isolation is ignored. Instead, the following configuration appears to accomplish the same goal:


          <jboss-web>
             <loader-repository>
                com.example:archive=unique-archive-name
             </loader-repository>
          </jboss-web>


          Interestingly enough, 4.0.5 seems to support both configurations.


          Check out this link for more info: ClassLoadingConfiguration

          • 2. Re: Class loading and Scoping issue with multiple wars outside of ear
            7rond

            I actually hadn't noticed that one, but I changed this now and it had no effect, the war-scoped Identity still applies to all wars it seems.

            • 3. Re: Class loading and Scoping issue with multiple wars outside of ear
              gjeudy

              Have you tried isolating the classloader for the EAR and including both WARs inside the EAR ? Just curious to see if that will work.

              • 4. Re: Class loading and Scoping issue with multiple wars outside of ear
                gjeudy

                it just hit me all of a sudden, have you tried bundling the seam libs into each war ?


                I don't think Seam can manage multiple wars, it should probably be deployed independently so that each WAR deployment loads its own version of Seam classes.

                • 5. Re: Class loading and Scoping issue with multiple wars outside of ear
                  7rond

                  I'll get to testing this shortly.


                  Curious observation I just did though, this does not seem to be a class loading issue at all, but a issue with Seam. My main problem has been getting a wrong instance of the Identity class injected into some Seam enabled classes. I just wrote this simple test;



                  @Name("classLoadingTest")
                  public class ClassLoadingTest {
                  
                       @Logger
                       private Log logger;
                  
                       @In
                       private Identity identity;
                  
                       public void doTest() {
                  
                            try {
                                 Class.forName("my.org.admin.AdminIdentity");
                            } catch (ClassNotFoundException e) {
                                 logger.warn("Unable to load AdminIdentity", e);
                            }
                            logger.info("Got identity #0", identity.toString());
                  
                       }
                  
                  }



                  When I call this from a commandButton or such in the cms-test.war, I actually get a ClassNotFoundException from Class.forName(), yet still, the instance of Identity injected to this class is a instance of my.org.admin.AdminIdentity.


                  Bundling Seam with the wars seems like the route to go as I really don't want to have to bundle these webapps into the ear - both for the sake of rapid development and production deployment processes not interfering with more than they have to. I appreciate the input though, I'll get to testing both of these suggestions asap.

                  • 6. Re: Class loading and Scoping issue with multiple wars outside of ear
                    7rond

                    Just to add it to the conversation I just think I fixed this.


                    Seems the problem was not classloading, not packaging, not anything - but the @Install precedence I had chosen to put on my Identity component overriding the Seam default component.


                    I had set this one to Install.DEPLOYMENT, kind of knowing that APPLICATION would be the right one, but I think I just put it to DEPLOYMENT thinking it was for this deployment, aka this .war and didn't think more of it. I just realized and just set everything to back the way it originally was, but set the precedence to Install.APPLICATION - and everything started behaving like it was supposed to the whole time.


                    That being said, if anybody know the reasoning behind this, I'd love to hear it. The manual says:



                    DEPLOYMENT — Precedence to use for components which override application components in a particular deployment


                    This does't really tell me much, I can kinda figure I shouldn't use it seeing the results, but always interesting to know the extent of ones actions.


                    Thank you, Guillaume, you kind of accidentally put me on the right track for the fix - and as another sidenote, Seam seems to operate just fine without bundling jars within each application. Hooray!

                    • 7. Re: Class loading and Scoping issue with multiple wars outside of ear
                      7rond

                      ..and after going to lie down on the couch after getting it running properly I just got the sentence in the manual to make sense.


                      I blame a week with long nights and little sleep :)

                      • 8. Re: Class loading and Scoping issue with multiple wars outside of ear
                        mcarrizo

                        Hi !! Are you developing an open source CMS ? Because Im needing one .....

                        • 9. Re: Class loading and Scoping issue with multiple wars outside of ear
                          7rond

                          I'm only in the early planning/draft stages for one, nothing finished or even public yet.