简体   繁体   English

Singleton EJB在外部EJB容器中的行为应相同,但不应

[英]Singleton EJB should behave the same outside EJB container but doesn't

I have implemented a dummy data repository in a singleton bean for development purposes. 我出于开发目的在单例bean中实现了虚拟数据存储库。 The singleton bean's constructor creates dummy data and there are methods to retrieve, insert, update and delete dummy data. 单例bean的构造函数创建伪数据,并且有一些方法可以检索,插入,更新和删除伪数据。

When I unit test it, checking that objects being inserted and updated can be retrieved in the same state they were inserted and updated (ie property-by-property equality), the unit test passes. 当我对它进行单元测试时,检查插入和更新的对象是否可以在插入和更新的相同状态下(即,逐个属性相等)进行检索,单元测试通过。 In this test, I just instantiate the singleton bean as a regular object, ie via its constructor. 在此测试中,我只是将单例bean实例化为常规对象,即通过其构造函数。 When I actually use the singleton bean by injecting it into a @RequestScoped JSF backing bean (which leaves bean creation to the EJB container), after updating a data item and subsequently retrieving it by its ID, the update seems to be lost and the old field values are used. 当我通过将单例bean注入到@RequestScoped JSF支持bean(将bean创建留给EJB容器)中来实际使用它时,在更新数据项并随后通过其ID检索它之后,更新似乎丢失了,并且旧的使用字段值。 So the bean doesn't behave the same in and out of the container. 因此,bean在容器内外的行为都不相同。 And yet, there is a System.out.println in the constructor that is only executed once, so in that sense it appears to instantiate only once. 但是,构造函数中有一个System.out.println仅执行一次,因此从这种意义上讲,它似乎只实例化一次。

The singleton bean is structured like this: 单例bean的结构如下:

@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
@Singleton
@LocalBean
public class DummyDataRepository {
    public DummyDataRepository() {
        // Initial dummy data created here.
    }

    public final synchronized Foo findFooById(int id) {
        // Retreive a Foo by ID.
        // ...
    }

    public final synchronized void addFoo(Foo foo) {
        // Add the Foo.
        // ...
    }

    public final synchronized void updateFoo(Foo foo) {
        // Find the existing Foo by foo.id and replace it with foo.
        // ...
    }

    public final synchronized void deleteFoo(int id) {
        // Find the existing Foo by id and delete it.
        // ...
    }
}

There doesn't appear to be any reason that the bean should produce different results in and out of the EJB container. 似乎没有任何理由使Bean在EJB容器内外产生不同的结果。 It doesn't use any external resources. 它不使用任何外部资源。 Synchronization is bean managed (so should be the same in that regard). 同步是由Bean管理的(因此在这方面应该相同)。 The bean is declared as singleton. 该bean被声明为单例。 But in the container it appears to be acting as a stateless session bean. 但是在容器中,它似乎充当了无状态会话bean。

I'm using GlassFish 3.1.2.2. 我正在使用GlassFish 3.1.2.2。

Update: I changed the bean from @javax.ejb.Singleton to @javax.enterprise.context.ApplicationScoped (and inject it where required via @javax.inject.Inject instead of @javax.ejb.EJB ) and it now works as expected. 更新:我将bean从@javax.ejb.Singleton更改为@javax.enterprise.context.ApplicationScoped (并通过@javax.inject.Inject而不是@javax.ejb.EJB注入到需要的位置),现在它可以正常工作了。 Yet there should be no difference between the two. 但这两者之间应该没有区别。 It seams that, although the singleton EJB is being instantiated only once, it somehow reverts its state between method invocations. 它表明,尽管单例EJB仅被实例化一次,但它在某种程度上在方法调用之间恢复了其状态。

Public methods in a singleton bean should not be declared as final . 单例bean中的公共方法不应声明为final I had declared them as final because I was calling them from the constructor to populate collections with the initial dummy dataset. 我之所以将它们声明为final是因为我从构造函数中调用了它们,以使用初始的虚拟数据集填充集合。 When not declared as final, NetBeans correctly warned about calling methods from a base class constructor that could be overridden in a subclass. 如果未声明为final,则NetBeans会正确警告有关从基类构造函数调用方法的信息,这些方法可能会在子类中被覆盖。 When not declared as final, I was getting a NullPointerException simply by calling the singleton bean's own public method from the constructor. 当未声明为final时,仅通过从构造函数调用单例bean自己的公共方法就得到了NullPointerException So there must be some kind of proxying that occurs for non-final methods. 因此,对于非最终方法必须存在某种代理。

I'm still not sure why it appears as though results of final methods are cached (ie getting stale results). 我仍然不确定为什么看起来好像最终方法的结果被缓存了(即得到陈旧的结果)。 But I have my answer, so I'm happy enough with that. 但是我有我的答案,所以我对此感到很满意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM