CDI(Weld)将@Stateless EJB注入到Glassfish的@SessionScoped JSF2 bean中"无法将ejbRef转换为ejb"

Cra*_*ger 6 ejb glassfish cdi java-ee-6 jboss-weld

[ 更新:在Glassfish论坛/ ML讨论http://forums.java.net/jive/thread.jspa?messageID=480532后,对Glassfish提出了一个错误https://glassfish.dev.java.net/issues /show_bug.cgi?id=13040这个问题.]

我正在尝试将@Stateless EJB的本地无接口视图注入到JSF2 @Named @ javax.enterprise.context.SessionScoped支持bean中.EJB是扩展抽象通用基类的几种类型之一.注入"@Inject TheEJBClass varName"失败,"无法将ejbRej的EjbRef转换为类型为my.package.name.TheAbstractBase的业务对象".[编辑:实际上,事实证明注入成功,但注入代理中从超类继承的方法中的方法解析失败.]如果我使用"@EJB TheEJBClass varName",则varName保持为null,即没有注入任何内容.

细节:

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

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

@EJB TheEJBClass memberName;
Run Code Online (Sandbox Code Playgroud)

...实际上没有注入EJB,只留下memberName为null.

如果我用CDI @Inject注释注入它:

@Inject TheEJBClass memberName;
Run Code Online (Sandbox Code Playgroud)

...当我调用一个在"TheEJBClass"的超类中实现的"memberName"方法并且没有在TheEJBClass中重写时,CDI会抱怨,报告:

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)
....
Run Code Online (Sandbox Code Playgroud)

我已经尝试将基础转换为具体类并对其进行去泛化,但遇到同样的问题,所以我认为我没有使用通用基础攻击Weld错误(https://jira.jboss.org/browse/WELD-305,https://jira.jboss.org/browse/WELD-381,https://jira.jboss.org/browse/WELD-518).

为清晰起见,添加了注释的完整包认证的代码概述如下:

// 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

使用JSF2的内置生命周期和注入功能的代码非常相似,但鉴于这是一个新项目,CDI是未来的发展方向,我认为最好尝试使用CDI.这是我开始使用JSF2/EJB注入时的工作:

// 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在努力整理一个自成一体的测试用例,但我想我现在已经解决了这个问题,以防这是我只是在做一些愚蠢的事情,或者有一个众所周知的解决方案我的Google-fu isn'找到.为什么它适用于JSF2/EJB注入,但是注入CDI失败了?

(自从在Glassfish论坛上重新发布为http://forums.java.net/jive/thread.jspa?threadID=152567)

Cra*_*ger 3

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

修复:放弃 Glassfish 并转向 JBoss AS 7,它实际上在大多数情况下都可以工作。