6 Replies Latest reply on Dec 16, 2002 2:13 PM by erik777

    ClassLoader Question

    brall

      I am using Jboss 3.0.3 with Tomcat 4.1x. I am having problems with classes that exist in multiple jars/wars deployed to the server. It seems that if the class is loaded by an ejb jar before by a war package, the servlet container will use the previously loaded version of the class. Is this the expected behavior? Does this only affect war deployments? Is there a way around this problem? I seem to get the same behavior if I package the wars and jars in an ear as well.
      Thanks,
      --BRALL

        • 1. Re: ClassLoader Question
          slaboure

          yes, that's the expected behaviour in 3.x: it is called UCL, UnifiedClassLoader.

          If you don't want this, take a look at the 3.0 admin guide and read about "scoped UCL" (you can set a tag in the deployment descriptor of any EAR)

          • 2. Re: ClassLoader Question
            brall

            Thank you for the response, that helps. Is there a way to use a scoped class loaded for a war or jar? The UCL classloader is causing me problems because of resource loading. For example, some of the classes that are in multiple packages are utility package that rely on a deployment specific resource file to configure their behavior for each package. So when my utility tires to start in package A it will get the resource file from the first package that it was loaded or often the resource comes back null. Any suggestions would be of great help.

            • 3. Re: ClassLoader Question
              erik777

              I am having a similar problem, and may benefit from the same solution if it is possible.

              I am deploying two WAR files, the contents of which can be viewed as stacks

              SEC WAR
              =======
              STACK #1: lib\Global.jar
              STACK #2: classes\SecurityShared...
              STACK #3: classes\SecurityApp...
              STACK #4: Security JSPs

              MainApp WAR
              ===========
              STACK #1: lib\Global.jar
              STACK #2: classes\SecurityShared...
              STACK #3: classes\MainApp...
              STACK #4: MainApp JSPs

              I am having a problem mostly in certain JSPs in the MainApp WAR where it passes a MainApp class that implements an interface from Global.jar to a Security class, which is a subclass of a class in Global.jar, thus the Global.jar parent in Stack #1 eventually uses the interface implemented in Stack #3 and instantiated in Stack #4 to do certain manipulations.

              Here's a summary: An interface (I1) defined in Stack #1 is implemented in Stack #3 by a class (C1) that is also a subclass of another class in Stack #1. This class is instantiated in Stack #4, and passed to another class (C2) instantiated in Stack #4. C2 is defined in Stack #2 and is a subclass of a class in Stack #1. C2 passes C1 to its supers, until you are completely in Stack #1, where the error always occurs.

              I've discovered the runtime errors (e.g., java.lang.IncompatibleClassChangeError) can be prevented if I access JSPs in SEC WAR that use this same technique BEFORE I access the JSPs in the MainApp WAR that do this. In other words, the access to SEC WAR must occur first after each deployment or restart of JBoss.

              However, if, after I deploy or restart JBoss, I access MainApp WAR first, then it blows up deep where the superclass in Global.jar accesses methods or data represented by the interface implemented in Stack #3 and instantiated in the JSP pages (Stack #4) and passed through the stacks. If it blows up, then it will continually fail on all five JSPs that do this in both WARs until I restart JBoss or redeploy, and access the JSPs in SEC WAR first.

              On the other hand, if I access one of two of the JSPs in the SEC WAR first, then all five JSPs in both apps work fine.

              The Global.jar in both WARs is exactly the same, and always the same compile (timestamp and all). Also, the security classes they share are also from the same compile. So, although these classes are duplicated between the WARs, the binaries are completely the same.

              I suspect this is a ClassLoader issue since the result depends on which JSP is compiled and run first.

              Please help me find a solution to get around this.

              Thank you!

              Erik

              • 4. Re: ClassLoader Question
                erik777

                As an addendum to the problem description, if MainApp WAR is accessed first when the app is deployed or JBoss is restarted, then it invokes the following error:

                java.lang.LinkageError: loader constraints violated when linking net/openstandards/standard/EFormData class
                at org.apache.jsp.includeOrganization$jsp._jspService(includeOrganization$jsp.java:229)
                at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:107)
                at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
                at org.apache.jasper.servlet.JspServlet$JspServletWrapper.service(JspServlet.java:201)
                at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:381)
                at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:473)

                Note that it does not generate this or any other error if JSPs in the SEC WAR app also using the EFormData interface (I1) are accessed first.

                Indeed, if this is how OpenStandards.net is running today. The error above was generated just by clicking on the Organizations menu options. However, it is running today because I accessed JSPs in the SEC WAR application first. I just have to hope I don't have to reboot the server, restart JBoss, or upgrade the application anytime soon.

                This code ran without any problems in JBoss 2.4.0/Tomcat 3.2.3. I am just having a problem with JBoss 3.0.4/Tomcat 4.0.6.

                Can someone please help? A new project is on hold, as it will rely on the application framework dependent on this interface. I at least need a work around I can code, so it will run without error 100% of the time without having to block users out to access JSPs in a certain order. Plus, it is critical I need to know that it will work with any new application. I'd hate to create a new application only to discover that there is no work around given the new application contexts.



                • 5. Re: ClassLoader Question
                  vinays

                  do both the wars belong to the same application? u cd try making deploying a single .ear file by taking out the global.jar file from both the wars and instead making a entry in their manifest.mf file. Or if they are separate apps, try creating two different ears.

                  hope this helps.

                  cheers
                  Vinay Salehithal

                  • 6. Re: ClassLoader Question
                    erik777

                    They are separate apps, and they are together. More accurately, Main App depends on Sec App, but doesn't access anything in the Sec App war. It just has a copy of the client classes.

                    SecApp.war --> SecApp.jar
                    MainApp.war --> SecApp.jar

                    SecApp is 100% dynamic application security, designed to service an unlimited # of applications. Because it has it's own user interface for dynamically defining security (roles, user, modules, etc,...), it uses the EFormData class interface, which enables me to quickly create front ends independent of the backend model. EFormData is defined in Global.jar, a reusable component independent of SecApp or MainApp. In addition to being in the libs of each .war, Global.jar is also deployed to JBoss independently, because it has server-side (EJB) utilities, such as an interface for email.

                    MainApp.war uses EFormData as part of a framework for rapidly creating user interfaces, such as the list of organizations you see when you click on the Organization link at OpenStandards.net, or the individual organizations you can also click on.

                    It also uses the client application security classes which ultimately access EJB beans in SecApp.jar. They are also tied into the client-side framework that uses EFormData.

                    It is EFormData interface that is giving me all my problems. The class loader chokes on this. Other times, it has given other related errors when a class simply calls a method on it. Perhaps polymorphism is throwing a wrench into the class loader in this particular case.

                    As for the EARs, I've never used them, and don't understand their effects. If I deploy them in separate EAR files, will MainApp.war still be able to access the EJBs in SecApp.jar?

                    Deploying them together, although techically possible, is not a good idea. The idea is that SecApp is deployed once on a server instance. Then individual apps are deployed that can utilize it like a service. I would not want to add unrelated applications to a single EAR just because they all happen to use the same application security.

                    EFormData actually has nothing to do with application security. Indeed, nothing defined in Global.jar is aware of security. It is used to integrate the front-end with the back-end in an abstract way. Classes that implement EFormData are responsible for loading their user input from HttpServletRequest, doing data conversions, and interacting with the backend (create, retrieve, update, delete). Beyond reading user input from HttpServletRequest, it is oblivious to the front-end technology. Also, although I use Entity Beans, it is capable of seamlessly integrating any back-end (e.g., XML).