2012-08-31 15 views
1

爲了開發目的,我在單例bean中實現了一個虛擬數據存儲庫。單例bean的構造函數創建虛擬數據,並且有方法來檢索,插入,更新和刪除虛擬數據。Singleton EJB應該表現出與EJB容器相同的外部容器,但不是

當我單元測試它時,檢查插入和更新的對象是否可以在插入和更新的狀態(即屬性相等)中檢索,單元測試通過。在這個測試中,我只是將singleton bean實例化爲常規對象,即通過它的構造函數。當我實際使用單身bean時,通過將其注入到一個@RequestScoped JSF輔助bean(將bean創建留給EJB容器)中,在更新數據項並隨後通過它的ID檢索它之後,更新似乎丟失了,舊字段值被使用。所以這個bean在進出容器中的行爲不一樣。然而,在構造函數中有一個System.out.println只能執行一次,所以在這個意義上它似乎只實例化一次。

的單豆的結構是這樣的:

@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被聲明爲單例。但是在容器中它似乎充當無狀態會話bean。

我正在使用GlassFish 3.1.2.2。

更新: 我改變了豆從@javax.ejb.Singleton@javax.enterprise.context.ApplicationScoped(凡通過@javax.inject.Inject,而不是@javax.ejb.EJB需要注入的話),現在按預期工作。但兩者之間應該沒有區別。它認爲,雖然單例EJB只被實例化了一次,但它以某種方式恢復了它在方法調用之間的狀態。

回答

1

單身bean中的公共方法不應聲明爲final。我已經將它們聲明爲final,因爲我從構造函數中調用它們來使用初始的啞元數據集填充集合。如果沒有聲明爲final,那麼NetBeans會正確警告從基類構造方法中調用可以在子類中重寫的方法。當沒有聲明爲final時,我只是簡單地通過從構造函數中調用單例bean的公共方法來獲得NullPointerException。所以必須有一些非終極方法的代理。

我仍然不確定爲什麼它出現好像最終方法的結果被緩存(即得到陳舊的結果)。但我有我的答案,所以我對此感到滿意。

+1

那麼它的會話bean和參與交易模型,所以必須有一個代理。否則,它將是一個簡單的POJO。 – atamanroman

+0

謝謝@atamanroman。人們會希望GlassFish拒絕部署它,就像'@ ApplicationScoped' bean的情況一樣。 –