You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@felix.apache.org by "Pierre De Rop (Jira)" <ji...@apache.org> on 2020/06/03 17:23:00 UTC

[jira] [Created] (FELIX-6284) Felix Connect Native-Image support

Pierre De Rop created FELIX-6284:
------------------------------------

             Summary: Felix Connect Native-Image support
                 Key: FELIX-6284
                 URL: https://issues.apache.org/jira/browse/FELIX-6284
             Project: Felix
          Issue Type: Improvement
          Components: Connect
    Affects Versions: connect-0.2.0
            Reporter: Pierre De Rop
            Assignee: Pierre De Rop


The upcoming OSGi R8 will allow to combine OSGi with application compiled with graalVM/native-image, and maybe Atomos already supports this. In the meantime, I need to use the old apache Felix Connect library in GraalVM substrate/native-image environment.

To do so, there might be few adaptions to be done in Felix Connect. One is about how bundles are scanned by the *ClasspathScanner* class. Currently, this class provides a "scanForBundles" method which looks for all bundle URLS available from the classpath, using:
{code:java}
Enumeration<URL> ClassLoader.getResources("META-INF/MANIFEST.MF") {code}
This works fine in classpath environment, and collected URLS (jar:file) are then used to create BundleDescriptors. Each BundleDescriptor can then get access to bundle content using the URL.

The ClassLoader.getResource method returns for instance URLS like:
{code:java}
jar:file:/home/pderop/felix.connect/bundles/org.apache.felix.gogo.command-1.1.0.jar!/META-INF/MANIFEST.MF
jar:file:/home/pderop/felix.connect/bundles/org.apache.felix.metatype-1.2.2.jar!/META-INF/MANIFEST.MF
etc ...{code}
But in compiled applications (using substrate/native image), the ClassLoader.getResources("META-INF/MANIFEST.MF") method returns an enumeration of URLS which are all the same (using "resource" protocol) for all found bundles. For example, for gogo and metatype bundles in the example above, the ClassLoader.getResources("META-INF/MANIFEST.MF") would return these same urls:
{code:java}
resource:META-INF/MANIFEST.MF
resource:META-INF/MANIFEST.MF {code}
this is problematic, because it's not possible to load resources from a bundle using a unique jar:file url. Moreover, in native-image, using the "resource" url seems to cause problems, and it seems we can only open and read "resource" input stream only one time.  I also observed some exceptions when reading "resource" inputstreams, like this:
{code:java}
DEBUG: bundle jaxrs.hello:0.0.0 (11)BundleComponentActivator : Descriptor locations OSGI-INF/sample.jaxrs.HelloDS.xml
java.io.IOException: Stream closed
        at java.io.BufferedInputStream.getInIfOpen(BufferedInputStream.java:165)
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:252)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:271)
        at org.apache.felix.connect.URLRevision.getUrlContent(URLRevision.java:131)
        at org.apache.felix.connect.URLRevision.getEntries(URLRevision.java:73)
        at org.apache.felix.connect.EntryFilterEnumeration.<init>(EntryFilterEnumeration.java:52)
        at org.apache.felix.connect.PojoSRBundle.findEntries(PojoSRBundle.java:486)
        at org.apache.felix.scr.impl.BundleComponentActivator.findDescriptors(BundleComponentActivator.java:413)
        at org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:313)
        at org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:263)
        at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:551)
        at org.apache.felix.scr.impl.Activator.access$200(Activator.java:69)
        at org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:424)
        at org.apache.felix.scr.impl.AbstractExtender.createExtension(AbstractExtender.java:196)
        at org.apache.felix.scr.impl.AbstractExtender.modifiedBundle(AbstractExtender.java:169)
        at org.apache.felix.scr.impl.AbstractExtender.modifiedBundle(AbstractExtender.java:49)
        at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:488)
        at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:420)
        at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:232)
        at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:450)
        at org.apache.felix.connect.felix.framework.util.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:821)
        at org.apache.felix.connect.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:771)
        at org.apache.felix.connect.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:510)
        at org.apache.felix.connect.PojoSRBundle.start(PojoSRBundle.java:157)
        at org.apache.felix.connect.PojoSR.startBundles(PojoSR.java:286)
        at com.nokia.as.service.felixconnect.impl.Launch.start(Launch.java:161)
        at com.nokia.as.service.felixconnect.impl.Launch.main(Launch.java:76)
{code}
I don't know currently if there is an API in graalvm which could be used as a work around, but in the meantime, a method can be added in the ClasspathScanner in order to load original jars from a directory, using jar:file URL protocol. In this way, we can still use "jar:file" URLS as before. So, it means the original jars must be kept beside the executable. Maybe the patch can be improved later, but it's light and allows compiled applications to use declarative service, configadmin, dependency manager, etc ... I will create a PR for this.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)