Osgi ServiceMix ClassCastException - java

I am having trouble with ServiceMix 5.5.2.
I have a bundle A that contain a class test.java.Root.class and after update of other bundle in ServiceMix my bundle A says:
ClassCastException : class test.java.Root can t be cast to test.java.Root
It the same class...
I know that the real problem is that this class was loading twice by different ClassLoader but I don't know why and when: the class is inside the jar and the package is not exported.
I have done refresh on the bundle but nothing work. Only a ServiceMix restart work :(
How can I find (before restarting and avoid restarting) all references of the class and where reference are still possibly in use?
Does ServiceMix propose Karaf command to see this?

Related

JAXB conflict when using OSGi Bundle in NetBeans Platform app (Netigso)

I have been struggling with this error for an entire day and I just couldn't find any posts out there. This is the error I am getting:
org.netbeans.InvalidException: Netigso: my-module-path: Cannot start com.my-bundle state remains INSTALLED after start()
This is my scenario:
-I have a NetBeans Platform v7.4 app, that uses an OSGi Module.
-Inside of the OSGi module I have a simple POJO API
-I need to add JAXB annotations "import javax.xml.bind.annotation" to the POJOs because in another non-OSGi module I am saving/reading the model from an XML file
-The OSGi module import works, as long as I do not add the #XML annotations. The moment I add the annotations, I get the error above.
Can somebody help me figure out how do I need to handle the "javax.xml.bind.annotation" import inside of the OSGi bundle? What is causing this error?

How to clean OSGi bundles cache at runtime

I have following sample scenario ... (please note that I can implement the scenario using services but I'm trying some things)
An OSGi bundle with an Activator class (name it "client") and another OSGi bundle that is a simple library (name it "server") exposing a method named callMe(). In the start() method of the "client" there is a call to the callMe() method of the "server". Of course the "server" bundle exposes the package where we have the class with callMe() method and the "client" bundle has it as imported package.
Starting the OSGi framework without the two bundles installed, I install the "client" bundle first and when I try to execute start() method the following error is shown :
org.osgi.framework.BundleException: Unresolved constraint in bundle org.example.helloworld [4]: Unable to resolve 4.0: missing requirement [4.0] osgi.wiring.package; (osgi.wiring.package=org.example.helloworldlib)
It's right because the "server" bundle isn't neither installed nor resolved.
Now, I install "server" bundle and recall start() on "client" : this time all works fine because the "server" bundle is installed so the "client" can be resolved, activated and it can call callMe() method on "server".
After that I uninstall the "server" bundle leaving the "client". The strange thing is now ... stop the "client" and re-start() it ... the "client" works ! It's able to call the callMe() method of "server" even if I uninstalled it before ! I know that OSGi framework has a bundle cache so it seems that "server" bundle is in the cache but why it's not showed in the bundles list ?
Is it possible to clean the cache at runtime ?
Paolo.
OSGi builds the wiring to needed packages when a bundles goes to the state resolved. It then keeps these wirings until refresh is called.
So it is completely normal that the client keeps working when you uninstall the server bundle.
When you call refresh the resolve step is done again. So at this point the client fails to resolve. As far as I know the wiring is not cached on disk.
So if you uninstall server and restart the framework client should also fail to resolve.

CQ5. configure classloading. Why does CQ loses class metainformation (annotations)?

We have 2 different OSGI bundles.
In first bundle exist class which parses JSON string to MyClass.MyClass annotated by Gson annotations.MyClass located in Second bundle. I have a lot of problem with it. Eventually in debug mode I have noticed that
MyClass.class.getDeclaredField("fieldName").getAnnotation(AnnotationType.class)
returns null.
Hence CQ5 somewhere losed the annotations.
I created absolutely new project, copy parser class and MyClass to this. This code really works normally.
Eventually we have understood that 'MyClass' and Gson was loaded by different classloaders and after we began load Gson same classloader and problem has been fixed. But it is very clumsy solution.
What do you think about it?
How does it fix it more elegant?
There are two places from which your bundles can import the GSON dependency:
it can be put into the OSGi container as a standalone bundle,
it can be embedded.
In order to find out which is true in your case, open the bundle in Apache Felix console and look for com.google.gson in the Imported Packages section. If it looks like this:
com.google.gson,version=2.2.4 from com.google.gson (343)
it means that your bundle imports GSON from standalone bundle 343 (case 1). On the other hand, if there is no such entry, but you can find GSON jar name:
gson-2.2.4.jar
in the Bundle Classpath, it means that you are embedding GSON into your bundle (case 2).
You found out that the cause of the problem is that GSON library in bundle1 and bundle2 is loaded by different class loaders. It means that at least one bundle uses the embedded version of the library (case 2) rather than the standalone (case 1). In order to fix this, you need to review <Embed-Depdency> directive of maven-bundle-plugin in pom.xml and remove gson from there. You may also try changing the scope of gson in your <dependencies> section to provided.

Camel - unmarshal().serialization() - ClassNotFoundException

I'm trying to unmarshal with serialization method a bean that is not the current bundle but in a commons components bundle.
I get the following error when camel tries to unmarshal my bean :
22:43:11,865 | ERROR | nModule-thread-1 | DefaultErrorHandler | 89 - org.apache.camel.camel-core - 2.8.0.fuse-06-11 | Failed
delivery for exchangeId: ID-ITEM-64684-49962-1354223882336-2-1.
Exhausted after delivery attempt: 1 caught:
java.lang.ClassNotFoundException: commons.InformationInput
java.lang.ClassNotFoundException: commons.InformationInput at
java.net.URLClassLoader$1.run(URLClassLoader.java:202)[:1.6.0_33] at
java.security.AccessController.doPrivileged(Native Method)[:1.6.0_33]
at
java.net.URLClassLoader.findClass(URLClassLoader.java:190)[:1.6.0_33]
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)[:1.6.0_33]http://stackoverflow.com/questions/6749334/osgi-bundle-access-spring-context-file-from-another-bundle
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)[:1.6.0_33]
at
org.apache.felix.framework.ModuleImpl.doImplicitBootDelegation(ModuleImpl.java:1610)
at
org.apache.felix.framework.ModuleImpl.searchDynamicImports(ModuleImpl.java:1547)
My bundle containing the bean is correctly started and i've defined the commons package in the Export-Package of the bundle definition
Does anyone managed to such thing ?
This sometimes occurs when the bundle that is serializing/deserializing classes does not know in advance what packages must be imported.
One workaround is to use DynamicImport-Package. For example:
DynamicImport-Package: *
This then means the bundle can import classes in any package, but beware of the costs (see the linked article).
This sounds similar to Hibernate issues an OSGi environment where it fails because of class loading issues. I would recommend something classed class buddy loading. in the Manifest of your commons bundle that contains the class add this
Eclipse-BuddyPolicy:registered
Then in your dependent buddy make sure you have it added as a dependent bundle and this to its manifest.
Eclipse-RegisterBuddy:com.nameofmycommonbundle
This should solve your problem.
Here is a reference to hibernate reference
I find a workaroud by enabling dynamicimport on camel-core bundle.
This can be done on karaf console : dev:dynamicimport <camel-core-bundle-id>

Servicemix - OSGi classloading issues with embedded dependencies

I'm developing project with multiple OSGi bundles, deployed on ServiceMix (FuseESB compilation, v. 4.3.1). The issue is, one of this bundles is connecting to EJB on WebLogic, therefore it embeddes weblogic.jar.
The solution is working, however a trick was required. The bundle exports Spring service via OSGi. This service is imported in another bundle, which is entry point to the system. When from this bundle the service was called, the weblogic classes were invisible. The working trick is to wrap Spring service in following aspect, which temporarly switches classloader:
public Object profileInventory(ProceedingJoinPoint pjp) throws Throwable {
Object output = null;
ClassLoader clOld = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(pjp.getTarget().getClass().getClassLoader());
output = pjp.proceed();
} finally {
Thread.currentThread().setContextClassLoader(clOld);
}
return output;
}
As I have understood, the service is called with classloader from entry bundle, not with the classloader from bundle that embedds weblogic, and for this classloader embedded dependency classes are not visible. In similar case, exported Spring service can use private imports and private packages from its bundle, but with embedded jars it is not so.
My question is: is the embedding jars something so specific, that this embedded classes will be visible only when the call originates from embedding bundle (or with classloader swich trick), or there is something more to specify when embedding bundle, something I have forgot to do?
I'm using maven-bundle-plugin
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-Name>${pom.artifactId}</Bundle-Name>
<Bundle-SymbolicName>${pom.groupId}.${pom.artifactId}</Bundle-SymbolicName>
<Embed-Dependency>
weblogic;scope=*,
</Embed-Dependency>
I have encountered a similar problem when using Spring remoting before. Spring likes to dynamically load classes using the thread context classloader, which doesn't always fare well in OSGi.
The burden to work correctly doesn't belong in the caller though, it belongs in the offending bundle. I don't have the code on hand (it was a couple of years ago), but you need to simply provide the classloader to the Spring remoting classes (I am assuming you are using Spring remoting) to handle the classloading properly.
For example, if the bundle uses SimpleRemoteStatelesSessionProxyFactory, it should be calling the setBeanClassLoader() method.

Categories