Skip to main content

"Unable to convert ejbRef for ejb" during @Inject of EJB

1 reply [Last post]
ringerc
Offline
Joined: 2008-06-08

Hi folks

First: I'm somewhat new to Java EE and DI, so I may be missing the obvious as I try to wrap my head around the three different DI systems (JSF2, CDI/Weld, EJB) in Java EE 6.1 . I've read the tutorial, done a lot of searching, etc though, so if I'm missing the obvious it's because I'm asking the wrong questions.

I'm running Glassfish 3.0.1 on Linux (Ubuntu 10.04 in case it matters) and having real problems handling injection of my data model EJBs into my JSF2 session scoped models using CDI (Weld). And yes, before you ask, I have beans.xml in place and CDI is activating, trying to inject, and throwing an exception (see below).

I'm trying to inject a local no-interface view of a @Stateless EJB into a JSF2 @Named @SessionScoped backing bean. The EJB is one of several that extend an abstract generic base class.

If I inject it with an @EJB annotation, eg:

@EJB TheEJBClass memberName;

... the EJB isn't actually injected, leaving memberName null.

If I inject it with a CDI @Inject annotation:

@Inject TheEJBClass memberName;

... then CDI complains, reporting:

<br />
java.lang.IllegalStateException: Unable to convert ejbRef for ejb TheEJBClass to a business object of type class my.package.name.TheAbstractBase<br />
	at com.sun.ejb.containers.EjbContainerServicesImpl.getBusinessObject(EjbContainerServicesImpl.java:104)<br />
	at org.glassfish.weld.ejb.SessionObjectReferenceImpl.getBusinessObject(SessionObjectReferenceImpl.java:60)<br />
    ....<br />

I've tried converting the base to concrete class and de-generifying it, but encounter the same problem, so I don't think I'm hitting the Weld bugs with generic bases (https://jira.jboss.org/browse/WELD-305, https://jira.jboss.org/browse/WELD-381, https://jira.jboss.org/browse/WELD-518).

An outline of the code, with full package qualification on annotations added for clarity, is:

<br />
// JSF2 managed backing bean.<br />
//<br />
// Called from JSF2 .xhtml via #{someJSF2Model.value}<br />
//<br />
@javax.inject.Named<br />
@javax.enterprise.context.SessionScoped<br />
public class SomeJSF2Model implements Serializable {<br />
   @javax.inject.Inject TheEJBClass member;<br />
   public Integer getValue() {<br />
       return member.getValue();<br />
   }<br />
   // blah blah<br />
}</p>
<p>// One of several EJB classes that extend TheAbstractBase<br />
@javax.ejb.Stateless<br />
public class TheEJBClass extends TheAbstractBase {<br />
  // blah blah<br />
  // does **NOT** override "getValue()"<br />
}</p>
<p>public abstract class TheAbstractBase {<br />
 // blah blah<br />
    public Integer getValue() {<br />
        return 1;<br />
    }<br />
}<br />

Note that injection does work if I override TheAbstractBase.getValue() in TheEJBClass, or if I call a method defined in TheEJBClass and not any superclass. It seems like the issue is something to do with inheritance.

I'm really quite lost trying to figure out how all the DI stuff interacts in Java EE 6, and would really, really appreciate a helping hand. Once you figure the lifecycle stuff out and the conceptual structure behind what it's for / how it works, it seems like a good idea, but I'm struggling with the practical aspects. In this case, for example, I can't for the life of me figure out why Weld cares that TheEJBClass extends TheAbstractBase, given that I'm injecting it explicitly via a local no-interface view.

Very similar code that used JSF2's built-in lifecycle and injection features worked, but given that this is a new project and CDI is where things are heading in the future, I thought it best to try to go for CDI. Here's what I started out with using JSF2/EJB injection, which worked:

<br />
// JSF2 managed backing bean. Using @ManagedBean and JSF2's @SessionScoped<br />
// instead of CDI @Named and CDI @SessionScoped this time.<br />
//<br />
@javax.faces.bean.ManagedBean<br />
@javax.faces.bean.SessionScoped<br />
public class SomeJSF2Model implements Serializable {<br />
   @javax.ejb.EJB TheEJBClass member;<br />
   public Integer getValue() {<br />
       return member.getValue();<br />
   }<br />
   // blah blah<br />
}</p>
<p>// One of several EJB classes that extend TheAbstractBase<br />
// Unchanged from CDI version<br />
@javax.ejb.Stateless<br />
public class TheEJBClass extends TheAbstractBase {<br />
  // blah blah<br />
  // does **NOT** override "getValue()"<br />
}</p>
<p>// Unchanged from CDI version<br />
public abstract class TheAbstractBase {<br />
 // blah blah<br />
    public Integer getValue() {<br />
        return 1;<br />
    }<br />
}<br />

I'm currently working on putting together a self-contained test case, but thought I'd fire off the question now in case this is something where I'm just doing something silly or there's a well known solution my Google-fu isn't up to finding. Why did it work with JSF2/EJB injection, but fail with CDI injection?

(Question also appears on StackOverflow - http://stackoverflow.com/questions/3509255/unable-to-convert-ejbref-for-... and links back here)

Message was edited by: ringerc

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
ringerc
Offline
Joined: 2008-06-08

It looks like this may be a Glassfish Weld/CDI integration bug. See the follow-up post with a test case: http://forums.java.net/jive/message.jspa?messageID=480532#480532