Quirks and twists of testing CODI @Bundle with OpenEJB ApplicationComposer


Using JavaEE means also testing JavaEE with all the implications!

I personally use an ApplicationComposer from OpenEJB when writing unit tests not requiring all containers (as in web, cdi, ejb, …) up and running but just enough to have injection and deploy ejbs. I am not happy with ApplicationComposer because I think it has number of limitations but that’s another discussion. If you care, you can read up on ApplicationComposer in this nice post from Romain Manni Bucau.

Just recently I encountered an issue when ApplicationComposer-testing application using MyFaces CODI extensions. The error shows as an exception (I marked the interesting parts red):

SEVERE - CDI Beans module deployment failed
javax.enterprise.inject.UnsatisfiedResolutionException: Api type [org.apache.myfaces.extensions.cdi.core.api.resource.bundle.ResourceBundle]
is not found with the qualifiers Qualifiers: [@javax.enterprise.inject.Default()] for injection into Field Injection Point, field name : excelTemplate
, Bean Owner : [ScheduleWorkbookController, Name:null, WebBeans Type:MANAGED, API Types: my.app.ScheduleWorkbookController,java.lang.Object,java.io.Serializable]
, Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]]
at org.apache.webbeans.util.InjectionExceptionUtil.throwUnsatisfiedResolutionException(InjectionExceptionUtil.java:77)
at org.apache.webbeans.container.InjectionResolver.checkInjectionPoints(InjectionResolver.java:178)
at org.apache.webbeans.container.BeanManagerImpl.validate(BeanManagerImpl.java:914)
at org.apache.webbeans.config.BeansDeployer.validate(BeansDeployer.java:440)
at org.apache.webbeans.config.BeansDeployer.validateInjectionPoints(BeansDeployer.java:390)
at org.apache.webbeans.config.BeansDeployer.deploy(BeansDeployer.java:194)
at org.apache.openejb.cdi.OpenEJBLifecycle.startApplication(OpenEJBLifecycle.java:182)
at org.apache.openejb.cdi.ThreadSingletonServiceImpl.initialize(ThreadSingletonServiceImpl.java:158)
at org.apache.openejb.cdi.CdiBuilder.build(CdiBuilder.java:43)
...

Now what we see here is that

  • CDI container does not find some bean class (UnsatisfiedResolutionException)
  • in particular it cannot find ResourceBundle class
  • injected as a variable excelTemplate
  • into ScheduleWorkbookController

Ok so according to ApplicationComposer configuration rules “all” we have to is to add all the CDI relevant classes to a Class array returned by the @Module method:

@RunWith(ApplicationComposer.class)
public MyTest {
    @Module
    public Class[] classes() {
        return new Class[] { ScheduleWorkbookController.class, ExcelTemplate.class, ResourceBundle.class };
    }
}

That’s it right? Wrong, the exception will still occur!

The reason is the fact that the org.apache.myfaces.extensions.cdi.core.api.resource.bundle.ResourceBundle is just an interface. You still need the implementing class so that during CDI container initialization the real instances can be injected.

So let us find out if there are classes provided in CODI implementation that implement ResourceBundle. In fact there is exactly one default class org.apache.myfaces.extensions.cdi.core.impl.resource.bundle.DefaultResourceBundle.

Alas, adding it to the @Module class array will NOT work since the DefaultResourceBundle has package visibility!

Now, the solution is logical at the end but believe me, based on error messages and semi-chaotic attempts to somehow make it work, it did not came to me the easy way.

Unless you have already guessed – the solution is to add org.apache.myfaces.extensions.cdi.core.impl.resource.bundle.ResourceBundleProducer to the @Module class list.

That’s right – the class producing the actual instances of ResourceBundle!