glassfish
  1. glassfish
  2. GLASSFISH-11764

EJBContainer#createEJBContainer() does not consider full classpath

    Details

      Description

      The contract for EJBContainer#createEJBContainer() says:

      "JVM classpath is searched for all ejb-jars or exploded ejb-jars in directory
      format."

      The "JVM classpath" in this documentation is presumably intended to be what the
      EJB 3.1 specification says:

      "By default, the embeddable container searches the JVM classpath (the value of
      the Java System property java.class.path) to find the set of EJB modules for
      initialization."

      That happens to be a really narrow version of what any given JVM classpath
      usually is in reality. A pragmatic definition of classpath also includes the
      set of all "reachable" classpath entries present in a jar file's MANIFEST.MF
      Class-Path entry.

      IMHO the classpath scanning mechanism in EJBContainer should take into account
      the full set of classpath entries (including those reachable from a Class-Path
      manifest header), not just the value in System.getProperty("java.class.path"),
      since that is what programmers expect.

      Finally, most Maven tests run by building up such a classpath in an otherwise
      empty "booter" jar file. Test cases that launch in this manner will not be able
      to discover EJBs on the classpath without manual intervention until this bug is
      fixed.

      The full discussion of this issue is available at
      http://forums.java.net/jive/thread.jspa?threadID=78213&start=0&tstart=0.

        Activity

        ljnelson created issue -
        Hide
        Alexis MP added a comment -

        cc

        Show
        Alexis MP added a comment - cc
        Hide
        sirajg added a comment -

        cc

        Show
        sirajg added a comment - cc
        Hide
        Amy Roh added a comment -

        assign to marina

        Show
        Amy Roh added a comment - assign to marina
        Hide
        ksak added a comment -

        Yes, agree this is ambiguous in the EJB spec. It will have to be clarified in the next spec. This should work
        the same way manifest-classpath entries are handled for EE modules during deployment. Namely, that
        classes in .jars referenced from the manifest-classpath of a module (and their recursive manifest-
        classpaths contents, etc.) are logically included in the set of classes for the original module. Note that the
        entries referenced from the manifest-classpath do not themselves define new modules. Their classes are
        merely processed as if they were physically packaged within the original module that appears on the jvm
        classpath.

        Show
        ksak added a comment - Yes, agree this is ambiguous in the EJB spec. It will have to be clarified in the next spec. This should work the same way manifest-classpath entries are handled for EE modules during deployment. Namely, that classes in .jars referenced from the manifest-classpath of a module (and their recursive manifest- classpaths contents, etc.) are logically included in the set of classes for the original module. Note that the entries referenced from the manifest-classpath do not themselves define new modules. Their classes are merely processed as if they were physically packaged within the original module that appears on the jvm classpath.
        Hide
        ljnelson added a comment -

        OK, so take Maven, which when its surefire-plugin (a JUnit runner, basically)
        runs in <forkMode>always</forkMode> mode always builds one jar file in /tmp that
        contains a Manifest Class-Path entry. This is pervasive throughout commercial
        enterprise Java development.

        You're saying-and I don't necessarily disagree with this-that as far as
        Glassfish is concerned, it will effectively discover the mother of all EJB jars,
        which will just happen to be this empty surefire jar? So ejb-jar.xml files
        sprinkled throughout the jars it references are ignored?

        Coming at this a different way for a moment, I wonder what the value of
        ClassLoader.getResources("META-INF/ejb-jar.xml") would be in such a case (never
        tried it). I would argue that if it returns many URLs, then the EJB spec should
        follow this behavior (i.e. contrary to your assertion I'd expect many modules to
        be defined). If it returns one, then I would agree with your assertion.

        Having been burned by Manifest Class-Paths in the past, I seem to recall that
        the magic that computes the set and the effective classpath doesn't just make it
        look like referenced jars are somehow included as though they were packaged in
        the original jar file; it is more like it adds URLs to a URLClassLoader (even
        though as far as I can recall that's not actually what happens).

        Show
        ljnelson added a comment - OK, so take Maven, which when its surefire-plugin (a JUnit runner, basically) runs in <forkMode>always</forkMode> mode always builds one jar file in /tmp that contains a Manifest Class-Path entry. This is pervasive throughout commercial enterprise Java development. You're saying- and I don't necessarily disagree with this -that as far as Glassfish is concerned, it will effectively discover the mother of all EJB jars, which will just happen to be this empty surefire jar? So ejb-jar.xml files sprinkled throughout the jars it references are ignored? Coming at this a different way for a moment, I wonder what the value of ClassLoader.getResources("META-INF/ejb-jar.xml") would be in such a case (never tried it). I would argue that if it returns many URLs, then the EJB spec should follow this behavior (i.e. contrary to your assertion I'd expect many modules to be defined). If it returns one, then I would agree with your assertion. Having been burned by Manifest Class-Paths in the past, I seem to recall that the magic that computes the set and the effective classpath doesn't just make it look like referenced jars are somehow included as though they were packaged in the original jar file; it is more like it adds URLs to a URLClassLoader (even though as far as I can recall that's not actually what happens).
        Hide
        ljnelson added a comment -

        Retract my previous comment, please; I misread your statement.

        Show
        ljnelson added a comment - Retract my previous comment, please; I misread your statement.
        Hide
        marina vatkina added a comment -

        Reassign to deployment to verify that they process manifest entry references

        Show
        marina vatkina added a comment - Reassign to deployment to verify that they process manifest entry references
        Hide
        Hong Zhang added a comment -

        scrubbing issues

        Show
        Hong Zhang added a comment - scrubbing issues
        Hide
        Hong Zhang added a comment -

        The deployment now supports absolute URL in the Class-Path attribute. Assign to
        ejb team to see if there is any remaining work from ejb container to get the
        use case work with embedded ejb container.

        Show
        Hong Zhang added a comment - The deployment now supports absolute URL in the Class-Path attribute. Assign to ejb team to see if there is any remaining work from ejb container to get the use case work with embedded ejb container.
        Hide
        marina vatkina added a comment -

        Reassigning back to deployment to resolve:
        a) a jar with a PU referenced in the class-path
        b) GenericAnnotationDetector.hasAnnotationInArchive to look at the manifest
        class-path

        Show
        marina vatkina added a comment - Reassigning back to deployment to resolve: a) a jar with a PU referenced in the class-path b) GenericAnnotationDetector.hasAnnotationInArchive to look at the manifest class-path
        Hide
        Hong Zhang added a comment -

        I can fix b) here which is only invoked in the embedded code path.

        But for a) to be fixed, we need to look at META-INF/persistence.xml in the
        referenced jar. And more general, we need to start looking for deployment
        descriptors in the library jars. I am not sure if that's what we want to do.
        Let's having more discussions before we decide what to do. I am going to change
        the target milestone to 3.2 (if we do decide to support it, we will need quite
        some changes).

        Show
        Hong Zhang added a comment - I can fix b) here which is only invoked in the embedded code path. But for a) to be fixed, we need to look at META-INF/persistence.xml in the referenced jar. And more general, we need to start looking for deployment descriptors in the library jars. I am not sure if that's what we want to do. Let's having more discussions before we decide what to do. I am going to change the target milestone to 3.2 (if we do decide to support it, we will need quite some changes).
        Hide
        Hong Zhang added a comment -

        Reading the EE 6 spec (section 8.2.1, quoted at the end), it says the
        depoloyment descriptor in the library jar must be ignored:
        "Any deployment descriptors in referenced .jar files must be ignored when
        processing the referencing .jar file."

        Also:
        Top level JAR files that are processed by a deployment tool should not contain
        Class-Path entries; such entries would, by definition, reference other files
        external to the deployment unit. A deployment tool is not required to process
        such external reference

        I think the next version of the EJB spec must do some clarifications to
        override the above EE spec section before we do something in the implementation
        to support the use case.

        ============================================================================
        EE.8.2.1 Bundled Libraries
        Libraries bundled with an application may be referenced in the following ways:
        A JAR format file (such as a .jar file, .war file, or .rar file) may reference
        a .jar file or directory by naming the referenced .jar file or directory in a
        Class-Path header in the referencing JAR file’s Manifest file. The
        referenced .jar file or directory is named using a URL relative to the URL of
        the referencing JAR file. The Manifest file is named META-INF/MANIFEST.MF in
        the JAR file. The Class-Path entry in the Manifest file is of the form
        Class-Path: list-of-jar-files-or-directories-separated-by-spaces
        (See the JAR File Specification for important details and limitations of the
        syntax of Class-Path headers.) The Java EE deployment tools must process all
        such referenced files and directories when processing a Java EE module. Any
        deployment descriptors in referenced .jar files must be ignored when processing
        the referencing .jar file. The deployment tool must install the .jar files and
        directories in a way that preserves the relative references between the files.
        Typically this is done by installing the .jar files into a directory hierarchy
        that matches the original application directory hierarchy. All referenced .jar
        files or directories must appear in the logical class path of the referencing
        JAR files at runtime.
        Only JAR format files or directories containing class files or resources to be
        loaded directly by a standard class loader should be the target of a Class-Path
        reference; such files are always named with a .jar extension. Top level JAR
        files that are processed by a deployment tool should not contain Class-Path
        entries; such entries would, by definition, reference other files external to
        the deployment unit. A deployment tool is not required to process such external
        reference.
        =============================================================================

        Show
        Hong Zhang added a comment - Reading the EE 6 spec (section 8.2.1, quoted at the end), it says the depoloyment descriptor in the library jar must be ignored: "Any deployment descriptors in referenced .jar files must be ignored when processing the referencing .jar file." Also: Top level JAR files that are processed by a deployment tool should not contain Class-Path entries; such entries would, by definition, reference other files external to the deployment unit. A deployment tool is not required to process such external reference I think the next version of the EJB spec must do some clarifications to override the above EE spec section before we do something in the implementation to support the use case. ============================================================================ EE.8.2.1 Bundled Libraries Libraries bundled with an application may be referenced in the following ways: A JAR format file (such as a .jar file, .war file, or .rar file) may reference a .jar file or directory by naming the referenced .jar file or directory in a Class-Path header in the referencing JAR file’s Manifest file. The referenced .jar file or directory is named using a URL relative to the URL of the referencing JAR file. The Manifest file is named META-INF/MANIFEST.MF in the JAR file. The Class-Path entry in the Manifest file is of the form Class-Path: list-of-jar-files-or-directories-separated-by-spaces (See the JAR File Specification for important details and limitations of the syntax of Class-Path headers.) The Java EE deployment tools must process all such referenced files and directories when processing a Java EE module. Any deployment descriptors in referenced .jar files must be ignored when processing the referencing .jar file. The deployment tool must install the .jar files and directories in a way that preserves the relative references between the files. Typically this is done by installing the .jar files into a directory hierarchy that matches the original application directory hierarchy. All referenced .jar files or directories must appear in the logical class path of the referencing JAR files at runtime. Only JAR format files or directories containing class files or resources to be loaded directly by a standard class loader should be the target of a Class-Path reference; such files are always named with a .jar extension. Top level JAR files that are processed by a deployment tool should not contain Class-Path entries; such entries would, by definition, reference other files external to the deployment unit. A deployment tool is not required to process such external reference. =============================================================================
        Hide
        marina vatkina added a comment -

        There will be more things to sort out with a jar wrapping an Java EE module via
        Class-Path ref: the module name of an EJB module (with the lack of deployment
        descriptors processing in the referenced jars) becomes that of the wrapping jar.

        Show
        marina vatkina added a comment - There will be more things to sort out with a jar wrapping an Java EE module via Class-Path ref: the module name of an EJB module (with the lack of deployment descriptors processing in the referenced jars) becomes that of the wrapping jar.
        kenaiadmin made changes -
        Field Original Value New Value
        issue.field.bugzillaimportkey 11764 43368
        Hong Zhang made changes -
        Fix Version/s future release [ 11148 ]
        Fix Version/s 3.2 [ 10969 ]
        prasads made changes -
        Tags 3_1-exclude 3_1-exclude javaee_ri_target

          People

          • Assignee:
            Hong Zhang
            Reporter:
            ljnelson
          • Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated: