Thursday, September 29, 2011

CDI and Enterprise Archives

I would be the first one to admit that I do not yet have total mastery of Contexts and Dependency Injection (CDI) in Java EE 6. I understand it fairly well, I believe. But there has not yet been a chance for me to use it on a real job, since no clients we deal with have moved up to Java EE 6. So far it has just been experimental projects on Glassfish 3.1 or JBoss AS 6/7.

Having said that, it took me aback when I tried to inject (with @Inject) a session bean from an EJB JAR, in an EAR project, into a JSF managed bean. I used @Named, not @ManagedBean. The scope was CDI, and not JSF.

When I tried to invoke a JSF action on the managed bean, I kept on getting the standard NPE that we see if there is no beans.xml. In fact the wording was identical. It indicated that the JSF managed bean could not be located. Now, I certainly had a beans.xml - several in fact. And some experimentation with annotations revealed that CDI was in effect.

So why was it that CDI could not locate the JSF managed bean?

Turns out that it had everything to do with trying to inject an EJB from the EJB JAR, into the JSF managed bean in the WAR. In all of my early experiments I had used one monolithic WAR, that included the EJBs, so I never had this problem. And for the life of me I could not conceieve of a situation where you could not inject EJBs from an EJB JAR in the same EAR as the WAR.

Well, evidently you cannot. At least not in Glassfish.

I finally had to use the approach described here: inject-a-stateless-ejb-with-inject-into-cdi-weld-managedbean-jsf-1-2-ejb-application

I should note that while this link references JSF 1.2, I also had to do this for JSF 2.0. I should also note that the server exception was very misleading - it was the @Inject that was failing, not the @Named on the JSF managed bean.

Based on various problem reports:

JBoss AS 7: CDI/EJB Injection in EAR Deployments
CDI Broken between EJB Module and JPA Utility JAR

it sure looks to me like all of this has not been resolved. It could be the specifications are clear on this, and I plan to do some intensive reading. But what good is that if the implementations are not getting it?

This article, JBoss 6 and Cluster-wide EJB Injection, sort of leaves the impression that we should not be having this kind of problem. Furthermore, the discussion in Chapter 8 of the Seam documentation, Producer Methods, leads me to believe that @Produces ought not to be required, since we already have an EJB. Needing a producer just to make an EJB from an EJB JAR available for injection into a WAR - in the same EAR - seems pretty clunky. I just wonder why I should not use @EJB instead.

Anyway, back to the books, I guess. There are still decent reasons why one might want an EAR with separate EJB JARs, and WARs, and JPA utility JARs, and what not. And I refuse to believe that the specs mandate that an awkward workaround has to be applied for EJBs that are to be injected, if they reside in a different module than the one that contains the injection point.

No comments:

Post a Comment