Singleton EJB应该在EJB容器外部表现相同但不行

时间:2012-08-31 01:58:58

标签: java glassfish-3 cdi ejb-3.1

为了开发目的,我在单例bean中实现了一个虚拟数据存储库。单例bean的构造函数创建虚拟数据,并且有检索,插入,更新和删除虚拟数据的方法。

当我对它进行单元测试时,检查插入和更新的对象是否可以在插入和更新的相同状态下检索(即逐个属性),单元测试通过。在这个测试中,我只是将单例bean实例化为常规对象,即通过其构造函数。当我实际使用单例bean时,将它注入@RequestScoped JSF支持bean(将bean创建留给EJB容器),在更新数据项并随后通过其ID检索它之后,更新似乎丢失了并使用旧的字段值。因此,bean在容器内外的行为不同。然而,构造函数中有一个System.out.println只执行一次,所以在这种意义上它似乎只实例化了一次。

单例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.
        // ...
    }
}

似乎没有任何理由认为bean应该在EJB容器内外产生不同的结果。它不使用任何外部资源。同步是bean管理的(因此在这方面应该是相同的)。 bean被声明为singleton。但是在容器中,它似乎充当了无状态会话bean。

我正在使用GlassFish 3.1.2.2。

更新 我将bean从@javax.ejb.Singleton更改为@javax.enterprise.context.ApplicationScoped(并在必要时通过@javax.inject.Inject而不是@javax.ejb.EJB注入),现在它按预期工作。但两者之间应该没有区别。虽然单例EJB只被实例化一次,但它会以某种方式在方法调用之间恢复其状态。

1 个答案:

答案 0 :(得分:1)

单例bean中的公共方法不应声明为final。我已将它们声明为final,因为我是从构造函数中调用它们来使用初始虚拟数据集填充集合。当未被声明为final时,NetBeans正确地警告过从基类构造函数中调用可以在子类中重写的方法。当没有声明为final时,我只是通过从构造函数中调用singleton bean自己的公共方法来获得NullPointerException。因此,非最终方法必须存在某种代理。

我仍然不确定为什么出现,好像最终方法的结果被缓存(即获得陈旧的结果)。但我有我的答案,所以我很开心。