EJB 3.1 Embeddable API + Junit 技術心得整理
在 Junit 中使用 Embedded GlassFish Server 做爲 EJB 元件的測試環境。The EJB 3.1 Embeddable API is designed for unit testing of EJB modules.
參考範例 Using the Embedded EJB Container to Test Enterprise Applications
設定
預設行爲
- Embedded EJB Container 會複製 Glassfish Domain 下的 domain.xml 做爲他的 Domain 設定.
- Embedded EJB Container 會在使用者目錄 下建立暫時的 domain, 例如: C:/Users/user/AppData/Local/Temp/domain6466380673056850xml。
啓動設定
Embedded EJB Container 啓動時,可進行設定以下的 Property [1]:
- Installation location: Embedded EBJ Container 的安裝位置,預設為 GlassFish Server 的位置。
- Instance location:Embedded EBJ Container instance 的安裝位置,依優先順序為: glassfish.embedded.tmpdir system property value, java.io.tmp system property value,as-install/domains/domain1
- configuration.file:使用的設定檔,預設為 domain-dir/config/domain.xml。
- Application Name:應用程式的名稱,會影響 EJB 元件的 JNDI 名稱。預設的 Application name 為 classes。類別的預設 JNDI 名稱為 jndi:global/classes/[you_class_name]。若 Application Name 設爲 App,則類別的預設名稱為 jndi:global/app/classes/[you_class_name]
as-install 是指 GlassFish Server 安裝的根目錄,内有 domains 及 lib 目錄。 domain-dir 是指 伺服器實體的根目錄,例如: C:\glassfish4\glassfish\domains
在 Log 檔的一開始會顯示 Embedded GlassFish Server 所使用的:installation location, configuration file. 也可以在 Log 檔中找到 EJB 元件的 JNDI 名稱。
Resources 的設定
- 若要測試 Entity Bean,需手動啓動資料庫。
- 和一般的 GlassFish Server 上的 Resources 設定相同。可使用 glassfish-resources.xml 來設定。或者,到 Glassfish 的 Admin Console 設定 jdbc resources。
- 若 Resources 未設定好,執行測試時會出現錯誤訊息:
Jun 09, 2017 1:54:22 PM org.glassfish.deployment.admin.DeployCommand execute SEVERE: Exception while preparing the app : Invalid resource : { ResourceInfo : (jndiName=java:app/jdbc/TicketClasspm), (applicationName=classes) } com.sun.appserv.connectors.internal.api.ConnectorRuntimeException: Invalid resource : { ResourceInfo : (jndiName=java:app/jdbc/TicketClasspm), (applicationName=classes) }
- 另外,若
persistence.xml
中的Data Source
欄位設定錯誤,也會出現上述的訊息。注意,Data Source
欄位上的名字不用加上java:app/
前置字串。
如果確認 Resource 的設定無誤,但執行測試時仍然出現上述錯誤,試著重新部署應用程式,看是否能解決問題。
測試 EJB
若要在 junit 中測試 EJB,我們無法在 embedded glassfish 中使用 CDI 的功能,所以必須手動取得 EJB 的 instance。所需的步驟如下:
- 取得
EJBContainer
物件 - 使用 lookup 方法取得 EJB 的實體
底下是在 junit 的 @BeforeClass
及 @AfterClass
的兩個方法下取得 EJB container 及 EJB 的實體:
@BeforeClass
public static void setUpClass() throws Exception {
// container is a static field for the test class
container = EJBContainer.createEJBContainer();
System.out.println("Opening the container");
ticketDataFacade = (TicketDataFacade) container.getContext().lookup("java:global/classes/TicketDataFacade");
receiverFacade = (ReceiverFacade) container.getContext().lookup("java:global/classes/ReceiverFacade");
ticketReserveTxnFacade = (TicketReserveTxnFacade) container.getContext().lookup("java:global/classes/TicketReserveTxnFacade");
ticketPickUpMethodFacade = (TicketPickUpMethodFacade) container.getContext().lookup("java:global/classes/TicketPickUpMethodFacade");
}
@AfterClass
public static void tearDownClass() {
container.close();
System.out.println("Closing the container");
}
測試 Entity
測試 Entity 時,主要的問題是取得 EntityManager
實體。若在 EJB 中已有使用 @PersistentContext
注入 EntityManager
實體,在取得 EJB 時 embedded GlassFish 會自動幫我們注入。
但如果 embedded GlassFish 無法爲我們自動注入時,就必須手動的產生 EntityManager
實體及執行 DML 所需要的 Transaction。
例子如下:
// #1 Get the entity manager by using the EntityManagerFactory
EntityManagerFactory factory Persistence.createEntityManagerFactoy("TicketCare-ProductionPU");
EntityManager em = factory.createEntityManager();
// Prepare the dml string
String del_str = "delete from TicketingEntity where t.ticket = :ticket";
// #2 Create a EntityTransaction
EntityTransaction emTxn = em.getTransaction();
// #3 Begin the transaction
emTxn.begin();
for (Ticket ticket: tickets){
em.createQuery(del_str).setParameter("ticket" ticket).executeUpdate();
}
// #4 commit to end the transaction
emTxn.commit();
// #5 close the EntityManager
em.close()
// #6 close the EntityManagerFactory
factory.close();
延伸閲讀
- Getting Started in Arquillian Guides, http://arquillian.org/guides/getting_started/.
- Michael Sikora, 2008. Chapter 5 The Java Persistence Query Language and Chapter 6 Entity Manager in EJB 3 Developer Guide, Packt publishing. (https://www.packtpub.com/application-development/ejb-3-developer-guide)
References
[1] Oracle, 2011, EJB 3.1 Embeddable API Properties in Oracle GlassFish Server 3.1 Embedded Server Guide. https://docs.oracle.com/cd/E18930_01/html/821-2424/gjlde.html. Accessed on 2017/06/10. [2] Oracle , 2013. GlassFish Server Open Source Edition Embedded Server Guide, Release 4.0. http://www.emse.fr/~lalevee/ismin/eb/documents/glassfish-docs/embedded-server-guide.pdf. Accessed on 2017/06/10