I use felix and pax-cdi 0.13 and weld. I have two bundles A in B. In bundle A I have BundleTracker and Customizer, in bundle B I have CDI beans. So I want in bundle tracker to get cdi beans from bundle B using bean manager. So I have method in customizer:
@Override
public Object addingBundle(Bundle bundle, BundleEvent event) {
String marker = (String) bundle.getHeaders().get("Some-Marker");
if (marker != null) {
try {
//1 we get CdiContainerFactory
BundleContext thisBundleContext=FrameworkUtil.getBundle(this.getClass()).getBundleContext();
ServiceReference<?> sr = thisBundleContext.getServiceReference(CdiContainerFactory.class.getName());
CdiContainerFactory cdiContainerFactory = (CdiContainerFactory) thisBundleContext.getService(sr);
if (cdiContainerFactory==null){
System.out.println("Cdi container factory is null");
}else{
System.out.println("Cdi container factory is not null");
}
//2 we get BeanManager from CdiContainerFactory
Class<?> klass = bundle.loadClass("com.temp.Temp");
BeanManager beanManager = cdiContainerFactory.getContainer(bundle).getBeanManager();
Bean<?> bean = (Bean<?>)beanManager.resolve(beanManager.getBeans(klass));
Object temp= beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));
} catch (ClassNotFoundException ex) {
Logger.getLogger(ExtenderBundleTracker.class.getName()).log(Level.SEVERE, null, ex);
}
}
return bundle;
}
To register bundle tracker I use the following code:
bundleTracker=new BundleTracker<>(context, Bundle.ACTIVE, new MyCustomizer());
The code above works. But not always. I have timing problem. I always get Cdi container factory is not null
, but the following line
BeanManager beanManager = cdiContainerFactory.getContainer(bundle).getBeanManager();
sometimes throws NullPointerException. As I suppose when Bundle B becomes active CDI container is still not ready for it. How can such problem be solved?
The fact that the bean manager sometimes cannot be found is due to the fact that the CDI container is (asynchronously) created by a bundle listener from the PAX-CDI bundles as well. This means that you may run into a race condition because the container may or may not be created at the time your bundle listener is called.
When using PAX-CDI, I would not recommend trying to access the bean manager, but in stead export the bean you need as an OSGi service (@OsgiServiceProvider annotation on the bean) and track that service via a ServiceTracker
. If that is not possible because of the scope of the bean, you can always create a separate factory pattern bean in the container that does the bean creation work for you and export that one as a service.