I'm using netbeans, project: 'maven OSGI bundle', i have bundle activator running fine in felix (and so on).
But I'm not able to add an external JAR (i.e. local) to the bundle itself. In practice let's say i have and utils.jar file I'd like to use IN the bundle (without exporting it), I can't understand why and how it is so difficult (uncommon?).
P.S. I have seen that PAX and Eclipse (i tried only one with no success) may create a bundle from a jar lib, but it still sounds so strange to me that this task is not a common practice.
background:
I did some homework and I'm guessing I'm approaching the problem in the wrong way, so I'm posting for help (hints in the right way).
I'm developing a java library (as set of interfaces and implementations) acting as middleware for various projects. The generic problem and scope is very compatible with OSGI arch.
Now the problem is basically: sharing a set of classes/interfaces (=jar library) between bundles (= services and implementations).
I like and think that the best approach is having a BASE bundle exporting such library and other bundles as extensions or dependent services as users/providers/actuators.
SOLVED. after a lot of homework and some tests i got it working by finding the mavenized version of the library and using 'Embed-Dependency' keyword (editing pom manually). still dunno how to do that with netbeans ide.
Related
I'm struggling to wrap my head around developing OSGI bundles to publish to Karaf. I'm using Netbeans 7.4 and the Create Maven OSGI bundle when creating a new project. I think what I'm wrestling with is dealing with dependencies between different projects and working with them in Netbeans and then publishing to Karaf.
What I'm trying to do is set up a REST web service; I found this tutorial to be a good starting point in getting something basic up and running. So I started setting up a parent project with sub projects (all of these are from the Maven OSGI Bundle template). But after I started deploying bundles to my Karaf instance I started wrestling with the "missing requirement" errors within Karaf. I'd start trying to list each dependency in <Export-Package> or <Embed-Dependency> but it seems like I just keep going farther down and always getting new "missing requirement" messages listing yet another dependency. I then started trying the maven copy-dependencies plugin to export whatever dependencies are used in my project and copying whatever comes out into the Karaf deploy folder, too. That worked for the most part but I'm wrestling with what I think are downstream dependencies of a 3rd party jar, but that's probably a separate question anyway.
So, what I'd like to know is how should I be developing a coherent "application" with this setup? I understand I should separate everything into standalone bundles; i.e., I'll have my REST interface as one, the implementation as another, business logic as another. As a maven project, if I have a dependency for datetime handling or string utilities, maven will handle resolving all of those. But these dependencies won't automatically be included in my OSGI bundle, is that the case? What is the workflow to make sure that everything my project depends on is available to the bundles in Karaf? What about my projects that have other projects as dependencies, i.e., an interface implementation? I would include that project as a dependency so it will compile, but how do I make sure that that dependency is met after it is published?
The mismatch between dependencies at compile time and at deployment time is indeed a problem when working with OSGi.
What you need to know is how these relate to each other. At compile time you have the maven dependencies. When you build your project the maven bundle plugin creates the necessary Import-Package and Export-Package statements for you. Most of the time this simply works and you should avoid tuning too much there by hand.
So after the build the Manifest specifies what the resulting bundle needs but this does not automatically make sure the dependencies are met. So when you deploy the bundle to karaf you get the errors about missing dependencies. This is normal.
Now you need to install other bundles that fulfil these dependencies. Often you can simply install the jars of your maven dependencies (if they are bundles). This does not always work though. So basically you install the bundles and check if the requirements are met now.
The nice thing with karaf is that many bigger dependencies like cxf are already available as features. So it is a good idea to first try to get the dependencies by installing available features before you try to install them bundle by bundle.
So this helps you in getting your dependencies right. Then for "production" use the best solution is to create your own feature file where you refer to the bundles you found.
While installing bundles using the deploy dir seems nice at first it is not a good solution. Better install the bundles directly from maven using the mvn: url syntax karaf provides.
Regarding embedding dependencies. Sometimes it is a good solution but often it only makes things worse as it can lead to package use conflicts which are hard to solve. So better do not embed anything if it is possible.
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'm currently developing a maven osgi bundle using Netbeans 7.1. While its easy to create new maven osgi bundle project from netbeans, I've been struggling about how I would run it. Simply running it from netbeans gives me an error that tells me there is missing requirement (missing slf4j for example).
Then I tried a different way. I ran equinox in a terminal and then manually install my project jar to it. But then I must also resolve all the dependencies manually.
Is there any way to automatically download all the required dependencies from an OSGI bundle and install it to a running OSGI framework?
thanx before
AFAIK there's no automation for OSGi in Netbeans (though I may well be wrong). The support you may have seen in Eclipse is only for Eclipse plugins not vanilla OSGi.
Your best bet is to go for some integrating testing or launch via a maven goal, pax-exam or bndtools or even pax-runner will allow you to launch from IDE/maven.
However I don't know of anything that will automatically resolve all dependencies (transitive dependencies and implementations of APIs you depend on would be problematic)
Its a big pain, no question about it. What I used to do was to do a full build (and if you've configured your manifests correctly should include all necessary dependencies) which will generate the necessary jar. I then wired my Tomcat to pick up the jar from my target repository and configured it to hotswap automatically.
Its a matter of preference if you want to run your app server from within your netbeans but I preferred to execute a separate instance of tomcat outside of my IDE. It'll work either way tho.
Currently when I am writting a bundle in that depends on a package, I have to "import" or "depend" on a whole other bundle in Maven that contains that package.
This seems like it is counter-productive to what OSGi gives me.
For example let's say I have two bundles: BundleAPI and BundleImpl.
BundleAPI provides the API interfaces:
// BundleAPI's manifest
export-package: com.service.api
BundleImpl provides the implementation:
//BundleImpl's manifest
import-package com.service.api
However, when I am coding BundleImpl in Eclipse, I am forced to "depend" in maven POM on BundleAPI itself - so that eclipse does not complain.
//BundleImpl's POM
<dependency>
<groupId>com.service</groupId>
<artifactId>com.service.api</artifactId>
[...]
</dependency>
So - on one hand, I am depending only on the package com.service.api, while on the other - I need to have the whole bundle - BundleAPI.
Is there a way to make maven or eclipse smart enough to just find the packages somewhere, instead of whole bundles?
I am very much confused as to how this works - any type of clarity here would be great. Maybe I am missing something fundamentally simple?
The key is to distinguish between build-time dependencies and runtime dependencies.
At build time you have to depend on a whole artifact, i.e. a JAR file or bundle. That's pretty much unavoidable because of the way Java compilers work. However at runtime you depend only on the packages you use in your bundle, and this is how OSGi manages runtime substitution. This is the Import-Package statement in your final bundle.
Of course as a developer you don't want to list two parallel sets of dependencies, that would be crazy. Fortunately maven-bundle-plugin is based on a tool called bnd that calculates the Import-Package statement for you based on analysing your code and discovering the actual packages used. Other tools such as bndtools (an Eclipse-based IDE for OSGi development) also use bnd in this way. Incidentally bnd is much more reliable and accurate than any human at doing this job!
So, you define only the module-level dependencies that you need at build time, and the tool generates the runtime package-level dependencies.
I would recommend against using Tycho because it forces you to use Eclipse PDE, which in turn forces you to manually manage imported packages (for the sake of full disclosure, I am the author of bndtools which competes against PDE).
You cannot develop bundles like regular Java projects with Maven and eclipse. You basically have 2 options.
Apache Felix Bundle Plugin: Basically you develop the project as a regular Java project and use Maven as you normally would. This plugin will be used to add all the OSGi specifics to the jar manifest at deployment time to OSGi enable it. The disadvantage of this aproach is that you are using a Java project in your workspace instead of a bundle, which makes running your project in the OSGi container a little extra work since Eclipse doesn't recognize it as a plugin project. Thus you have to add the jar from the Maven build as part of the target platform manually.
Tycho: This is another Maven plugin that attempts to actually bring theses two environments together and does a pretty good job of it. In this scenario, you actually create an Eclipse bundle/plugin project, which obviously makes for seamless integration in Eclipse. The pom then marks the project as being an eclipse-plugin type, which effectively makes Maven resolve the project dependencies (defined in the manifest) via the target platform instead of Maven itself.
I would take the Tycho approach as it gives a much more integrated approach with Eclipse.
Having the whole jar as a dependency shouldn't be a problem, that's how you have to do it with Maven anyway.
Can I programmatically use an Eclipse plugin in my java code (so that it is independent from eclipse)?
Yes you can if:
The plugin you want to use doesn't have any external dependencies => it's just a library plugin
The plugin you want to use and ALL it's dependencies are in your classpath
No in all other cases. Because many plugins use at least the core concepts of OSGI/Equinox (have an activator) it will be quite hard to use them in a standalone java app.
For example, SWT can be used outside eclipse.
You should take a look in your eclipse directory. In the plugins folder you'll find a lot of .jar files. Sure, you could use these as dependencies in your project.
Yes, sure, you just need to care deploy plugin's jar files with you project properly.
Eclipse plugins are OSGi bundles.
OSGi bundles are JAR files that have extra info in META-INF that declares exports and imports. They sometimes make calls to OSGi APIs.
Many Eclipse plugins depend on other Eclipse-specific plugins.
If you use OSGi in your environment, you can easily reuse those plugins that have no Eclipse dependencies. If your application is not OSGi, you can only easily reuse those that avoid the direct use of OSGi APIs.
Well designed plugins are split into UI and "core" parts. You would probably want to grab just the core component. And you may well need to provide an OSGi framework to properly load and activate the plugin too - depending on how complex it is.
As others have also mentioned, don't forget the dependencies.