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.
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?
I am trying to find a set of package names in all OSGi modules by using BundleWiring's findEntries() method. For all other modules, I can simply run
bundleWiring.findEntries("/" + packageName, "*.class", 2)
to get the URL's to all classes in that package.
The problem is this approach doesn't work for OSGi System Bundle (bundle 0). Through the classloader I was able to see that the classes I want are in tomcat/webapps/ROOT/WEB-INF/lib/x.jar, but how can I find the path to those classes if I am only given System Bundle as a bundle?
The packages are exported in system.packages.extra.mf
This is not possible because the system bundle is just the "outside" of OSGi. You can use an arbitrary ClassLoader to load the OSGi Framework, and ClassLoaders don't have a way to iterate the packages or classes that they know about.
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
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.
I'm starting an OSGI Spring DM based Swing application. The app should start and show up when the bundle is loaded. I know that this can be achieved with an activator class configured by manifest.mf file.
My problem: How can I inject bean references/services to this activator class using Spring as the activator is not configured in Spring context?
Should I not use the OSGI activator? How can Spring startup the application on bundle start?
Any kind of remarks are apreciated as I'm new to OSGI with Spring DM.
Cheers, Sven
You do not need an activator. Spring-DM has an "extender" bundle that automatically scans your bundle for two things:
One or more .xml files in the META-INF/spring folder of your bundle;
A Spring-Context header in your MANIFEST.MF, which points to one or more .xml files that may be anywhere inside your bundle.
If it finds either of these (and if your bundle is in the ACTIVE state) then it will load the Spring application context using the declared XML files.