6 Replies Latest reply on Apr 7, 2015 8:30 PM by jameslivingston

    WildFly 8.2.0/JBoss modules 1.3.3 ignores classpath in MANIFEST.MF

    jasipher

      We use a manifest-only jar file in our WAR and EAR files to control the order that jar files are searched for classes. When we issue patches, we put the modified class(es) in a separate jar file, add that jar file to the affected EAR or WAR file, and update the classpath in our manifest-only jar file to put the new patch at the beginning of the class path so that it will be used in place of the original class (which is still in the original jar file).

       

      For example, WEB-INF/lib will contain a single jar file named manifest.jar and sub-folders named 3rdparty, base, patch, and custom. The Class-Path entry in WEB-INF/lib/manifest.jar|META-INF/MANIFEST.MF looks like this:

      Class-Path: 3rdparty/manifest.jar patch/manifest.jar base/manifest.jar custom/manifest.jar

       

      When we publish a patch, the patch jar file is added to WEB-INF/lib/patch and to the front of the classpath in WEB-INF/lib/patch/manifest.jar's MANIFEST.MF.

       

      This worked fine for us for years with JBoss 4.2.3.GA, 5.1.0.GA, 7.1.2.Final, and 7.2.0.Final and we have a lot of infrastructure built around it. Now I'm trying to "upgrade" to WildFly 8.2.0.Final, and it looks like someone decided it would be OK to just ignore the classpath and load classes from any old random jar file.

       

      Is there anything I can do to get the old (correct!) behavior back??

       

      Here's what I see in the modules trace log for one of my problem classes

       

      Finding class my.package.NamingService from Module "deployment.service.ear.lib/patch/wmspatch.jar:main" from Service Module Loader

      Finding local class my.package.NamingService from Module "deployment.service.ear.lib/base/shared.jar:main" from Service Module Loader

      Loading class my.package.NamingService locally from Module "deployment.service.ear.lib/base/shared.jar:main" from Service Module Loader

       

      That class *should* be loaded from patch/patch.jar, not base/shared.jar. If I remove it from base/shared.jar it works OK, but I shouldn't have to do that.

       

      Message was edited by: John Sipher

        • 1. Re: WildFly 8.2.0/JBoss modules 1.3.3 ignores classpath in MANIFEST.MF
          ctomc

          I doubt this was intentional change, if anything it could be a regression.

           

          Can you create jira and attach simple reproducer for this?

          • 2. Re: WildFly 8.2.0/JBoss modules 1.3.3 ignores classpath in MANIFEST.MF
            jasipher

            I've been trying to create a "simple" example for two days but keep running into other classloader issues. I've documented those at [WFLY-4374] java.lang.IllegalAccessError and other classloader issues - JBoss Issue Tracker

            • 3. Re: WildFly 8.2.0/JBoss modules 1.3.3 ignores classpath in MANIFEST.MF
              jasipher

              I've verified that the problem still exists in WildFly 9.0.0.Beta2. Another issue has been fixed so that my simple hello world demo reproduces it. I've updated WFLY-4374

              to reflect that it affects 9.0.0.Beta2 and that it is now easily reproducible.

              • 4. Re: WildFly 8.2.0/JBoss modules 1.3.3 ignores classpath in MANIFEST.MF
                anindhyasharma

                Tomaz, the person handling the JIRA (David) noted that we take the discussion to the forum and not treat it as a bug. His last comment on the JIRA is "We will not fix this to be exactly how it was before, because the way we assemble modules makes this difficult/impractical"

                 

                This mechanism of using class-path for class loading different versions of the same class has worked for us in all previous versions of JBoss. It has worked not only in previous versions of JBoss but also other application servers we support. David mentions that both the old and new behaviors comply with Java EE spec. If that is the case, I would have thought that a particular feature not be taken away just like that in a new release...

                • 5. Re: WildFly 8.2.0/JBoss modules 1.3.3 ignores classpath in MANIFEST.MF
                  anindhyasharma

                  The Java EE 6 specification, section 8.2 Library Support and in it sub section 8.2.1 Bundled Libraries clearly states a JAR file may reference another JAR file using the Class-Path header in the manifest.

                   

                  The above is what we have done in previous versions too of JBoss and other vendor products and it works as noted.

                   

                  Here is an excerpt from the Wildfly documentation from the Developer's Guide, section on "Class Loading in Wildfly",

                  "If the ear-subdeployments-isolated is set to true then no automatic module dependencies between the sub-deployments are set up. User must manually setup the dependency with Class-Path entries, or by setting up explicit module dependencies."

                   

                  Further it goes on to state

                  "

                  Portability

                  The Java EE specification says that portable applications should not rely on sub deployments having access to other sub deployments unless an explicit Class-Path entry is set in the MANIFEST.MF. So portable applications should always use Class-Path entry to explicitly state their dependencies.

                  "

                   

                  So I am not sure how for Wildfly it can be stated that it meets EE specs (and your own documentation).

                  • 6. Re: WildFly 8.2.0/JBoss modules 1.3.3 ignores classpath in MANIFEST.MF
                    jameslivingston

                    To be clear, is the the use of package-private (default visibility) that related to the main complaint? If so, I believe David is correct.

                     

                    There are two different things which you may be conflating - visibility and accessibility. The EE specification sections that you are referring to are about visibility, and the classes are visible (unless shadowed by a class of the same name). If they were not visible, you would see a ClassNotFoundException rather than an IllegalAccessException.

                     

                    The IllegalAccessException is occurring because although the classes are visible, they and/or specific fields are not accessible to the other classes in the deployment. The specification covering that says that package-private things are only accessible to code in the same package, where package is defined as the pair of package name and classloader. That means if you have two classes belonging to a package of the same name but a different classloader, they will not be able to access each other's package-private things.

                     

                     

                    The EE specification says very little about the set up of classloaders, it instead talks about what must and must not be visible to various components (but also leaves a lot of that either undefined, or explicitly noted as being allowed to vary between implementations). When you have multiple jars in your EAR which refer to each other by Class-Path references, there is nothing which says they have to belong to the same classloader, and so have access to package-private items. This means that you cannot rely on package-private access outside of an individual jar[0].

                     

                    The Java EE specification purposely d es not define the exact types and arrangements of class loaders that must be used by a Java EE product. Instead, the specification defines requirements in terms of what classes must or must not be visible to components. A Java EE product is free to use whatever class loaders it chooses to meet these requirements. Portable applications must not depend on the types of class loaders used or the hierarchical arrangement of class loaders, if any.

                     

                     

                     

                    Many servers simply collect the transitive closure of jars and put them all into the same classloader, especially common for servers that had the "traditional" hierarchical classloader setup, but there is no requirement to do that. There are some down sides to that as well, since it means they can all see each other even if you don't want them to. You cannot for example put two different versions of the same library at the EAR level.

                     

                     

                     

                    It is also worth noting that the EE spec says:

                    Portable applications must not depend on the order in which classes and resources are loaded.

                    and refers to the JAR File Specification, which does not as far as I can tell say that the ordering of entries in Class-Path headers actually has an effect. So when you say that you put the patch jar in front of the other one in the Class-Path reference, I'm not sure that it is actually portable to rely on that.