Apache ServiceMix, however especially if the library was never considered in the context of OSGi, you may have dependencies not already available as bundles. You’ll then find yourself in the “fun” situation of shoehorning in a library never meant to run in OSGi with dependencies which are not available in OSGi as the only alternative is to re-write the library.
You could of course track down every transient dependency and wrap that dependency, but you may not need that particular functionality elsewhere yet, and exposing that dependency as an OSGi bundle then means other bundles in the OSGi container can now import it thus potentially locking you into the current version.
As an alternative, you can instead include the dependencies in your wrapped bundle along with the original library you’re wrapping, something like this Maven snippet:
<plugin>
<groupId>biz.aQute.bnd</groupId>
<artifactId>bnd-maven-plugin</artifactId>
<extensions>true</extensions>
<version>6.2.0</version>
<configuration>
<bnd>
<![CDATA[
-includeresource: myco-commons-[0-9\\.]*.jar;lib:=true, \\
javax.ws.rs-api-[0-9\\.]*.jar;lib:=true, \\
jersey-(client|common)-[0-9\\.]*.jar;lib:=true
Import-Package: *
]]>
</bnd>
<debug>true</debug>
</configuration>
<executions>
<execution>
<id>jar</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
But how do you know what dependencies you need and what imports you can ignore? Especially when you have a multiple layer deep dependency tree?
You can, of course, keep installing the bundle and checking to see what packages fail to import, but this is both tedious and time-consuming. Instead, using Apache Maven and the bnd command line tool, you can dump all of the package imports for your project’s dependencies to text files for offline analysis:
# First download all of the dependencies to a folder
mkdir ./bundle-dependencies
mvn dependency:copy-dependencies -DoutputDirectory=./bundle-dependencies
# Then use BND to print the usage info
for j in ./bundle-dependencies/*.jar; do bnd print -u $j > $j.txt; done
# Finally, cleanup the JAR files
rm -f ./bundle-dependencies/*.jar
This will produce text files with every package used by every package in a particular library. For example this is the file generated for jersey-client 2.35:
[USES]
org.glassfish.jersey.client javax.inject
javax.net.ssl
javax.ws.rs
javax.ws.rs.client
javax.ws.rs.core
javax.ws.rs.ext
org.glassfish.jersey
org.glassfish.jersey.client.inject
org.glassfish.jersey.client.internal
org.glassfish.jersey.client.internal.inject
org.glassfish.jersey.client.internal.routing
org.glassfish.jersey.client.spi
org.glassfish.jersey.internal
org.glassfish.jersey.internal.guava
org.glassfish.jersey.internal.inject
org.glassfish.jersey.internal.spi
org.glassfish.jersey.internal.util
org.glassfish.jersey.internal.util.collection
org.glassfish.jersey.message
org.glassfish.jersey.message.internal
org.glassfish.jersey.model.internal
org.glassfish.jersey.process.internal
org.glassfish.jersey.spi
org.glassfish.jersey.uri
org.glassfish.jersey.uri.internal
org.glassfish.jersey.client.authentication javax.annotation
javax.ws.rs
javax.ws.rs.client
javax.ws.rs.core
org.glassfish.jersey.client
org.glassfish.jersey.client.internal
org.glassfish.jersey.message
org.glassfish.jersey.uri
org.glassfish.jersey.client.filter javax.inject
javax.ws.rs.client
javax.ws.rs.core
org.glassfish.jersey.client.internal
org.glassfish.jersey.internal.inject
org.glassfish.jersey.spi
org.glassfish.jersey.client.http javax.ws.rs.core
org.glassfish.jersey.client
org.glassfish.jersey.client.inject org.glassfish.jersey.model
org.glassfish.jersey.client.internal javax.net.ssl
javax.ws.rs
javax.ws.rs.client
javax.ws.rs.core
org.glassfish.jersey.client
org.glassfish.jersey.client.spi
org.glassfish.jersey.internal.l10n
org.glassfish.jersey.internal.util
org.glassfish.jersey.internal.util.collection
org.glassfish.jersey.message.internal
org.glassfish.jersey.client.internal.inject javax.inject
javax.ws.rs
javax.ws.rs.ext
org.glassfish.jersey.client
org.glassfish.jersey.client.inject
org.glassfish.jersey.client.internal
org.glassfish.jersey.internal
org.glassfish.jersey.internal.inject
org.glassfish.jersey.internal.util
org.glassfish.jersey.internal.util.collection
org.glassfish.jersey.model
org.glassfish.jersey.client.internal.jdkconnector org.glassfish.jersey.internal.l10n
org.glassfish.jersey.client.internal.routing javax.ws.rs.core
javax.ws.rs.ext
org.glassfish.jersey.internal.routing
org.glassfish.jersey.internal.util
org.glassfish.jersey.message
org.glassfish.jersey.message.internal
org.glassfish.jersey.client.spi javax.net.ssl
javax.ws.rs
javax.ws.rs.client
javax.ws.rs.core
org.glassfish.jersey.client
org.glassfish.jersey.process
org.glassfish.jersey.spi
The package on the left is the package within that library and the packages on the right are the packages referenced by that package.
While you will still probably need to do the install and test cycle, this will make it significantly easier to understand where a dependency is referenced and if it can be excluded from the Import-Package statement.
While hopefully you won’t have to wrap a library like this as a bundle, I hope this post helps if you do!