0

I'm trying to deploy the Java backend of a web application on GlassFish 4.1.1. I use OSGi with declarative services. Declarative services seem to work when the bundle in question is published as a JAR but I'm having some trouble with WARs: Felix doesn't seem to find the the component descriptors (OSGI-INF/SomeComponent.xml). I put together a very simple example to illustrate this.

The bundle is called com.ex.client.
Here's the MANIFEST.MF:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Client
Bundle-SymbolicName: com.ex.client
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.ex.auth,
 javax.servlet;version="3.1.0",
 javax.servlet.http;version="3.1.0",
 org.osgi.framework
Service-Component: OSGI-INF/ClientServlet.xml
Web-ContextPath: /hi
Bundle-ClassPath: WEB-INF/classes

Here's the structure of the resulting WAR file:

com.ex.client.war
 |
 +-- META-INF
 |    |
 |    +-- MANIFEST.MF (as shown above)
 |
 +-- OSGI-INF
 |    |
 |    +-- ClientServlet.xml
 |
 +-- WEB-INF
      |
      +-- classes
      |    |
      |    +-- binaries
      |
      +-- web.xml

And here's Felix complaining that it cannot find OSGI-INF/ClientServlet.xml:

Info: Installed C:\glassfish-4.1.1\glassfish\domains\domain1\autodeploy\bundles\com.ex.client.war
Severe: ERROR: com.ex.client (333): Component descriptor entry 'OSGI-INF/ClientServlet.xml' not found
Info: Started bundle: file:/C:/glassfish-4.1.1/glassfish/domains/domain1/autodeploy/bundles/com.ex.client.war
Info: Started bundle: file:/C:/glassfish-4.1.1/glassfish/domains/domain1/autodeploy/bundles/com.ex.client.war
Info: Expanded at file:/C:/glassfish-4.1.1/glassfish/domains/domain1/osgi-cache/felix/bundle309/data/applications/bundle333-1456241385614/
Info: visiting unvisited references
Info: uris = [file:/C:/glassfish-4.1.1/glassfish/domains/domain1/osgi-cache/felix/bundle309/data/applications/bundle333-1456241385614/WEB-INF/classes/]
Info: visiting unvisited references
Info: visiting unvisited references
Info: total number of classes with faces annotation = 0
Info: Loading application [com.ex.client_1.0.0.qualifier] at [/hi]
Info: Registered ServletContext as a service with properties: {osgi.web.symbolicname=com.ex.client, osgi.web.version=1.0.0.qualifier, osgi.web.contextpath=/hi} 
Info: deployed bundle com.ex.client [333] at file:/C:/glassfish-4.1.1/glassfish/domains/domain1/osgi-cache/felix/bundle309/data/applications/bundle333-1456241385614/

When I go to the location

C:/glassfish-4.1.1/glassfish/domains/domain1/osgi-cache/felix/bundle309/data/applications/bundle333-1456241385614/

mentioned above I see the exact same structure as within the WAR file. OSGI-INF/ClientServlet.xml is there.

I googled "Component descriptor entry * not found" and found the code that logs the message (note: I'm not sure if this is the correct version): http://grepcode.com/file/repo1.maven.org/maven2/org.apache.felix/org.apache.felix.scr/1.8.2/org/apache/felix/scr/impl/BundleComponentActivator.java#150

URL[] descriptorURLs = findDescriptors( m_bundle, descriptorLocation );
if ( descriptorURLs.length == 0 )
{
    // 112.4.1 If an XML document specified by the header cannot be located in the bundle and its attached
    // fragments, SCR must log an error message with the Log Service, if present, and continue.
    log( LogService.LOG_ERROR, "Component descriptor entry ''{0}'' not found", new Object[]
        { descriptorLocation }, null, null, null );
    continue;
}

Where as far as I can tell descriptorLocation should be OSGI-INF/ClientServlet.xml (what I wrote in the Service-Component in the manifest). Somehow findDescriptors( m_bundle, descriptorLocation ), doesn't find the XML file.

I copied the findDescriptors method into a class in my bundle and I'm printing the results:

Info: bundle://333.0:0/OSGI-INF/ClientServlet.xml

So /OSGI-INF/ClientServlet.xml is indeed there and can be found using the same code that is failing for BundleComponentActivator (again, if this is really the same version of the code; I'm struggling to find out which version GlassFish 4.1.1 uses). So I think the problem is that when BundleComponentActivator first tries to find this XML, it isn't there yet. It works later for me because at that point it has been unpacked and made available.

So... what to do? Am I wrong to think that this should work? Am I packing things incorrectly?

Alix
  • 927
  • 7
  • 21
  • Everything looks fine in terms of packaging, so I suspect a bug in Glassfish. Try raising this against their bug tracker? – Neil Bartlett Feb 24 '16 at 12:19
  • @NeilBartlett: I will and report back. Thanks! – Alix Feb 24 '16 at 12:53
  • I would suspect the code is using `getResource` to find the xml file. Since `Bundle-Classpath` does not include the root of the jar it cannot be found. Files listed on `Service-Component` must be found using `getEntry` which ignores `Bundle-Classpath`. – BJ Hargrave Feb 24 '16 at 13:18
  • It looks the the code is correct, http://grepcode.com/file/repo1.maven.org/maven2/org.apache.felix/org.apache.felix.scr/1.8.2/org/apache/felix/scr/impl/BundleComponentActivator.java#213, so perhaps the framework implementation is wrong in its handling of `findEntries` or the `bundle:` URL protocol. – BJ Hargrave Feb 24 '16 at 13:20
  • @BJHargrave: When I invoke my copy of method `findDescriptors` (which uses `findEntries`) the URLs are resolved correctly. The code that logs the error (http://grepcode.com/file/repo1.maven.org/maven2/org.apache.felix/org.apache.felix.scr/1.8.2/org/apache/felix/scr/impl/BundleComponentActivator.java#150) fails before doing anything with the URLs; at that point it's just checking whether any URL has been resolved (logs error if `descriptorURLs.length == 0`). So I still think the problem is that this code is executed too early, before the XML is unpacked into the right location. – Alix Feb 24 '16 at 13:44
  • But please let me know if you have more ideas. In the meantime I've filed an issue in GlassFish's issue tracker: https://java.net/jira/browse/GLASSFISH-21518. – Alix Feb 24 '16 at 13:46

0 Answers0