6

[更新:在http://forums.java.net/jive/thread.jspa?messageID=480532讨论 Glassfish 论坛/ML 后,针对 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”失败,并显示“无法将 ejb TheEJBClass 的 ejbRef 转换为 my.package.name.TheAbstractBase 类型的业务对象”。[编辑:实际上,事实证明注入成功,但是从超类继承的方法的注入代理中的方法解析失败。]如果我使用“@EJB TheEJBClass varName”,则 varName 保持为空,即没有注入任何内容。

细节:

我在 Linux 上运行 Glassfish 3.0.1(Ubuntu 10.04 以防万一)并且在处理使用 CDI(焊接)将我的数据模型 EJB 注入到我的 JSF2 会话范围模型中时遇到了实际问题。是的,在你问之前,我已经准备好 beans.xml 并且 CDI 正在激活以执行注入。

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

@EJB TheEJBClass memberName;

... EJB 实际上并没有被注入,因此 memberName 为空。

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

@Inject TheEJBClass memberName;

...然后,当我调用在 TheEJBClass 的超类中实现且未在 TheEJBClass 中覆盖其自身的“memberName”方法时,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)
....

我已经尝试将基础转换为具体类并对其进行反泛化,但遇到了同样的问题,所以我认为我不会使用通用基础来解决 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;
    }
}

请注意,如果我在 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;
    }
}

我目前正在整理一个独立的测试用例,但我想我现在会提出这个问题,以防我只是在做一些愚蠢的事情,或者我的 Google-fu 有一个众所周知的解决方案'直到找到。为什么它适用于 JSF2/EJB 注入,但会因 CDI 注入而失败?

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

4

1 回答 1

3

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

修复:放弃 Glassfish 并迁移到 JBoss AS 7,它实际上大部分时间都可以工作。

于 2011-11-29T03:36:44.567 回答