RMI Client in an OSGi Container

I need to open an RMI-based system in an OSGi bundle. The RMI client package is a jar that I converted to an OSGi package using the bnd tool (I don't have access to the sources), and at least in eclipse everything seems fine, but when I try to connect to RMI, a ClassCastException is thrown. probably because OSGi and RMI make fun use of ClassLoader.

How can i solve this? perhaps using an RMI client jar as a "system" package?

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
+4
source share
2 answers

Standard serialization Java and OSGi do not mix well because of class visibility problems, and since RMI is built on top of serialization ...

If you google around, you will find many people asking about RMI and OSGi, but a little in the way of specific solutions.

I did not sit down to investigate the specific problems of RMI and OSGi, but I solved the problem of using Spring HTTPInvoker , which still uses the Java serialization mechanism.

The problem boils down to one class: ObjectInputStream

This is the guy responsible for de-serializing - and to de-serialize an object, you need the visibility of its class. If you have a modern IDE, you can look at the inheritance hierarchy of this class and see that there are many extensions, 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 package so that de-serialization will have access to the classloader that my classes could see.

You can play with system packages, but it really is a hack, and I would not recommend it for long-term use.

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

Paremus guys claim to have a solution in their server fabric Service Fabric (OSGi-based server) for RMI, and this can be configured to work with Felix (I think Eclipse Equinox is the default).

+5
source

I had the same problem and am surprised how easy it is to solve it. I have three packages: bundleA, bundleB, bundleC. bundleA is a set of abstract classes that know nothing about the connectivity of B and bundleC. BundleB uses bundleA and bundleC. bundleC is used by bundle B.

So bundleA <-- bundleB --> bundleC .

In bundleA, I have code that calls an RMI server and works with classes from bundleC. And here I had a problem - ClassNotFoundException. So, the following code I used in the bundleA class

 ClassLoader threadClassLoader= Thread.currentThread().getContextClassLoader(); try { Class bundleCSomeClass = someVariablePassedFromBundleB.getMyClass(); Thread.currentThread().setContextClassLoader(bundleCSomeClass.getClassLoader()); //here we are calling RMI service } catch (RemoteException ex) { }finally{ Thread.currentThread().setContextClassLoader(threadClassLoader); } 
0
source

All Articles