Sunday, February 15, 2015

Avoiding [osgi.wiring.package=sun.misc] Exception with OSGi Self-Contained Bundles

On my last post "WebSockets with Grizzly on Apache Felix (OSGi)", a problem came up when installing my simple bundle into OSGi.

The exceptions faced were:


  org.osgi.framework.BundleException: Unresolved constraint in bundle 
  automationmiddleware.plugins.remoteagent [29]: Unable to resolve 29.0: missing requirement 
  [29.0] osgi.wiring.package; (&(osgi.wiring.package=org.glassfish.grizzly)(version>=2.3.0)(
  !(version>=3.0.0)))



  org.osgi.framework.BundleException: Unresolved constraint in bundle 
  automationmiddleware.plugins.remoteagent [29]: Unable to resolve 29.0: missing requirement 
  [29.0] osgi.wiring.package; (osgi.wiring.package=sun.misc)
at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:4002)


The first exception happens because Felix cannot find org.glassfish.grizzly package which is referenced by my bundle. This is easily solvable by dropping the grizzly-httpservice-bundle-2.3.18.jar bundle into the bundles folder of Felix, this bundle contains the package that Felix is failing to resolve.

The second exception occurs because by default the maven plugin maven-bundle-plugin that is typically used to package your bundle (JAR) has it parameter Import-Package set to "*".Which means "include everything that is referenced in your jar as a package to be resolved". You can easily also solve this by modifying your Felix configuration file adding this line:


  org.osgi.framework.system.packages.extra=sun.misc


The problem with both solutions above is that, they can be merely seen as a workaround, so please do not do this on a production project. 

Following the solutions above will expose all your Felix bundles to those 2 bundles, which by them selves, may dependent on different versions of sun.misc or org.glassfish.grizzly. Such dependency may cause "General Error" exceptions later on! Most probably when shipping to production, according to Murphy's law. To do it by the book as recommended here, follow the tips bellow:


  • Packaging Self-Contained Bundles, means that you bundles embed all their dependencies within them, to do this I modified my previously pom.xml file to this:

    ...
    <build>
     <sourceDirectory>src</sourceDirectory>
     <plugins>
      <plugin>
       <groupId>org.apache.felix</groupId>
       <artifactId>maven-bundle-plugin</artifactId>
       <extensions>true</extensions>
       <configuration>
        <instructions>
         <Bundle-SymbolicName>${project.artifactId};singleton:=true</Bundle-SymbolicName>
         <Bundle-Version>${project.version}</Bundle-Version>
         <Bundle-Activator>lumina.plugins.pandoraremote.Activator</Bundle-Activator>
         <Include-Resource>grizzly-httpservice-bundle-2.3.18.jar</Include-Resource>
         <Bundle-ClassPath>.,grizzly-httpservice-bundle-2.3.18.jar</Bundle-ClassPath>
         <Import-Package>sun.misc.*;resolution:=optional,*</Import-Package>
        </instructions>
       </configuration>
      </plugin>
      ...
     </plugins>
    </build>
    ...

    If you notice, on the line 14 and 15, I embed my dependency on grizzly-httpservice-bundle-2.3.18.jar within my bundle (JAR) and I also add that JAR to my classpath. This way when resolving my bundle, Felix will find the org.glassfish.grizzly package in that JAR and it will then successfully resolve my bundle dependencies.
      
  • About the sun.misc exception, as I was saying by default the Import-Package parameter of the maven plugin maven-bundle-plugin, is set to "*", to prevent Felix from trying to resolve sun.misc all you need to do is to override that parameter with this:

    <Import-Package>sun.misc.*;resolution:=optional,*</Import-Package>
    


    By declaring sun.misc resolution as optional, Felix will skip sun.misc resolution step, and your package will load successfully.

Doing things this way will help you keep your sanity a few more years, and your colleagues too ;) !

Note: Thanks to my colleague Pedro Domingues for calling my attention on the workaround I mentioned at the beginning of this post. Without his kind advise I would have carried on with my poor solution, which could eventually cause more harm than good!