tags:

views:

253

answers:

2

Hi, After asking for help for managing dependencies on different versions of the same libraries in Java, it was suggested that I should take a look at OSGI implementations. Being under a deadline pressure, I could really use some help that would save me from digging through endless OSGI docs. I have a working app, which is going to use a new framework. The framework uses different versions of jars that I'm already using, so I want to package the new framework as an OSGI bundle. Can I leave my app as it is, and use the OSGI bundle only as a container within JVM? This would mean I would be using OSGI bundle only to isolate a set of classes from the rest of the JVM to avoid conflicts between different versions of classes. in other words, I want to use OSGI without carrying all my code to an OSGI based setup.

Kind regards Seref

A: 

First, you have to have your entire application within the OSGi framework. However, I don't think it would be difficult to set it up so that you only have to work with a few bundles (perhaps only two, depending on your setup.

The path with the fewest issues I can see would be to take the framework and "wrap" it and all of its dependencies in a single bundle. Make the packages for the dependencies private. For your main project, do the same.

The other path would be to package all the libraries separately using the appropriate wrap commands. This has significantly more potential issues if you're not interested in going full OSGi.

Depending on your build setup, I would look start by taking a look at the maven-bundle-plugin and/or Bnd. The maven-dependency plugin makes it pretty easy, as all you have to do is tell it which artifact-ids to embed and it'll do it. You will need to make sure you specify all of the embedded jar packages as private packages.

This should work unless the framework is doing class loading/AOP, which would make it significantly more difficult to OSGify.

Finally, if you're interested in a quick non-osgi solution, build the framework with the maven-shade-plugin and just rename all the packages for the conflicting libraries. This would probably be the easiest as you'd just repackage the framework with the shaded libraries once and then use that as your dependency.

deterb
+1  A: 

I do not have a complete answer for you here, I just wanted to counter what deterb said:

First, you have to have your entire application within the OSGi framework.

That is not true. Another approach would be to embed an OSGi container into a host application.

The tricky part here is the interaction between inside of OSGi and outside, because the code lives on separate classloaders.

You can make your host classes visible to the OSGi part using the OSGi system classpath. The other way around is more difficult.

One way for host code to interact with bundles is an interface that is visible to both the host application and the bundle, i.e. part of the host. Another way would be to use reflection.

If you have a clear separation between host and OSGi, for example a plugin system, then this could work quite well.

Being under a deadline pressure

That could be a problem. There is a lot to learn with OSGi, and since it is just about to hit the mainstream, there is still a lack of community knowledge, tool support, library compatibility, and so on.

The biggest question you should ask at that point is: Do I really need to manage different versions of dependencies at runtime? If not, i.e. you can figure things out at the time of deployment (for example by configuration), then there may be a simpler solution for you.

Thilo
Thanks Thilo (and deterb), here is the situation: my software is using a particular library, which has dependencies to x.v1.jar. I now have to add another library to my project, which has dependencies to x.v1.1.jar In this case, even if I manage things at build time, in runtime, there will have to be two jars, containing classes with same names, and either the first library I'm using or the second one may end up accessing the wrong version of a class, or not able to reach a class etc etc. The mess is not hard to imagine.
Now If I could create kind of a sandbox within JVM, say, by putting all of the new library into a bundle, I would be getting rid of my problem. In this case, I'd be using some sort of mechanism to load types from the wrapped library(OSGI mechanics). For example, if I can use reflection and type names to get back instances of OSGI contained types, would those types use their OSGI container's classloader? If so, they'd load types from x.v1.1.jar and this may be a solution in my case.I would consider switching the whole thing to OSGI gradually, if I can handle this little, but critical use case.
@serefakin: Yes, you could put the x.v1.1.jar into OSGi, but you also need to put the library that depends on it in there (because you need to prevent it from seeing x.v1.jar). And that makes it difficult to use the library from code outside of OSGi (unless you have an interface that can live outside as well).
Thilo
that's what I have in mind at the moment. Actually, if I can reference to types in OSGI bundle from the main project, I can simply add a factory to the OSGI bundle, which creates and returns instances (via reflection, using type names), which in turn should use OSGI bundle's class loader. This gives me what I want for now. The critical assumption here is to be able to refer to types (to be instantiated later) from the OSGI bundle, which I assume is possible Otherwise OSGI would only be able to expose interfaces, which does not sound likely.
If you do not have control over the versioned libraries you want to load, then it may be difficult to interact with them from outside the container. Because, as Thilo pointed out, it's best for the libraries to implement some service/interface that you can call from the outside. But for that, you need to create such a dependency from the libraries, which won't be easy if you cannot change them.
omerkudat
ok, I've managed to achieve what I need at the moment. I just wanted to create instances of certain types, without dependencies of those types clashing with dependencies of the code which will consume the instances. using equinox, I've build a bundle, and using transloader library, I am able to get instances out of the osgi bundle. in the future I'll probably be moving everyting into osgi. I should add that tooling support of Eclipse makes things much easier during development, compared to Apache felix.Thanks for the answers, It took me just two days to solve this :)