tags:

views:

303

answers:

1

I need to expose a RMI-based system in an OSGi bundle. The RMI client "bundle" is a jar which I converted into a OSGi bundle using the bnd tool (I don't have access to the sources) and at least in eclipse everything seems to be fine, but when I try to connect to the RMI server, a ClassCastException is throwed, much probably because either OSGi and RMI make a funny use of the ClassLoader.

How can I solve this? maybe using the RMI client jar as a "system" bundle?

Here is the stack trace:

Blipnet OSGi service starting...
com.blipsystems.blipnet.api.blipserver.BlipServerConnectionException: There was a problem connecting to the server
    at com.blipsystems.blipnet.api.core.blipserver.BlipServerConnectionAdapter.(Unknown Source)
    at com.blipsystems.blipnet.api.core.blipserver.BlipServerConnectionAdapter.(Unknown Source)
    at com.blipsystems.blipnet.api.blipserver.BlipServer.getConnection(Unknown Source)
    at dk.itu.jingling.blipnetosgi.BlipnetConnectionService.setup(BlipnetConnectionService.java:28)
    at dk.itu.jingling.blipnetosgi.BlipnetConnectionService.(BlipnetConnectionService.java:22)
    at dk.itu.jingling.blipnetosgi.Activator.start(Activator.java:32)
    at org.apache.felix.framework.util.SecureAction$Actions.run(SecureAction.java:1235)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:658)
    at org.apache.felix.framework.Felix.activateBundle(Felix.java:1699)
    at org.apache.felix.framework.Felix.startBundle(Felix.java:1621)
    at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:890)
    at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:877)
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.start(DirectoryWatcher.java:819)
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.start(DirectoryWatcher.java:805)
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.startAllBundles(DirectoryWatcher.java:798)
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:299)
Caused by: java.lang.ClassCastException: com.blipsystems.blipnet.blipserver.cms.NewApiHandler_Stub cannot be cast to com.blipsystems.blipnet.api.core.blipserver.RemoteBlipServerConnection
+2  A: 

Standard Java serialization and OSGi don't mix well due to class visibility issues, and as RMI is built on top of serialization...

If you google around, you'll find plenty of people asking about RMI and OSGi but little in the way of concrete solutions.

I haven't sat down to investigate the particular problems of RMI and OSGi, but I did solve the problem of using Spring's HTTPInvoker, which still uses Java's serialization mechanism.

The problem comes down to a single class: ObjectInputStream

This is the guy responsible for de-serializing - and to de-serialize an object you need visibility of its class. If you have an modern IDE you can look at the inheritance hierarchy of this class and see that there are many extensions of it, including a couple of classes specific to RMI.

My solution was to use Spring's extensible implementation of ObjectInputStream and plug in the classloader from my bundle, so that way the de-serialization would have access to a classloader that could see my classes.

You could play around with the system bundles, but that's really a hack and I wouldn't recommend it for long-term use.

Unfortunately, OSGi still has some nasty corners that require you to dig down in the levels of abstraction to find the problem and fix it - RMI is one of those.

The Paremus guys claim to have a solution in their Service Fabric server product (an OSGi-based server) for RMI and that can be configured to work with Felix (I think Eclipse's Equinox is the default).

hbunny
steve,thank you for your reply, anyway I don't understand well: by "using Spring's HttpInvoker" you mean that you used HttpInvoker as a client for an RMI service? because the thing is that the RMI library is a closed-source proprietary library, they provide server and client but I don't have a way to change them. On top of this, they use extensively callbacks in their classes, meaning that the RMI client become also an RMI server, so I don't really know if the HttpInvoker will help in these cases
cheng81
The HTTPInvoker stuff was only a comparison of solving related problems (serialization) - I'm not suggesting you use it.
hbunny
You will need to get your hands dirty with low-level RMI to find the problem - do you have access to the source code for debugging purposes on the library?
hbunny
as usual, no :) actually I was trying to make the library shared across the OSGi container (I know, It's not a good thing to do), but I didn't managed (http://stackoverflow.com/questions/1496995/how-to-configure-a-system-wide-package-in-osgi)
cheng81