【问题标题】:How can I inject an EJB with no interface into a Spring bean?如何将没有接口的 EJB 注入 Spring bean?
【发布时间】:2015-12-29 15:36:59
【问题描述】:

我有几个 EJB 3.x 无状态会话 bean,它们没有定义接口。我需要将这些 bean 注入 Spring bean,但我无法这样做。

没有接口 EJB:

@Singleton
public class MyNoInterfaceEJB {
   public String sayHello() { return "hi"; }
}

我的豆子:

@Named
public class MyEJBClientBean {
   @EJB
   private MyNoInterfaceEJB testejb;

   // ...
}

还有我的 bean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:jee="http://www.springframework.org/schema/jee"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-3.0.xsd
  http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">

    <jee:local-slsb id="testejb" jndi-name="java:global/MyEAR/MyModule/MyProject!com.test.MyNoInterfaceEJB"
            business-interface="com.test.MyNoInterfaceEJB"/>

    <context:annotation-config />
    <context:component-scan base-package="com.test" />
 </beans>

在 spring 容器初始化时,出现以下错误:

Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'testejb': 
Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: [com.test.MyNoInterfaceEJB] is not an interface

异常本身非常清楚——spring 容器期望我的 bean 具有本地接口视图,因为它是业务接口;但是,我没有(也不能介绍)。

非常感谢任何帮助!

【问题讨论】:

  • 这是我能找到的最接近的相关问题:stackoverflow.com/questions/23008810/… -- 但它需要使用远程和本地接口视图,这对我来说不是一个选项。
  • EJB、CDI(如 @Named 所暗示的那样。因此,您所说的“控制器”现在由 CDI 而非 Spring 管理)、您应该使用的 JPA 等是其中的一部分Java EE。是什么让您仍然坚持使用 Spring,即您使用 Spring 的哪些功能在 Java EE 中不可用? (这没有争议,而是一个一般用例)。

标签: spring ejb-3.1


【解决方案1】:

例外是您的 spring 配置文件中的&lt;jee:local-slsb&gt; 元素的结果。您在元素的业务接口属性中提供实现类。

我不确定 Spring 是否能够处理 Spring bean 中的 @EJB 注释。如果没有,您可以让您的 spring bean 实现 Spring 接口 org.springframework.beans.factory.InitializingBean 并为无接口 EJB 执行编程 JNDI 查找。

希望对您有所帮助。

【讨论】:

  • 是的 - 这就是我前进的方向......如果我可以让 Spring 使用无接口视图自动装配 EJB 会简单得多......
【解决方案2】:

在@EJB注解上指定映射名称就足够了,并从bean.xml中删除local-slsb声明

我不知道为什么 Spring 需要映射名称,或者无法自己弄清楚。如果您还不知道,请从应用服务器的调试日志中找出它。

@Named
public class MyEJBClientBean {

    @EJB(mappedName="java:global/MyApp/MyModule/MyNoInterfaceEJB!com.initech.MyNoInterfaceEJB ")
    private MyNoInterfaceEJB testejb;

  // ...

}

上面的例子是完整 EAR 中的全名,如果没有冲突,它也可能绑定到“更短”的 jndi-names。

【讨论】:

    【解决方案3】:

    使用

    <jee:jndi-lookup jndi-name="java:app/domains/BaseDao" expected-type="com.project.core.persistence.baseDaoImpl.BaseDao" id="baseDao" ></jee:jndi-lookup>
    

    然后,您可以使用@Autowire 注解注入它或在您的 bean 中声明。

    <Bean class ="com.project.springBean" id ="myBean">
    <property name="baseDao" ref="baseDao" />
    or 
    @Component
    public class SpringBean {
    @AutoWired
    private BaseDao baseDao;
    public void setBaseDao(BaseDao baseDao) {
    this.baseDao =baseDao;
    

    } 如果你使用自动装配,你应该在你的 springBean 类中有 b​​aseDao 的 setter 方法。

    【讨论】:

      【解决方案4】:

      如果你简单地声明一个MyNoInterfaceEJB 类型的bean 应该没问题,使用任何你想要的方式。我是这样做的,在我的配置类中:

      @Bean public MyNoInterfaceEJB myEjb()
      {
        return new MyNoInterfaceEJB();
      }
      

      如果您删除了&lt;jee:local-slsb&gt; 定义,您应该会收到不同的错误消息,只需要MyNoInterfaceEJB 类型的bean。这就是你要做的。

      【讨论】:

      • 我很确定 EJB 永远不应该用 new 实例化。在这种情况下,如果您不想使用 @EJB 注释,可以使用 InitialContext 查找它。
      猜你喜欢
      • 2014-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-12
      • 2013-06-25
      • 2017-11-21
      • 1970-01-01
      相关资源
      最近更新 更多