I have a 3rd party jar, no source, that is used to connect to a proprietary database system. I believe the jar is actually an Eclipse plugin; it was taken from one of the lib folders of the Eclipse-based editor for that system.
Anyway, I'm trying to develop a bundle that exposes the functionality of this jar, using Netbeans 7.4 and Karaf 3.0.1. Just trying to install the jar into Karaf isn't working - if I drop it into the deploy folder it doesn't even appear on the list, like it doesn't recognize it as an OSGI bundle. I created a new OSGI Maven bundle in Netbeans, added the jar as a dependency, and have tried all manner of shading, including in Bundle-ClassPath, Export-Package, with no luck. At one point I thought I had it working but Karaf was complaining about needing some Eclipse requirements.
I did more digging, unzipped the jar and the manifest for the 3rd party jar has this:
Require-Bundle: org.eclipse.core.runtime
So then I started down the rabbit hole of fulfilling those dependencies. Based on the maven pages I put together this features.xml file:
<features xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
<feature name='custom_deps' version='1.0'>
<bundle>mvn:org.eclipse.equinox/log/1.0.100-v20070226</bundle>
<bundle>mvn:org.eclipse/osgi/3.5.0.v20090520</bundle>
<bundle>mvn:org.eclipse.core/contenttype/3.2.100-v20070319</bundle>
<bundle>mvn:org.eclipse.core/jobs/3.3.0-v20070423</bundle>
<bundle>mvn:org.eclipse.core.runtime.compatibility/auth/3.2.100-v20070502</bundle>
<bundle>mvn:org.eclipse.equinox/app/1.3.100-v20130327-1442</bundle>
<bundle>mvn:org.eclipse.equinox/common/3.6.200-v20130402-1505</bundle>
<bundle>mvn:org.eclipse.equinox/preferences/3.5.100-v20130422-1538</bundle>
<bundle>mvn:org.eclipse.equinox/registry/3.5.301-v20130717-1549</bundle>
<bundle>mvn:org.eclipse.core/runtime/3.3.100-v20070530</bundle>
</feature>
</features>
Now when I try to install that I get:
karaf#root()> feature:install custom_deps
Error executing command: Could not start bundle mvn:org.eclipse/osgi/3.5.0.v2009
0520 in feature(s) custom_deps-1.0: Activator start error in bundle org.eclips
e.osgi [256].
which I think might have something to do with equinox vs felix? I'm just using the default Karaf setup and creating bundles using the built-in Netbeans Maven project and am still relatively new to the OSGI world. For the most part I can get bundles up and running and have put together a basic collection for an app, but this one bundle depends on being able to use this library and I'm struggling to find a way to get it working. I'm wondering if there's a way to either resolve all the linked dependencies of the jar, or somehow strip out whatever is depending on eclipse? I'm wondering if it's just plugin-related parts that aren't necessary for the connectivity I'm looking for.
Thanks for any ideas.
Edit: adding more info about the 3rd party jar
The jar is vendor-provided, but from a now defunct vendor. I'm not sure whether I can give vendor details or not so I'll mask the specific company info here. So the jar is named "com.bigcompany.product.productbeans_4.3.1.jar". The full manifest of the jar looks like this:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Productbeans Plug-in
Bundle-SymbolicName: com.bigcompany.product.productbeans
Bundle-Version: 4.3.1
Bundle-Activator: com.bigcompany.product.productbeans.ProductbeansPlugin
Bundle-Vendor: BIGCOMPANY
Bundle-Localization: plugin
Require-Bundle: org.eclipse.core.runtime
Eclipse-AutoStart: true
Export-Package: com.bigcompany.product.productbeans
The switch to Equinox in Karaf was relatively painless, but dropping the jar into Karaf still it still didn't appear in the list. I tried unzipping the jar, modifying the manifest to remove the Require-Bundle and Eclipse-Autostart lines, repacked it up and tried installing that - at that point it showed up but my bundles that want this library still complain about missing requirements 'com.bigcompany.product.productbeans'.
From there I'm tried redeploying my bundle that tries to import the 3rd party package, and when I try installing my features file above that complains about missing constraints - is there a required order of the bundles in the features file?
I think ultimately what I'm hoping is is there an authoritative way to just embed or include a jar (or it's contained .class files?) into a bundle that requires them, and to have it just work? I've tried Embed-Dependency, Bundle-Classpath (although I'm not sure if I have the syntax or locations correct?), using the maven shade plugin, and either I get to where my bundle says it's missing the 3rd party package, or if it doesn't give that it says it can't find the eclipse dependencies. If I have a non-OSGI project, the maven dependencies don't list or include any sort of eclipse-related dependencies. I can include snippets of my POM or something else if needed.
Basically the Require-Bundle says that it needs the equinox bundle. Karaf by standard uses Apache felix as OSGi runtime. As equinox is also a runtime you can not simply install it inside felix.
Instead you simply switch your karaf to use equinox instead of felix.
Edit etc/config.properties and set
karaf.framework=equinox
Then try to deploy your bundle again (without additional dependencies first).
Related
I have an OSGI bundle that is working perfectly, I added, as a maven dependency, unirest a lightweight HTTP library, when deploying to serviceMix I get a missing requirement:
filter:="(osgi.wiring.package=com.mashape.unirest.http)"
Of course I am using that package in my bundle, but as far as serviceMix is concerned, that library is just classes in my classpath like my own classes
I guess I'am missing something Here
I know it is possible to embed a library, but I don't understand why any additional manipulation is needed ? how is that different from just adding that library as a maven dependency
Any answers and pointers to articles/documentation is really appreciated
There is a difference between the way dependencies are treated in maven and osgi.
Maven treats the dependencies as a single classpath/classloader where the classes from every jar can access the classes from every other jar.
This is historical from main apps, and its the way maven runs unit tests.
In the osgi run-time environment each bundle has its own classloader, and by default, only has access to the classes and jars embedded in its own bundle.
The classes in each bundle are isolated unless the package is exported from one bundle and imported to another.
The maven bundle plugin attempts to bridge the gap. Just adding a dependency to maven is not enough, one must also tell the maven bundle plugin how to package and deploy it. The options are 1) embed the dependency in your bundle, or 2) deploy the dependency as a separate bundle.
The maven bundle plugin defaults to option 2: import everything.
To understand the exports from your dependency better, I suggest looking at the manifest file in the bundle jar. (META-INF/manifest.mf)
I just looked at the unirest jar on maven central and found no packages exported in the manifest. In fact unirest has no bundle headers, so its not an osgi bundle.
The error message
missing requirement : filter:="(osgi.wiring.package=com.mashape.unirest.http)"
means your bundle is attempting to import a package, but servicemix has no bundle exporting it.
To understand this better, I suggest looking at the manifest file in your bundle jar. (META-INF/manifest.mf) I expect it will contain an import of com.mashape.unirest.http. Also look at servicemix to see if anything exports it:
From the command from try: exports | grep com.mashape.unirest.http
I expect you will find no bundle exporting it.
I suggest you configure the maven bundle plugin to embed unirest instead of importing it. like this:
<Embed-Dependency>unirest-java</Embed-Dependency>
(if you already have an Embed-Dependency configuration you will need to merge them.)
Ref. http://felix.apache.org/documentation/subprojects/apache-felix-maven-bundle-plugin-bnd.html#detailed-how-to
Another way is deploy unirest-java as a bundle by wrapping it.
That could be as simple as copying it to the deploy folder:
https://karaf.apache.org/manual/latest/#_wrap_deployer
That would have the advantage of sharing unirest-java.
Lastly, if unirest does its own class loading, then that may turn out to be incompatible with osgi.
I got a 3rd party jar which I am using for Blowfish decryption in a bundle that I need to deploy on apache karaf.
So now I also need karaf to know this jar but every solution I find is about creating a whole bundle for that jar which is pretty much for a simple library imo.
What I already did is installing that jar in my local maven repository and adding the dependency but this also doesn't work (at least on karaf).
Is there any other way to get 3rd party jars on apache karaf to work?
Are you using a features xml file? If so you could use wrap:mvn: to make it available:
<feature name="feature1" version="1.0.0">
<bundle>wrap:mvn:group.id/third.party.artefact.id/version</bundle>
<bundle>mvn:group.id/your.artefact/version</bundle>
</feature>
This will bundle the third party jar at runtime and make sure it's installed for your bundle to use. Taken from Karaf - Creating bundles
In addiction to #fiw you may want to osgify your thirdparty jar using Bndtools. In order to achive it:
Download bnd tools
Open a shell where you have downloaded bnd-2.4.0.jar.
Type:
java -jar bnd-2.4.0.jar wrap -o osgify-dependency.jar dependency.jar
where dependency.jar is your third party and osgify-dependency.jar will be the output.
Deploy to maven repo overriding the previous maven coordinates, or deploy your thirdparty with different coordinates.
mvn deploy:deploy-file -Dfile osgify-dependency.jar ...
I'm new in OSGI development and am struggling to understand how best to handle dependent JARs.
i.e. if I'm creating a bundle the likelihood is that I will need to use a few 3rd party JARs. When I create my bundle JAR to deploy to OSGI, obviously these 3rd party JARs are not included and thus the bundle will not run.
I understand that one option is to turn these JARs into bundles and deploy them to the OSGI container. When I bundled and try deploy third party jar it throws error for their own dependent jars and these dependencies are endless and not possible to fulfill.
What is the best solution to this?
-- Anurag
Finally I resolve third party jar issue actually I forger to add following tag in my POM.xml file
<_exportcontents>*
My issue is resolve, thanks to all of you for your support and giving me valuable clues.
If you are a beginner with osgi then I would not recommend to bundle bigger libs yourself. Often more than defining some import and export headers is required and it can become very difficult. Fortunately a lot of libs are available as bundles.
If the original lobs is not yet a bundle then you can search in maven central for a bundled version from servicemix bundles.
Using apache karaf is also often a big help. There are karaf features with predefined deps for a lot of libs like activemq, cxf, camel, openjpa, ...
In the worst case you can embed the lib and all deps in your own jar. This tends to cause class loading issues though if you try to share some classes between bundles.
What lib is the problem in your case?
A lot of libraries you mention (log4j, quartz, dom4j) have already been converted to OSGi bundles by Springsource. You can find them in the Springsource Enterprise Bundle Repository. All Hibernate libraries > 4.2 are also osgified.
You have three choices:
Find the library in some pre-made bundles (Springsource Repository, Eclipse Orbit Repository, etc.)
Include the libraries into your bundle as an external library (Make a directory lib, copy your jar files there, and reference them from the Bundle-Classpath element in MANIFEST.MF)
Convert the library into an OSGi bundle (e.g. with the bnd wrapconverter, example here)
I have a java project that compiles down to an OSGi bundle. I'm using the maven-bundle-plugin to create the bundle, and the maven-sling-plugin to push the bundle to my running OSGi server. At the moment, my project has two dependencies (Guava and Gson) that need to be manually installed in the Felix server prior to installing the bundle. The manual install for these two dependency bundles only needs to occur once (when first setting up the OSGi server), but since it's a manual process, I'd kind of like to just push it into the "mvn install" phase.
I've looked at a number of maven plugins (maven-sling-plugin, maven-ipojo-plugin, dependency plugins, etc.), but I'm afraid that I just don't have enough knowledge to know where to start, or even to search in Stackoverflow for the solution (I have a suspicion that this has already been answered).
So - is there a clean way to install/start dependent bundles with maven? Something where I can specify a jar and a runlevel, and have the installation take place prior to my bundle being installed?
The Ops4j pax construct project might help: http://team.ops4j.org/wiki/display/paxconstruct/Pax+Construct
Looks like it's possible to use maven to specify which bundles to install and then spin up a felix osgi environment as described here:
http://www.sonatype.com/books/mcookbook/reference/ch01s04.html
How to create OSGi bundle from jar library?
In case you are using eclipse: There is a wizard for that.
It allows you to select a number of jar libraries and creates a plug-in project (i.e. OSGi bundle) including these jars.
You can find it here:
File -> New -> Other ... -> Plug-in from Existing jar Archives.
In principle you just need to add OSGi metadata to the manifest
There is a bundle creator for eclipse which gives a very practical way to add these entries which should be part of the Plugin Dev Toolkit.
Here is an article detailing the process and how to do it with the Bnd tool, maven and so forth.
I personally like the pax tools very much. It is all command line based, but very practical. To create an OSGi bundle of an existing jar you can use bnd tool.
First check out if you can find a osgi enabled version of your library from repositories
SpringSource http://www.springsource.com/repository
Fusesource http://repo.fusesource.com/
If you don't find the OSGi enabled versions. You can go ahead with using the pax tool - PaxConstruct or use the aQute's Bnd tool.
Create a new Plug-in project from existing JAR archive.
Add the jar file to be exported
Click next and name the project.
NOTE:
Make sure OSGI framework is selected in target platform.
Unzip the JAR archives into the project is deselected -> deselecting it, will export all the packages of the JAR
if Unzip the JAR archives into the project is selected then you will manually need to export required packages in the MANIFEST.MF file.
Click finish. You will find project with name transport-5.1.1 created in your workspace. Also you can verify, all the packages of the JAR are exported in MANIFEST.MF file.
The Eclipse Bundle Recipe project provides a Maven based approach for adding OSGi meta data to JARs consumed from a Maven repository.
At its core, it uses the bnd tool. This tool is like a swiss army knife. It analyzes jars and class files and properly calculate package import and exports. You should use bnd for converting proprietary jars yourself. It's available in Maven Central.
Late arrival to the party:
If you're using Gradle, you can add the jar as a normal dependency of your project if you apply the osgi-run plugin.
The osgi-run plugin will wrap the jar transparently into a bundle for you, exporting every package in it and calculating all its imports. As Gradle will know the jar's transitive dependencies, it will do the same for them as well, if necessary.
The jar(s) will be part of the OSGi runtime osgi-run creates, which you can then start up with gradle runOsgi or gradle createOsgi, then executing either the run.sh or run.bat scripts.
The actual wrapping is done by Bnd, the swiss knife of the OSGi world, of course.
If you want to configure how the wrapping happens (what should be imported/exported, usually), you can do it easily in the Gradle build file, see the documentation for details.
Example:
wrapInstructions {
// use regex to match file name of dependency
manifest( "c3p0.*" ) {
// import everything except the log4j package - should not be needed
instruction 'Import-Package', '!org.apache.log4j', '*'
instruction 'Bundle-Description', 'c3p0 is an easy-to-use library for making traditional ' +
'JDBC drivers "enterprise-ready" by augmenting them with functionality defined by ' +
'the jdbc3 spec and the optional extensions to jdbc2.'
}
}