glassfish
  1. glassfish
  2. GLASSFISH-14123

OSGi EJB deployment fails for bundles with a Bundle-ClassPath

    Details

    • Issuezilla Id:
      14,123

      Description

      I'm attempting to run Glassfish on Equinox and to deploy application bundles
      in-place directly from my Eclipse workspace (see the referenced forum message
      for more background).

      EJB bundles currently fail to deploy due to issues on both sides (i.e. Equinox
      and Glassfish).

      The Eclipse part of the problem:

      Workspace bundles get installed in OSGi as an unzipped directory, but the folder
      structure is not exactly the same as you would see in an unzipped JAR. Instead,
      you get the following:

      META-INF/
      bin/
      <other resources>

      All the classfiles are under bin/.

      Glassfish uses Bundle.getEntryPaths() to discover the bundle contents and to
      explode the bundle to a temp directory (I wonder why this is required).

      Now apparently for an entry "/bin/com/acme/Foo.class", Glassfish tries to load a
      class bin.com.acme.Foo and fails, so the bundle seems to have no classes at all
      and deployment fails.

      I've patched Equinox to change the getEntryPaths() behaviour in development
      mode, and this is a workaround for the problem. See
      https://bugs.eclipse.org/bugs/show_bug.cgi?id=160133.

      However, as pointed out in that bug, the default folder structure of Eclipse
      workspace bundles can be turned into a fully compliant OSGi bundle by simple
      adding a

      Bundle-Classpath: bin/, .

      to the manifest.

      I added this manifest entry manually, but Glassfish still fails to deploy the
      bundle, even when I zip it up as a JAR and install the JAR manually.

        Activity

        Hide
        Sanjeeb Sahoo added a comment -

        Herald,

        GlassFish explodes the bundle in its domain directory, because it tries to map a
        bundle packaged as per OSGi rules to a layout specified in Java EE specs.

        I don't think Bundle-ClassPath: bin, . is correct. Why is "." needed if every
        class and resource is actually in bin/ directory?

        Can you attach a test bundle.jar that demonstrates the problem for me to
        investigate further?

        Thanks,
        Sahoo

        Show
        Sanjeeb Sahoo added a comment - Herald, GlassFish explodes the bundle in its domain directory, because it tries to map a bundle packaged as per OSGi rules to a layout specified in Java EE specs. I don't think Bundle-ClassPath: bin, . is correct. Why is "." needed if every class and resource is actually in bin/ directory? Can you attach a test bundle.jar that demonstrates the problem for me to investigate further? Thanks, Sahoo
        Hide
        Harald Wellmann added a comment -

        Created an attachment (id=5228)
        Test bundle, including sources

        Show
        Harald Wellmann added a comment - Created an attachment (id=5228) Test bundle, including sources
        Hide
        Harald Wellmann added a comment -

        The attachment is a simple test bundle with a Bundle-ClassPath: bin (No "."
        included).

        I've also tested this bundle with Glassfish on Felix:

        Szenario 1:
        a) start GF on Felix
        b) telnet into the Gogo shell
        c) install the bundle from the shell
        d) start the bundle
        e) success: the bundle activator prints the results of getEntryPaths():

        g! install
        file:/home/hwellmann/workspace/3.6.1-glassfish/org.glassfish.test.bug14123.jar
        Bundle ID: 248
        g! start 248
        bin/
        META-INF/
        src/
        g!

        The bundle does not get recognized as an EJB bundle in this scenario, but at
        least this demonstrates that the bundle is valid, despite the Bundle-ClassPath.

        Szenario 2:
        a) start GF on Felix
        b) copy the test bundle to domains/domain1/autodeploy/bundles
        c) failure:

        [#|2010-10-26T11:57:24.714+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;|Failed
        to install artifact:
        /home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/org.glassfish.test.bug14123.jar:
        java.lang.NullPointerException|#]

        [#|2010-10-26T11:57:24.715+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;|java.lang.NullPointerException|#]

        [#|2010-10-26T11:57:24.715+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;|
        at
        org.apache.felix.fileinstall.internal.DirectoryWatcher.installOrUpdateBundle(DirectoryWatcher.java:924)|#]

        [#|2010-10-26T11:57:24.715+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;|
        at
        org.apache.felix.fileinstall.internal.DirectoryWatcher.install(DirectoryWatcher.java:872)|#]

        [#|2010-10-26T11:57:24.716+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;|
        at
        org.apache.felix.fileinstall.internal.DirectoryWatcher.install(DirectoryWatcher.java:785)|#]

        [#|2010-10-26T11:57:24.716+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;|
        at
        org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:423)|#]

        [#|2010-10-26T11:57:24.716+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;|
        at
        org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:241)|#]

        Show
        Harald Wellmann added a comment - The attachment is a simple test bundle with a Bundle-ClassPath: bin (No "." included). I've also tested this bundle with Glassfish on Felix: Szenario 1: a) start GF on Felix b) telnet into the Gogo shell c) install the bundle from the shell d) start the bundle e) success: the bundle activator prints the results of getEntryPaths(): g! install file:/home/hwellmann/workspace/3.6.1-glassfish/org.glassfish.test.bug14123.jar Bundle ID: 248 g! start 248 bin/ META-INF/ src/ g! The bundle does not get recognized as an EJB bundle in this scenario, but at least this demonstrates that the bundle is valid, despite the Bundle-ClassPath. Szenario 2: a) start GF on Felix b) copy the test bundle to domains/domain1/autodeploy/bundles c) failure: [#|2010-10-26T11:57:24.714+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;|Failed to install artifact: /home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/org.glassfish.test.bug14123.jar: java.lang.NullPointerException|#] [#|2010-10-26T11:57:24.715+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;|java.lang.NullPointerException|#] [#|2010-10-26T11:57:24.715+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;| at org.apache.felix.fileinstall.internal.DirectoryWatcher.installOrUpdateBundle(DirectoryWatcher.java:924)|#] [#|2010-10-26T11:57:24.715+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;| at org.apache.felix.fileinstall.internal.DirectoryWatcher.install(DirectoryWatcher.java:872)|#] [#|2010-10-26T11:57:24.716+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;| at org.apache.felix.fileinstall.internal.DirectoryWatcher.install(DirectoryWatcher.java:785)|#] [#|2010-10-26T11:57:24.716+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;| at org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:423)|#] [#|2010-10-26T11:57:24.716+0200|INFO|glassfish3.1|null|_ThreadID=75;_ThreadName=fileinstall-/home/hwellmann/glassfish-3.1-b24/glassfish/domains/domain1/autodeploy/bundles/;| at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:241)|#]
        Hide
        Sanjeeb Sahoo added a comment -

        Thanks a lot for attaching the test bundle. There are problems with both
        GlassFish as well as with the test bundle. First the test bundle issue:
        The attached jar is not a compliant jar. I wrote a simple java program as shown
        below to read its manifest and got null.

        class JarFileTester {
        public static void main(String[] args) throws Exception

        { URL url = new URL(args[0]); JarInputStream jis = new JarInputStream(url.openStream()); System.out.println(jis.getManifest()); // this prints null System.out.println(new JarFile(new File(url.getPath())).getManifest()); // this prints non-null }

        }

        As the comments above shows, if I open that jar as JarInputStream, the manifest
        is returned as null. The reason for this is that MANIFEST.MF is expected to be
        at the beginning of the stream, where as the attached jar violates this rule. I
        just exploded the jar file and repackaged it using "jar cvfm foo.jar
        META-INF/MANIFEST.MF ." command and now I can open read the manifest using
        JarInputStream. So, this settles the NPE issue reported by fileinstall when the
        bundle is copied to autodeploy/bundles/ directory.

        The second issue is about the bundle not being recognized as a EJB jar. This is
        a bug in GlassFish OSGi/EJB container and I shall use this bug to fix that issue
        (hopefully) soon.

        Show
        Sanjeeb Sahoo added a comment - Thanks a lot for attaching the test bundle. There are problems with both GlassFish as well as with the test bundle. First the test bundle issue: The attached jar is not a compliant jar. I wrote a simple java program as shown below to read its manifest and got null. class JarFileTester { public static void main(String[] args) throws Exception { URL url = new URL(args[0]); JarInputStream jis = new JarInputStream(url.openStream()); System.out.println(jis.getManifest()); // this prints null System.out.println(new JarFile(new File(url.getPath())).getManifest()); // this prints non-null } } As the comments above shows, if I open that jar as JarInputStream, the manifest is returned as null. The reason for this is that MANIFEST.MF is expected to be at the beginning of the stream, where as the attached jar violates this rule. I just exploded the jar file and repackaged it using "jar cvfm foo.jar META-INF/MANIFEST.MF ." command and now I can open read the manifest using JarInputStream. So, this settles the NPE issue reported by fileinstall when the bundle is copied to autodeploy/bundles/ directory. The second issue is about the bundle not being recognized as a EJB jar. This is a bug in GlassFish OSGi/EJB container and I shall use this bug to fix that issue (hopefully) soon.
        Hide
        Sanjeeb Sahoo added a comment -

        We were not correctly mapping an OSGi bundle with non-default Bundle-ClassPath
        to an archive. e.g., when a bundle has a Bundle-ClassPath: bin/, the mapped
        archive contained
        entries like bin/com/acme/MyBean.class although this class belongs to com.acme
        package.
        As a result, EJB sniffer was not able to find any EJBs. To fix the issue, we have
        now introduced an abstraction called EJBBundle similar to WAB. I refactored most
        of the code
        out of WAB to an abstract called OSGiJavaEEArchive and WAB as well as EJBBundle
        extend from that.
        As a result of this change, now even EJB bundles support fragments just like WAB.

        I also found minor issues in our effective bundle classpath computation logic.
        e.g., we were
        not handling whitespaces in BCP. Similarly, '.' was not handled correctly for
        host bundles.
        There was bug in the getManifest() logic - it could throw NPE. We also changed
        the getManifest()
        to always return the manifest of the host bundle. if host does not have a
        manifest, we return null.

        Adding
        osgi-javaee/osgi-ejb-container/src/main/java/org/glassfish/osgiejb/EJBBundle.java
        Sending
        osgi-javaee/osgi-ejb-container/src/main/java/org/glassfish/osgiejb/OSGiEJBDeploymentRequest.java
        Sending
        osgi-javaee/osgi-javaee-base/src/main/java/org/glassfish/osgijavaeebase/OSGiBundleArchive.java
        Adding
        osgi-javaee/osgi-javaee-base/src/main/java/org/glassfish/osgijavaeebase/OSGiJavaEEArchive.java
        Adding
        osgi-javaee/osgi-javaee-base/src/main/java/org/glassfish/osgijavaeebase/URIable.java
        Sending
        osgi-javaee/osgi-web-container/src/main/java/org/glassfish/osgiweb/WAB.java
        Transmitting file data ......
        Committed revision 42244.

        Thank you very much for reporting this issue.

        Show
        Sanjeeb Sahoo added a comment - We were not correctly mapping an OSGi bundle with non-default Bundle-ClassPath to an archive. e.g., when a bundle has a Bundle-ClassPath: bin/, the mapped archive contained entries like bin/com/acme/MyBean.class although this class belongs to com.acme package. As a result, EJB sniffer was not able to find any EJBs. To fix the issue, we have now introduced an abstraction called EJBBundle similar to WAB. I refactored most of the code out of WAB to an abstract called OSGiJavaEEArchive and WAB as well as EJBBundle extend from that. As a result of this change, now even EJB bundles support fragments just like WAB. I also found minor issues in our effective bundle classpath computation logic. e.g., we were not handling whitespaces in BCP. Similarly, '.' was not handled correctly for host bundles. There was bug in the getManifest() logic - it could throw NPE. We also changed the getManifest() to always return the manifest of the host bundle. if host does not have a manifest, we return null. Adding osgi-javaee/osgi-ejb-container/src/main/java/org/glassfish/osgiejb/EJBBundle.java Sending osgi-javaee/osgi-ejb-container/src/main/java/org/glassfish/osgiejb/OSGiEJBDeploymentRequest.java Sending osgi-javaee/osgi-javaee-base/src/main/java/org/glassfish/osgijavaeebase/OSGiBundleArchive.java Adding osgi-javaee/osgi-javaee-base/src/main/java/org/glassfish/osgijavaeebase/OSGiJavaEEArchive.java Adding osgi-javaee/osgi-javaee-base/src/main/java/org/glassfish/osgijavaeebase/URIable.java Sending osgi-javaee/osgi-web-container/src/main/java/org/glassfish/osgiweb/WAB.java Transmitting file data ...... Committed revision 42244. Thank you very much for reporting this issue.

          People

          • Assignee:
            Sanjeeb Sahoo
            Reporter:
            Harald Wellmann
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: