Problems with maven built OSGi including dependencies

14,007

Solution 1

Apparently, the library uses com.sun.jdmk.comm, which is not exposed from the framework bundle. You can check this question if you really need it, or exclude it from the imports by putting in an additional instruction,

<Import-Package>!com.sun.jdmk.comm, *</Import-Package>

Solution 2

If you end up with a huge exclude list, you should probably take that as an indication that something isn't right with your build process and the bundle.

If it was me, the first thing I'd do is crack open your bundle and have a look at what classes it includes, and what packages it exports. I suspect you've got a pretty massive bundle, which means your bundle's dependencies are going to be pretty extensive. This means you lose a lot of the modularity benefits of OSGi, and it can cause a lot of practical problems too.

Any time you declare a package to be optional, you're saying 'I'm happy to accept ClassDefNotFoundExceptions for classes in this package.' For your code you can probably know if a package genuinely is optional, but it's pretty tricky to guess which packages used by a third party are optional. This, of course, is why pre-bundleised jars are more convenient, but I realise this isn't much help to you. :)

What you're doing by embedding the third party library is bundleising it, but in a way which isn't so reusable. (The other difference is that it will share a classloader with the embedding bundle, which could make things work a lot better if the third party library tries to load your classed by reflection, for example.) Since you're having problems with the dependencies, I'd be inclined to take the hit of adding a build step which wraps the third party jar, so that you can clearly see what classes and dependencies relate to your code, and which to this extra jar.

The other thing I'd look at is your export package=* clause. This will export every package on your classpath, which means all those packages get built into your jar. And you get all their package imports, too. Your poor bundle becomes a whole application, rather than the lean OSGi module you were hoping for. You should restrict your exports to the bare minimum (you want to keep your innards private, and you definitely don't want to be sharing everyone else's innards).

--

Enterprise OSGi in Action: http://www.manning.com/cummins

Share:
14,007

Related videos on Youtube

qqilihq
Author by

qqilihq

Co-founder and Cee-something-Ohh at LineUpr: Create an app for virtual, hybrid and physical events in thirty minutes. Developer of the Selenium KNIME Nodes: Automate your browser with a graphical workflow without writing a line of code. One of the developers behind NodePit: Your search engine for KNIME nodes and workflows.

Updated on June 04, 2022

Comments

  • qqilihq
    qqilihq about 2 years

    I'm currently starting with OSGi, iPOJO and iPOJO Annotations and trying to build a simple component to be deployed in Felix. Unfortunately, I'm stumbling over various problems which take me hours to solve or which I cannot even solve after wasting hours, like the following:

    I want to use an existing library in my OSGi bundle which we build using Maven. The library is currently not "OSGI-ified" and we are not planning to do so in the medium term. Because of that, I want to include this library and all of its dependencies in the bundle, using …:

    <Embed-Dependency>*</Embed-Dependency>
    <Embed-Transitive>true</Embed-Transitive>
    

    What I have now, is the following pom.xml file for the OSGi component:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>foo</groupId>
        <artifactId>samplecomponent</artifactId>
        <packaging>bundle</packaging>
        <version>0.0.1-SNAPSHOT</version>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.3.2</version>
                    <configuration>
                        <compilerArgument>-Xlint:all</compilerArgument>
                        <showWarnings>true</showWarnings>
                        <source>1.6</source>
                        <target>1.6</target>
                        <compilerArguments>
                            <encoding>UTF-8</encoding>
                        </compilerArguments>
                        <showDeprecation>true</showDeprecation>
                        <verbose>true</verbose>
                        <encoding>UTF-8</encoding>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.felix</groupId>
                    <artifactId>maven-bundle-plugin</artifactId>
                    <extensions>true</extensions>
                    <version>2.3.6</version>
                    <configuration>
                        <instructions>
                            <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                            <Embed-Dependency>*</Embed-Dependency>
                            <Embed-Transitive>true</Embed-Transitive>
                            <Embed-Directory>lib</Embed-Directory>
                            <Export-Package>*</Export-Package>
                            <_exportcontents>*</_exportcontents>
                        </instructions>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.felix</groupId>
                    <artifactId>maven-ipojo-plugin</artifactId>
                    <version>1.6.0</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>ipojo-bundle</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
        <dependencies>
            <dependency>
                <groupId>org.apache.felix</groupId>
                <artifactId>org.apache.felix.ipojo.annotations</artifactId>
                <version>1.8.0</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>foo</groupId>
                <artifactId>mylibrary</artifactId>
                <version>1.2.3</version>
                <scope>compile</scope>
            </dependency>
        </dependencies>
    </project>
    

    The bundle jar file is built without any problems, but when deploying and starting the bundle on Apache Felix, I get the following error:

    g! install file:/…/samplecomponent-0.0.1-SNAPSHOT.jar 
    Bundle ID: 8
    g! start 8
    org.osgi.framework.BundleException: Unresolved constraint in bundle samplecomponent [8]: Unable to resolve 8.0: missing requirement [8.0] osgi.wiring.package; (osgi.wiring.package=com.sun.jdmk.comm)
    

    I have set the log level to the highest verbosity, no more information unfortunately. When I remove mylibrary, the bundle is started without problems.

    Any suggestions appreciated!

  • qqilihq
    qqilihq over 12 years
    Thank you, that was in general a good pointer. But, after adding the exclude, further unresolved dependencies popped up. What I did now, is set the dependencies to "optional": <Import-Package>*;resolution:=optional</Import-Package> Now I got it working as expected :)
  • yvesb
    yvesb over 12 years
    Hm, good to see that you're problem is solved, but resolution:=optional should only be used in times of great distress: you undermine the OSGi resolving mechanism by doing that, since you mark every import as optional. I would prefer something like !com.sun.*,* .
  • qqilihq
    qqilihq over 12 years
    Okay, I will keep this in mind for the future, thank you for the warning. But in the above example, the problem was, that new missing unresolved dependencies were popping up for various different namespaces, making a huge exclude list.
  • qqilihq
    qqilihq over 12 years
    Thank your for the clarification. I already narrowed down the Export-Package to the essential. What I did not fully understand was your suggestion "[…] take the hit of adding a build step which wraps the third party jar, so that you can clearly see what classes and dependencies relate to your code, and which to this extra jar." -- could you elaborate on this?
  • Holly Cummins
    Holly Cummins over 12 years
    There are a few ways to do this, but most use the same mechanism which the maven bundle plugin is using under the covers, bnd. You can download bnd as a command line tool and then just call 'bnd wrap [yourjar]', with an optional bnd file to refine things like bundle name, imports, and exports. Alternatively you can use maven to do it (google 'maven bundle wrap goal'). These should both give you, pretty darn quickly, a version of your jar with OSGi metadata. Then you can look inside, confirm that you've only dragged in classes from the jar itself, and check the package imports are sensible.
  • Neil Bartlett
    Neil Bartlett over 12 years
    @qqilihq The problem with your suggested solution is that ALL package imports are now marked as optional. If you're going to do that, why even bother using OSGi at all?
  • qqilihq
    qqilihq over 12 years
    Holly, sorry for the late response and thank you for your hint. Very appreciated!
  • qqilihq
    qqilihq over 12 years
    @Neil Bartlett You are right, but at this point I was just looking at a quick (and dirty) solution. I'm in progress optimizing the whole project for OSGi, but I'm just getting into the topic currently and need my time :) .