My Question is
I have two osgi bundles, In which one bundle has hazelcast (3.3 version) jar and I have exported all the packages in it... which means the other bundle can use all the packages of hazelcast available in first bundle.
So what I planned is,
-> One bundle is for keeping the hazelcast jar as common bundle.
-> Other bundle is for performing the business operations in which the first bundle will be the dependent bundle for this,
I have the hazelcast xml which has a serialization factory mapping in it.
Note : The serialization factory class is there in other bundle (Not in hazelcast jar bundle), So what happens is when I start the hazelcast server, It clearly says that the serialization factory class is not found.
com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassNotFoundException: com.test.beans.SerializableFactory
at com.hazelcast.nio.serialization.SerializationServiceBuilder.buildDataSerializableFactories(SerializationServiceBuilder.java:290)
at com.hazelcast.nio.serialization.SerializationServiceBuilder.addConfigDataSerializableFactories(SerializationServiceBuilder.java:247)
at com.hazelcast.nio.serialization.SerializationServiceBuilder.build(SerializationServiceBuilder.java:169)
at com.hazelcast.instance.Node.createSerializationService(Node.java:193)
at com.hazelcast.instance.Node.<init>(Node.java:140)
at com.hazelcast.instance.HazelcastInstanceImpl.<init>(HazelcastInstanceImpl.java:120)
at com.hazelcast.instance.HazelcastInstanceFactory.constructHazelcastInstance(HazelcastInstanceFactory.java:153)
at com.hazelcast.instance.HazelcastInstanceFactory.newHazelcastInstance(HazelcastInstanceFactory.java:136)
at com.hazelcast.instance.HazelcastInstanceFactory.newHazelcastInstance(HazelcastInstanceFactory.java:112)
at com.hazelcast.core.Hazelcast.newHazelcastInstance(Hazelcast.java:58)
For your INFORMATION, I already tried config.setClassloader
Related
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?
As I understand right every osgi bundle has its own cdi container. So I have the following situation - I have two bundles: A and B. Bundles are deployed in glassfish4. In bundle A I have cdi beans. In bundle B I don't have beans.xml -> no cdi container for the bundle B is created.
In bundle B I have a reference to bundle A (Bundle bundleA). How can I get in bundle B reference to bundle A cdi container. My current solution (in bundle B):
BeanManager bm = CDI.current().getBeanManager();
throws exception:
StandardWrapperValve[default]: Servlet.service() for servlet default threw exception
org.jboss.weld.exceptions.IllegalStateException: WELD-001328: Unable to identify the correct BeanManager. The calling class com.temp.MyClass is not placed in bean archive
at org.jboss.weld.SimpleCDI.unsatisfiedBeanManager(SimpleCDI.java:89)
at org.glassfish.weld.GlassFishWeldProvider$GlassFishEnhancedWeld.unsatisfiedBeanManager(GlassFishWeldProvider.java:89)
at org.jboss.weld.SimpleCDI$ClassNameToBeanManager.findBeanManager(SimpleCDI.java:67)
at org.jboss.weld.SimpleCDI$ClassNameToBeanManager.load(SimpleCDI.java:47)
at org.jboss.weld.SimpleCDI$ClassNameToBeanManager.load(SimpleCDI.java:40)
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3589)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2374)
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2337)
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2252)
at com.google.common.cache.LocalCache.get(LocalCache.java:3990)
at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3994)
at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4878)
at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4884)
at org.jboss.weld.SimpleCDI.getBeanManager(SimpleCDI.java:105)
at org.jboss.weld.SimpleCDI.getBeanManager(SimpleCDI.java:38)
Calling BeanManager bm = CDI.current().getBeanManager(); is the correct way to obtain a BeanManager for current bean archive. E.g. the bean archive to which the class where you invoke this belongs. That would be bundle B in your case. And you do not have a beans.xml there hence the exception.
As I understand right every osgi bundle has its own cdi container.
I am not much familiar with OSGI but from Weld perspective that would work. Weld sees any form of archive (jar, war, ...) as bean archive and for one bean archive you have one manager.
If you want a reference to BM from bundle A, obtain it there and expose a getter I suppose. The point is you need to invoke getBeanManager() from the actual archive it belongs to.
Maybe if you elaborated on what do you aim to achieve with that BM, I might help you further. Generaly speaking I would refrain from obtaining references to BMs from other archives. You can always have an exposed API and let the original archive deliver the services to you.
I noticed a fragment I have uses a Export-Package directive for the package that is contributed to its host:
Fragment-Host: org.eclipse.jetty.osgi.boot
Export-Package: org.eclipse.jetty.osgi.boot.utils;version="1.0.1.felix"
-buildpath: osgi.core;version=4.3.0,\
org.eclipse.jetty.osgi.boot;version=7.6.1.v20120215
-sources: false
Import-Package: !org.eclipse.jetty.osgi.boot.utils.internal,\
*
This bundle contributes some extra classes into the org.eclipse.jetty.osgi.boot.utils package in the host.
Ideally I think I should strive to keep packages private where possible, but what about this case? None of the rest of my code requires org.eclipse.jetty.osgi.boot.utils.
From the OSGi core specification (6.0):
A host bundle's class path is searched before a fragment's class path.
"This bundle contributes a new org.eclipse.jetty.osgi.boot.utils with classes that override those of the host"
Fragment bundles cannot override the classes of the host bundle (if that was what you meant).
If a package is not intended to use by other bundles, it should not be exported. The host bundle can see the classes and resources of its attached fragment bundle, but only if it does not have the same class or resource.
The accepted answer of #balazs-zsoldos:
Fragment bundles cannot override the classes of the host bundle
...is correct in this specific case, but it is not true in general. A more nuanced answer would be that fragments cannot override the host bundle's classes unless the host bundle has been configured to allow it (which in your case the org.eclipse.jetty.osgi.boot bundle is not).
The way you configure the host bundle to allow it is by using the Bundle-ClassPath header. Let's assume you have a host bundle A with an attached fragment B, and A has the following manifest entry:
Bundle-ClassPath: contrib,.
Suppose the bundle classloader is asked to look for class pack.Z in bundle A. The bundle classloader will search in the following order:
A:contrib/pack/Z.class
B:contrib/pack/Z.class
A:pack/Z.class
B:pack/Z.class
So you can see that if your contrib directory in A is empty or non-existent, then the bundle classloader will try and load B:contrib/pack/Z.class before it will try and load A:pack/Z.class. But as you can see, this is only possible if A was explicitly built to allow it.
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.
We have a problem using a custom JCA implementation in our OSGi bundle. The JCA implementation that we are forced to use by our customer leads to a class loader memory leak. This prevents the deployment and usage of it in our bundle, because we quickly run into a perm gen space problem.
The proposed solution from the JCA provider is to put the JAR in the jre/lib/ext folder, but it is not loaded from there. This is due, as far as I know, to the OSGi (Eclipse equinox) class loader policy to have the bootstrap classloader as the parent of each bundle classloader, which excludes the extension class loader that loads from the jre/lib/ext folder. I.e. no bundle ever sees anything in the jre/lib/ext folder.
Is there a way to get Eclipse equinox to load a jar that is registered as a security provider, only once, such that all bundles or a specific bundle can see that provider? The fact that the JCA library is not unloaded via OSGi could be tolerated in this instance.
You should edit the system packages and add the packages from the JCA-custom.jar.
You can define which packages should be included in several ways.
You create a profile for equinox and define the packages. You can find examples for each jdk versions in the eclipse.osgi jar. For example, look for JavaSE-1.6.profile and try finding the entry org.osgi.framework.system.packages
You can define it as a system variable when you start your OSGi container. The system variable is the same: -Dorg.osgi.framework.system.packages=package names separated by comma