Inject CDI beans into Tapestry-5.x e.g. in Jboss-7.0.2-Final

As I explained in “Inject Java EE Beans into Tapestry-5.x“, the AppModule offers a way to configure Tapestry Web Applications directly in Java. In that post, we injected Java EE Beans into Tapestry applications. This time we do the same with Context and Dependency Injection (CDI) Beans. It follows the same procedure. The only difference is the way of looking up a bean. We still use JNDI for a lookup, but this time we retrieve the CDI BeanManager. In a second step we get the bean. For performance reasons we retrieve the bean only once per Thread (see annotation @Scope). It will be cached for subsequent lookups.

The following code snippet shows how this works:

        @SuppressWarnings("unchecked")
        private <T> T buildController(Class<T> clazz, String beanname) {
                try {
                        InitialContext ctx = new InitialContext();
                        BeanManager bmgr = (BeanManager) ctx.lookup("java:comp/BeanManager");
                        Set<Bean<?>> beans = bmgr.getBeans(clazz);
                        @SuppressWarnings("unchecked")
                        Bean<T> bean = null;
                        for (final Bean<?> b : beans) {
                                if (b != null && b.getName().equals(beanname)) {
                                        bean = (Bean<T>) b;
                                        break;
                                }
                        }
                        if (bean == null) {
                                throw new IllegalStateException("Bean with name '" +
                                   beanname + "' of type '" + clazz.getName() +
                                   "' not found" );
                        }
                        CreationalContext<T> cctx = bmgr.createCreationalContext(bean);
                        @SuppressWarnings("unchecked")
                        T o = (T) bmgr.getReference(bean, clazz, cctx);
                        return o;
                } catch (Exception e) {
                        throw new RuntimeException(e);
                }
        }
        @Scope(ScopeConstants.PERTHREAD)
        public DummyController buildDummyController(Request request, RequestGlobals globals) {
                return buildController(DummyController.class, "dummyController");
        }
        // ...
}

The bean may look like this:

@Named("dummyController")
@RequestScoped
public class DummyControllerImpl implements DummyController {
  // ...
}

Leave a Reply

Your email address will not be published. Required fields are marked *