代码之家  ›  专栏  ›  技术社区  ›  Craig Ringer

在将@stateless ejb注入@sessionscoped jsf2 bean-in-glassfish中的cdi(weld)时,“无法转换ejbRef for ejb”

  •  6
  • Craig Ringer  · 技术社区  · 14 年前

    [ 更新 :在Glassfish论坛上讨论后/ml http://forums.java.net/jive/thread.jspa?messageID=480532 一只虫子被用来对付玻璃鱼。 https://glassfish.dev.java.net/issues/show_bug.cgi?id=13040 关于这个问题。]

    我正在尝试将@stateless EJB的本地无接口视图注入名为@javax.enterprise.context.sessionscoped backing bean的jsf2。EJB是扩展抽象泛型基类的几种类型之一。“@inject theejbclass varname”的注入失败,原因是“无法将ejb的ejbRef转换为class my.package.name.theabstractBase类型的业务对象”。 [编辑:事实上,事实证明注入成功,但是从超类继承的方法的注入代理中的方法解析失败。] 如果我使用“@ejb theejbclass varname”,那么varname将保持为空,即不注入任何内容。

    细节:

    我在Linux上运行Glassfish 3.0.1(如果有问题的话,可以使用Ubuntu10.04),在处理使用CDI(Weld)将数据模型EJB注入JSF2会话范围的模型时遇到了实际问题。是的,在您询问之前,我已经准备好beans.xml,CDI正在激活以执行注入。

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

    @EJB TheEJBClass memberName;
    

    …实际上没有注入EJB,membername为空。

    如果我用cdi@inject注释注入它:

    @Inject TheEJBClass memberName;
    

    …然后,当我调用“membername”方法时,CDI会抱怨,该方法是在jbclass的超类中实现的,而不是在jbclass本身中重写的,报告:

    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)
    ....
    

    我试过将基础转换为具体的类并对其进行反泛型,但遇到了同样的问题,所以我不认为我用通用的基础会碰到焊接错误。( 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;
        }
    }
    

    注意注射 如果我重写了jbClass中的bstractBase.getValue(),或者如果我调用了jbClass中定义的方法,而不是任何超类,则可以工作。这似乎与继承有关。

    使用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 )

    1 回复  |  直到 13 年前
        1
  •  3
  •   Craig Ringer    13 年前

    如上所述,这是一个焊接/玻璃鱼虫。

    解决方法:放弃Glassfish,以7的身份迁移到JBoss,这在大多数情况下都是有效的。