“无法转换ejbRef for ejb”在CDI(Weld)上将@Stateless EJB注入Glassfish中的@SessionScoped JSF2 bean

“无法转换ejbRef for ejb”在CDI(Weld)上将@Stateless EJB注入Glassfish中的@SessionScoped JSF2 bean

问题描述:

[更新:在 http://forums.java.net/jive/thread.jspa?messageID=480532 对Glassfish提交的错误 https://glassfish.dev.java.net/issues/show_bug.cgi?id=13040 发生此问题。]

[UPDATE: After discussion on the Glassfish forums/ML at http://forums.java.net/jive/thread.jspa?messageID=480532 a bug was filed against Glassfish https://glassfish.dev.java.net/issues/show_bug.cgi?id=13040 for this issue.]

我试图将@Stateless EJB的本地*面视图注入到JSF2 @Named @ javax.enterprise.context.SessionScoped后备bean中。 EJB是扩展抽象通用基类的几个。注入@Inject TheEJBClass varName失败,无法将ejb的ejbRef TheEJBClass转换为类my.package.name.AbstractBase的业务对象。实际上,事实证明注入是成功的,但注入代理中的方法解析从继承自超类的方法失败。] 如果我使用@EJB TheEJBClass varName,那么varName保持为空,即没有被注入。

I'm trying to inject a local no-interface view of a @Stateless EJB into a JSF2 @Named @javax.enterprise.context.SessionScoped backing bean. The EJB is one of several that extend an abstract generic base class. Injection of "@Inject TheEJBClass varName" fails with "Unable to convert ejbRef for ejb TheEJBClass to a business object of type class my.package.name.TheAbstractBase". [edit: Actually, it turns out that injection succeeds, but method resolution in the injected proxy for methods inherited from superclasses fails.] If I use "@EJB TheEJBClass varName" then varName remains null, ie nothing is injected.

详细信息:

我在Linux上运行Glassfish 3.0.1(如果是Ubuntu 10.04重要),并且将处理我的数据模型EJB注入到使用CDI(Weld)的JSF2会话范围模型中的真正问题。是的,在你问之前,我有了beans.xml,CDI正在激活执行注入。

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 to perform injection.

如果我用@EJB注释注入它,例如: / p>

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

@EJB TheEJBClass memberName;

... EJB没有实际注入,留下memberName为空。

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

如果我注入一个CDI @Inject注释:

If I inject it with a CDI @Inject annotation:

@Inject TheEJBClass memberName;

...然后CDI抱怨当我调用一个memberName的方法,该方法实现在超类该EJBClass并没有在TheEJBClass中被覆盖,它的自我报告:

... then CDI complains when I call a method of "memberName" that's implemented in a superclass of TheEJBClass and not overridden in TheEJBClass its self, reporting:

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

我已经尝试将基础转换为具体的类并将其解除了,但遇到同样的问题,所以我不认为我用通用基础击中了Weld错误( https://jira.jboss.org/browse/WELD-305 https://jira.jboss.org/browse/WELD-381 https: //jira.jboss.org/browse/WELD-518 )。

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:

// JSF2 managed backing bean.
//
// Called via #{someJSF2Model.value} in a JSF2 page
//
@javax.inject.Named
@javax.enterprise.context.SessionScoped
public class SomeJSF2Model implements Serializable {
   @javax.inject.Inject TheEJBClass member;

   public Integer getValue() {
       return member.getValue();
   }
   // blah blah
}

// One of several EJB classes that extend TheAbstractBase
@javax.ejb.Stateless
public class TheEJBClass extends TheAbstractBase {
  // blah blah
  // does **NOT** override "getValue()"
}

public abstract class TheAbstractBase {
    // blah blah
    public Integer getValue() {
        return 1;
    }
}

请注意,注入 如果我覆盖TheEJBClass中的TheAbstractBase.getValue(),或者如果我调用在TheEJBClass中定义的方法,而不是任何超类。似乎这个问题与继承有关。

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.

使用JSF2内置生命周期和注入功能的非常类似的代码有效,但鉴于这是一个新项目CDI是未来的事情,我认为最好尝试去CDI。这是我使用JSF2 / EJB注入开始的,它的工作原理是:

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:

// JSF2 managed backing bean. Using @ManagedBean and JSF2's @SessionScoped
// instead of CDI @Named and CDI @SessionScoped this time.
//
@javax.faces.bean.ManagedBean
@javax.faces.bean.SessionScoped
public class SomeJSF2Model implements Serializable {
   @javax.ejb.EJB TheEJBClass member;
   public Integer getValue() {
       return member.getValue();
   }
   // blah blah
}

// One of several EJB classes that extend TheAbstractBase
// Unchanged from CDI version
@javax.ejb.Stateless
public class TheEJBClass extends TheAbstractBase {
  // blah blah
  // does **NOT** override "getValue()"
}

// Unchanged from CDI version
public abstract class TheAbstractBase {
    // blah blah
    public Integer getValue() {
        return 1;
    }
}

我正在努力整合自我,但是以为我现在就会解决这个问题,以防这是我刚刚做的事情,或者有一个众所周知的解决方案,我的Google-fu不能找到。为什么它与JSF2 / EJB注入一起工作,但CDI注入失败?

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?

(自从Glassfish论坛上重新发布为

( Since re-posted on the Glassfish forums as http://forums.java.net/jive/thread.jspa?threadID=152567 )

如上所述,这是一个Weld / glassfish bug。

As noted above, it's a Weld/glassfish bug.

修复:给在Glassfish上移动到JBoss AS 7,这实际上是大部分时间工作。

Fix: Give up on Glassfish and move to JBoss AS 7, which actually works most of the time.