9 Replies Latest reply on Dec 21, 2006 4:14 PM by tarantula

    Resources.getResourceAsStream not multiple war safe

    rdewell

      CR2. If multiple WARs are in the same EAR, and both WARs are Seam applications, then this method impl causes problems.

      For example, one WAR is loading/seeing the pages.xml of the other WAR.

      Please let me know if you need additional information.

      Ryan


        • 1. Re: Resources.getResourceAsStream not multiple war safe
          gavin.king

          You'll need to set up scoped classloading then, I suppose.

          Not really a Seam issue.

          • 2. Re: Resources.getResourceAsStream not multiple war safe
            rdewell

            According to:

            http://wiki.jboss.org/wiki/Wiki.jsp?page=ClassLoadingConfiguration

            scoping only works at the top-most level, in this case the EAR. So, there's no way to scope off WARs from each other within the same EAR. You can only scope off one EAR from other EARs.

            Couldn't / shouldn't Seam check for web app specific files like those in WEB-INF using the servlet context FIRST:

            "stream = FacesContext.getCurrentInstance().getExternalContext()
            .getResourceAsStream(resource);"

            instead of LAST, as is currently the case?? This would appear to solve the problem.

            • 3. Re: Resources.getResourceAsStream not multiple war safe

              Gavin - this is a bug in Seam. The current Seam code just happens to work. The WAR classloader does not contain the entire WAR file. It only contains WEB-INF/classses and WEB-INF/lib/*.jar. When you read "/WEB-INF/pages.xml" from the WAR classloader, you are actually getting it from the parent classloader (the EAR classloader) which *DOES* include the WAR file contents in the classpath. (And I don't think this is required by the spec. I think this is just the way JBoss happens to work, but I could be wrong on that point)

              When you have two WAR files in the EAR and try to read pages.xml, no matter which WAR classloader is the context classloader, it goes to the EAR classloader in both cases. If the pages.xml is in both WARs, it's a toss up which one you get. But, you'll get the same one from both apps.

              This is a case where you definitely need to go to the ServletContext (going through FacesContext, as rdewell suggests is fine) so that you can read the file correctly out of the WAR.

              I think moving the FacesContext to the front of the list of places to check in util.Resources makes sense to me since there doesn't appear to be any way to NOT put the WAR file directly on the EAR classloader. (I don't understand why we do that though - it makes no sense and it has caused problems in HAR deployer too)

              • 4. Re: Resources.getResourceAsStream not multiple war safe
                gavin.king

                OK, I made your suggested fix in CVS. Please try it out. Thanks.

                • 5. Re: Resources.getResourceAsStream not multiple war safe
                  rdewell

                  This also is not multiple WAR (in one EAR) safe:

                   private static boolean exists = false;
                  
                   protected AbstractSeamPhaseListener()
                   {
                   if (exists) log.warn("There should only be one Seam phase listener per application");
                   exists=true;
                   }
                  


                  • 6. Re: Resources.getResourceAsStream not multiple war safe
                    gavin.king

                    Right, which is why I just log a warn instead of throwing an exception.

                    Sorry, best I can do. I _need_ that warning, it has tripped a lot of people.

                    • 7. Re: Resources.getResourceAsStream not multiple war safe
                      alesj

                       

                      "rdewell" wrote:
                      This also is not multiple WAR (in one EAR) safe:

                       private static boolean exists = false;
                      
                       protected AbstractSeamPhaseListener()
                       {
                       if (exists) log.warn("There should only be one Seam phase listener per application");
                       exists=true;
                       }
                      


                      It is not even EAR/WAR and outside (totally different app) WAR safe.

                      • 8. Re: Resources.getResourceAsStream not multiple war safe
                        gavin.king

                        It is as long as you set up classloader isolation, which you _need_ when using Seam.

                        If you can suggest some better approach, I am all ears. (Pun accidental.)

                        • 9. Re: Resources.getResourceAsStream not multiple war safe
                          tarantula

                          What about some notion of namespaces where Seam loads components separately for different web applications?

                          Could Seam scan ear-deployment/META-INF/application.xml and isolate components per web application?

                          It would be nice to have the option to share Seam components in an EJB JAR across web apps in an EAR deployment while still maintaining separation for Seam components declared within each web application.