I have put a few jars on my Bundle-Classpath. The line below shows the entry in my pom.xml, which uses the Felix plugin to create the manigest.mf for the bundle.
<Bundle-ClassPath>.,lib/com.springsource.org.h2-1.0.71.jar,lib/com.springsource.org.apache.lucene-2.3.2.jar,lib/com.springsource.org.apache.lucene.search-2.3.2.jar</Bundle-ClassPath>
These jars have classes which import packages, but from what I can see, they all have a MANIFEST.MF, which has it's own (accurate) list of Import-Package statements.
However, when I build my project (using Maven and the bundle plugin), it reports an error because it cannot resolve references to certain classes. Specifically the error is:
Unresolved references to [com.sun.tools.javac, javax.naming, javax.naming.spi, javax.servlet, javax.servlet.http, javax.sql, javax.transaction.xa]
All of these errors come from com.springsource.org.h2-1.0.71.jar and all these packages are imported in the manifest of that jar.
I am unable to understand:
- Why is the Maven bundle plugin complaining, if these packages are already imported in the MANIFEST>MF of com.springsource.org.h2-1.0.71.jar
- Why are the problems coming only from com.springsource.org.h2-1.0.71.jar ? I tried removing that specific jar and the build goes through fine, even though com.springsource.org.apache.lucene.search-2.3.2.jar also has several entries for Import-Package in it's MANIFEST.MF ?
About the second point, I did some investigation, and I feel like there is a pattern. All the imports which com.springsource.org.apache.lucene.search-2.3.2.jar specifies in it's manifest, are being satisfied by com.springsource.org.apache.lucene-2.3.2.jar, which is also specified on the Bundle-Classpath.
The dependencies of com.springsource.org.h2-1.0.71.jar which are being satisfied by com.springsource.org.apache.lucene-2.3.2.jar (which is on the Bundle-Classpath), are not listed in the error message, however, those dependencies which are not satisfied by jars on the Bundle-Classpath are being listed in the error message.
Not quite sure what is happening. What is the rule regarding jar files which are specified on the Bundle-Classpath ? Do their imports (even when they are specified in the Import-Package) element of their manifest, have to be listed in the main project's pom ? Or is this something which the Maven bundle plugin is enforcing ? If the latter is the case, is there a way to get away from the enforcing ?
When you embed any jar via Embed-Dependency tag then the maven-bundle-plugin would analyze that jar also and add the referred packages to the host bundle Import-Package list. Mostly such packages are optional depending on the feature used. For example in your usecase the H2 jar has dependency on Lucene, Servlet API for certain features. if your usage scenario does not require these features then you can mark these packages as optional
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.5</version>
<extensions>true</extensions>
<configuration>
<obrRepository>NONE</obrRepository>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
..
<Embed-Dependency>
h2
</Embed-Dependency>
<Import-Package>
org.osgi.service.jdbc.*;
org.apache.lucene.*;
javax.transaction.*;resolution:=optional,
*
</Import-Package>
</instructions>
</configuration>
</plugin>
In above config we mark such packages as optional. The main problem is to determine the package list depending on your usage
One quick and dirty way is to mark all as optional imports. Should be used as a last resort. As some valid imports would be marked optional and OSGi fwk would not be able to check them.
<Import-Package>
*;resolution:=optional
</Import-Package>
Also note that H2 jar is a valid OSGi bundle so you can deploy it directly.
rule regarding jar files which are specified on the Bundle-Classpath ?
The files which are listed on the bundle-classpath are scanned by maven-bundle-plugin(mbp) to identify imports needed by
each specified jar. Thereby, mbp will add the required imports in the main (your main bundle) manifest.mf.
This does means that the packages should be exported by the outside bundles. If required packages are not found outside of
the bundle then the bundle will not start.
You have 2 solutions to use the third party jars required by your application.
Prepare the OSGi bundle of each and every third party jar. You may find the osgi bundle already created for
spring jars and other open source projects at spring repository here. Just search it perfectely. you will find it.
Use Bundle-classpath:
with this you will have to put your third party dependencies (and "all" their transitive dependencies) in your bundle and specify each jar in Bundle-ClassPath header. With this case, mbp will analyze the bundle classpath jars and try to mess with your import-package header. You just avoid this by including your custom header in pom.xml. If you choose for your custom import-package , be careful to include the required packages from other (outside) bundles correctely in your import-package.
Thumb rule : If your app finds something in your bundle-classpath then it will not go for import-package.