为什么WebSphere会创建重复的EJB环境条目?

时间:2015-09-04 06:15:24

标签: ejb websphere

我在EJB中使用@Resource注释指定了一个String资源。 EJB封装在EJB模块中。 ejb.jar有一个ejb-jar.xml,它指定String资源的默认值。 ejb.jar与web模块一起打包在ear存档中。

当将ear部署到WebSphere时,EJB模块的 Environment条目部分显示三个 EJB条目:

  1. 我为ejb模块映射的String资源;
  2. 我为ejb模块映射的String资源,只是这次被称为EJB_fully_qualified_name/resource_name;
  3. 资源的完全限定名称,但现在已为Web模块映射。
  4. 除非我为上述所有变体提供默认值,否则不会注入资源。如果我将ejb-jar.xml添加到Web模块,那么WebSphere将显示四个条目(每个模块一个简单名称和一个资源的完全限定名称)。这是一个WebSphere怪癖还是我做错了什么?我在集群环境中使用WebSphere 8.5.5.3。

    这是豆子:

    @Singleton
    @Startup
    public class ConfigSingleton { 
        @Resource
        private String serviceLookup;
    }
    

    这是ejb-jar.xml:

    <ejb-jar>
        <enterprise-beans>
                <session>
                    <ejb-name>ConfigSingleton</ejb-name>    
                    <env-entry>
                        <env-entry-name>serviceLookup</env-entry-name>
                        <env-entry-type>java.lang.String</env-entry-type>
                        <env-entry-value>value</env-entry-value>
                    </env-entry>                
                </session>
        </enterprise-beans>
    </ejb-jar>
    

2 个答案:

答案 0 :(得分:2)

您已经定义了2个完全不同的资源;要么被抬起头来。

根据Java EE规范,当您不使用@Resource注释的“name”属性时,会为您提供一个默认名称,即存在注释的完全限定类名,后跟JavaBeans属性名称(基本上是字段的名称,或者删除了'set'的方法的名称,以及小写的下一个字符)。 @Resource注释的javadoc有点误导,因为它只是说默认是字段名称;但没有明确说明字段名称是什么;它实际上是类名后跟字段名称,就像你打印出代表它的java.lang.reflect.Field一样。

当组合注释和XML时,XML仅在“name”匹配时覆盖注释。在提供的示例中,名称不匹配,因此您实际上有2个不同的资源。

如果您希望XML中的<env-entry>覆盖@Resource注释,以便您可以注入值,那么您需要更改注释,如下所示:

@Resource(name="serviceLookup")

或者将<env-entry-name>更改为完全限定的类名/ serviceLookup。

此外,当EJB模块包含在WAR模块中时,事情会变得复杂一些。不是“名称”方面,而是您可以提供价值的地方。除了在ejb-jar.xml中提供值之外,WebSphere还允许您在ibm-ejb-jar-bnd.xml中提供值。但是,当EJB模块在WAR中时,它也可能在ibm-web-bnd.xml中提供...因为所有EJB的所有资源都在java:comp/env名称空间中可见WAR模块。因此,在示例中,由于默认值,您将获得两个不同的名称,并且看起来是另外两个副本,这些副本实际上只是在您要覆盖ibm-web-bnd.xml中的值时提供。

答案 1 :(得分:0)

我认为您在这里看到的是不同的JNDI名称空间:

https://docs.oracle.com/cd/E19798-01/821-1841/girgn/index.html

可以使用原始名称从EJB模块中访问资源值,但是如果需要从同一应用程序中的另一个模块访问它,则应该提供由模块名称限定的JNDI路径,以确保唯一性(其他应用程序和全局命名空间等等。可追溯性)。