同時,我轉到了Arquillian 。 去年我仔細查看了Arquillian 1.0.0.Alpha4之后,是時候看看這些家伙為1.0.0決賽準備了什么。 有些東西有些變化,我很驚訝只在網上找到一些基本的例子。 這就是我開始寫這篇文章的主要原因。 要獲得所有這三種技術一起工作的更完整示例。
入門
首先,獲取最新的NetBeans 7.1的新副本。 幾周后就出來了,看起來真的很好。 如果愿意,您可以下載Java EE版本的副本,該副本隨附最新的GlassFish OSS Edition 3.1.1。 安裝并啟動它。 還要grep MySQL Community Edition的副本并安裝它。 返回NetBeans,通過新的項目向導設置新的Maven Web應用程序。 我們將其稱為“ simpleweb”,并告訴它在GF 3.1.1上運行(如果尚未運行,則應在服務創建之前創建Services> Server> GlassFish實例,或者在項目設置過程中創建它)。
實施您的應用程序
即使這不是測試驅動的,我還是喜歡使用這種方法,因為我仍然相信,這是您在項目中發現的最常見的情況。 您已經準備好運行很多東西,并且正在尋找某種自動集成測試。 因此,假設您有一個非常基本的實體,我們將其稱為“ com.mycompany.simpleweb.entities.AuditLog”。 您可以使用NetBeans新實體向導創建它。 實體創建過程中的第三步是提供程序和數據庫設置。 定義一個新的數據源,并將其命名為“ jdbc / auditlog”。 作為連接規范,請使用MySQL J驅動程序,并且我假設您已經啟動了數據庫并正在運行(假設這稱為Auditlog)。 測試連接并完成向導。

如果您使用向導,則將獲得一些免費禮物。 除了事實,您現在在源代碼樹中有AuditLog實體,您還可以在src / main / resources中找到一個META-INF / persistence.xml文件,并在src / main / setup中找到一個glassfish-resources.xml。 稍后需要這樣做,請記住這一點。 向您的實體添加一些其他屬性。 現在,我添加“字符串帳戶”。 并且不要忘記定義一個Version字段“ Timestamp timestamp”。 還有一點點命名查詢來獲取所有AuditLogs的列表也是很好的
@NamedQuery(name = "findAllAuditLogs",
query = "SELECT OBJECT (e) FROM AuditLog e")@Version
private Timestamp timestamp;
如果使用向導,請確保檢查pom.xml。 該向導會在提供的范圍內添加一些eclipselink依賴關系,因此在這里應該不會有太大的不同。 接下來是添加com.mycompany.simpleweb.service.AuditRepositoryService EJB。 這應該負責AuditLog實體上的所有CRUD操作。
向其中添加一些代碼以插入AuditLog:
@PersistenceContext
private EntityManager em;public void writeLog(String account) {AuditLog log = new AuditLog();log.setAccount(account);em.persist(log);}
還有更多代碼來查找表中的條目總數:
public int findAll() {TypedQuery<AuditLog> query = em.createNamedQuery("AuditLog.findAllAuditLogs", AuditLog.class);return query.getResultList().size();}
目前為止就這樣了。
添加基本??測試依賴項
接下來,我們將添加一些非常基本的測試依賴項。 打開您的項目pom.xml文件,然后將Arquillian的以下部分添加到您的項目中:
<repository><id>JBoss</id><name>JBoss Repository</name><url>https://repository.jboss.org/nexus/content/groups/public/</url></repository>
<dependencymanagement> <dependencies><dependency><groupid>org.jboss.arquillian</groupid><artifactid>arquillian-bom</artifactid><version>1.0.0.Final-SNAPSHOT</version><scope>import</scope><type>pom</type></dependency></dependencies>
</dependencymanagement>
<dependencies><dependency><groupid>org.jboss.arquillian.container</groupid><artifactid>arquillian-glassfish-embedded-3.1</artifactid><version>1.0.0.Final-SNAPSHOT</version><scope>test</scope></dependency><dependency><groupid>org.jboss.arquillian.junit</groupid><artifactid>arquillian-junit-container</artifactid><scope>test</scope></dependency>
</dependencies>
除此之外,您還需要嵌入的Glassfish依賴項。
<dependency><groupid>org.glassfish.extras</groupid><artifactid>glassfish-embedded-all</artifactid><version>3.1</version><scope>test</scope>
</dependency>
我們還需要MySQL J驅動程序:
<dependency><groupid>mysql</groupid><artifactid>mysql-connector-java</artifactid><version>5.1.18</version><scope>test</scope>
</dependency>
配置Arquillian
在所有必要的依賴關系就緒之后,我們需要進一步配置Arquillian。 這是通過arquillian.xml完成??的,該文件必須放在src / test / resources文件夾中(您可能之前需要在NetBeans外部創建它),并且應如下所示:
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian-1.0.xsd"><engine><property name="deploymentExportPath">target/arquillian</property></engine><container default="true" qualifier="glassfish"><configuration><property name="sunResourcesXml">src/main/setup/glassfish-resources.xml</property> </configuration></container>
</arquillian>
engine參數告訴Arquillian將測試存檔的打包版本放置到target / arquillian文件夾中。 這對于解決問題非常有用。 容器限定符將測試運行程序指向由實體創建向導創建的glassfish-resources.xml。 全做完了。 我想建議的一件事是制作persistence.xml的副本,并將其放置到重命名為test-persistence.xml之類的test / resources文件夾中。 我認為最好的選擇是配置測試JPA與生產性JPA有所不同。 作為一個簡單的例子,我們希望在測試期間看到更多日志記錄輸出,因此復制的版本還應包含所需的參數。 我還想將用于測試的表生成策略更改為拖放表:
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.logging.level.sql" value="FINEST" />
<property name="eclipselink.logging.parameters" value="true" />
讓我們看一下測試。
添加一個測試用例
讓我們添加一個測試。 對于NetBeans,這很容易:右鍵單擊EJB,然后選擇“工具>創建JUnit測試”。 選擇JUnit 4.x,并接受名稱建議“ com.mycompany.simpleweb.service.AuditRepositoryServiceTest”。 現在,您的項目有了一個新的“ Test Packages”文件夾。 如您所見,測試是錯誤的。 NetBeans假定您要基于嵌入式EJBContainer進行測試。 不錯的猜測,但我們想在此處添加一些Arquillian。 刪除EJBContainer導入并將類剝離為此:
@RunWith(Arquillian.class)
public class AuditRepositoryServiceTest {
}
現在是時候使用ShrinkWrap定義測試的部署檔案了。 測試的部署存檔是使用帶有Arquillian的@Deployment批注的靜態方法定義的。
@Deploymentpublic static JavaArchive createTestArchive() {return ShrinkWrap.create(JavaArchive.class, "test.jar").addPackage(AuditLog.class.getPackage()).addPackage(AuditRepositoryService.class.getPackage()).addAsManifestResource(new ByteArrayAsset("<beans>".getBytes()),ArchivePaths.create("beans.xml")).addAsManifestResource("test-persistence.xml",ArchivePaths.create("persistence.xml"));}
在添加了應包含的軟件包之后,添加了一個空的beans.xml(現在應該足夠了),并添加了test-persistence.xml作為名為persistence.xml的清單資源。 大。 最后一件事是定義測試本身。
@EJB
AuditRepositoryService repository;@Testpublic void insertLog() throws Exception {repository.writeLog("Markus");int numberOfLogs = repository.findAll();Assert.assertEquals(1, numberOfLogs);}
我們正在插入一個簡單的測試實體,并從數據庫中返回計數,該計數通過assertEquals檢查。 就這樣。 啟動您的測試。 (右鍵單擊AuditRepositoryServiceTest類,然后選擇“測試文件(Strg + F6)。
檢查發生了什么
輸出窗口顯示起始GlassFish的Std.out。 如果進一步檢查輸出,將會看到JDBC連接池和JDBC資源已創建: INFO:命令添加資源結果:PlainTextActionReporterSUCCESS描述:添加資源AdminCommandnull JDBC連接池mysql_auditlog_rootPool創建成功。 JDBC資源jdbc / auditlog已成功創建。 并部署了“測試”應用程序: 信息:WEB0671:在[/ test]處加載應用程序[test] 17.01.2012 10:12:39 org.glassfish.deployment.admin.DeployCommand執行 INFO:測試成功部署了6.461毫秒。
掃描輸出確實會指向一些EclipseLink東西,但是附加的SQL日志記錄似乎無效。 這是因為EclipseLink需要知道將輸出指向哪個記錄器。 通常,日志輸出將重定向到自動發現的服務器記錄器。 到目前為止,我們沒有進行任何日志記錄配置,僅依賴于Java Logging的默認值。 因此,讓我們添加一些日志記錄配置。 將一個空的logging.properties文件放入src / test / resources并向其中添加一些簡單的行:
handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.ConsoleHandler.level =完成 將maven sure-fire插件添加到pom.xml的build部分:
<plugin><groupid>org.apache.maven.plugins</groupid><artifactid>maven-surefire-plugin</artifactid><version>2.11</version><configuration><includes><include>com/mycompany/simpleweb/service/*</include></includes><systempropertyvariables><java.util.logging.config.file>${basedir}/src/test/resources/logging.properties</java.util.logging.config.file></systempropertyvariables></configuration></plugin>
如果現在執行清理和構建,則會看到所需的日志輸出顯示在NetBeans構建輸出中。
有限:插入音頻日志(ID,帳戶,時間戳)值(?,?,?)
綁定=> [1,馬庫斯,2012-01-17 11:02:54.0] 實際上,如果您使用Strg + F6,您仍然只會看到INFO級別的消息。 要解決此問題,您需要更改NetBeans運行操作設置。 右鍵單擊您的項目,然后選擇“屬性”。 選擇“操作”和“測試文件”。 將以下內容作為新行添加到“設置屬性”區域中:
java.util.logging.config.file = src / test / resources / logging.properties

現在,您還可以通過一次測試運行看到所需的日志級別輸出。 就是這樣 您可以下載完整的示例maven項目(作為ZIP文件) ,并帶有提到的類,并進行一些操作。 玩得開心!
即使上面的帖子旨在成為一個更復雜的演示,事實證明,我還是錯過了設置方面的一個大問題。 當您開始向實體中引入增強功能時,一切工作都很好。 僅舉幾例:延遲加載,更改跟蹤,獲取組等。 JPA提供者喜歡將此稱為“增強”,并且通常將其稱為“編織”。 編織是一種操作已編譯Java類的字節碼的技術。 EclipseLink JPA持久性提供程序使用編織來增強提到的內容的JPA實體并進行內部優化。 編織既可以在運行時加載實體時動態執行,也可以在編譯時通過對Entity .class文件進行后處理來靜態執行。 通常建議使用動態編織,因為它易于配置并且不需要對項目的構建過程進行任何更改。 您可能已經看到了EclipseLink的一些更好的日志輸出,如下所示:
[…] –開始weaver類轉換器處理類[com / mycompany / simpleweb / entities / AuditLog]。
[…] –持久化(PersistenceEntity)[com / mycompany / simpleweb / entities / AuditLog]。
[…] –編織變更跟蹤(ChangeTracker)[com / mycompany / simpleweb / entities / AuditLog]。 […] –編織懶惰(間接使用ValueHolder)[com / mycompany / simpleweb / entities / AuditLog]。 […] –編織提取組(FetchGroupTracker)[com / mycompany / simpleweb / entities / AuditLog]。 […] –結束weaver類轉換器處理類[com / mycompany / simpleweb / entities / AuditLog]。
Arquillian和嵌入式GlassFish的問題
想象一下,您以昨天博客中的示例為例,將簡單的String account屬性更改為如下所示:
@ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)private Person person;
這正是上述情況之一,您的JPA提供程序需要在執行之前對類文件進行一些增強。 如果不修改項目,將導致一些非常討厭的異常:
異常描述:訪問不存在的編織_vh_方法[_persistence_get_person_vh]時將發生NullPointerException。 未正確編織該類–對于EE部署,請檢查application.xml部署描述符中的模塊順序,并驗證包含持久性單元的模塊是否在使用該持久性單元的任何其他模塊之前。
[…]
內部異常:java.lang.NoSuchMethodException:com.mycompany.simpleweb.entities.AuditLog._persistence_get_person_vh() 映射:org.eclipse.persistence.mappings.ManyToOneMapping [person] 描述符:RelationalDescriptor(com.mycompany.simpleweb.entities.AuditLog –> [DatabaseTable(AUDITLOG)]) 在org.eclipse.persistence.exceptions.DescriptorException.noSuchMethodWhileInitializingAttributesInMethodAccessor(DescriptorException.java:1170) 在org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor.initializeAttributes(MethodAttributeAccessor.java:200) […]
表示缺少某些內容。 而這種缺失的方法是由編織過程引入的。 如果您反編譯編織的實體,則可以看到JPA提供程序在抱怨什么。 這是增強型實體類的外觀。 這只是編織過程引入到您的代碼中的增強方法之一。
public WeavedAttributeValueHolderInterface _persistence_get_person_vh(){_persistence_initialize_person_vh();if(_persistence_person_vh.isCoordinatedWithProperty() || _persistence_person_vh.isNewlyWeavedValueHolder()){Person person1 = _persistence_get_person();if(person1 != _persistence_person_vh.getValue())_persistence_set_person(person1);}return _persistence_person_vh;}
動態與靜態編織
顯然,默認的動態編織不適用于上述設置。 為什么? 編織是一個被寵壞的孩子。 僅當要編織的實體類僅存在于應用程序類加載器中時,它才起作用。 嵌入式GlassFish,Arquillian和maven sure-fire-plugin的結合使這一點有點混亂,故事的結尾是,您的實體完全沒有任何增強。 比較這個不錯的討論以獲得更詳細的解釋。 如果動態波動不起作用,我們必須使用稱為靜態編織的后備。 靜態意味著:在構建過程中對實體進行后處理。 有了Maven項目,這聽起來很容易。 讓我們尋找這樣的東西。 您可能會發現的第一件事是StaticWeaveAntTask 。 第二件事可能是Craig的eclipselink-staticweave-maven-plugin 。
讓我們從StaticWeaveAntTask開始。 您將必須使用maven-antrunner-plugin進行介紹。 從左到右復制課程,并進行大量的爭吵以使您的課程路徑牢牢掌握。 Laird Nelson在為所有3個大型JPA提供程序(EclipseLink,OpenJPA,Hibernate)提供示例配置原型方面做得很出色,您可以嘗試一下。 有關正在發生的事情的詳細說明可以在他的博客中找到 。 謝謝萊爾德的指點! 不要誤會我的意思:這是一種有效的方法,但是我根本不喜歡它。 主要是因為它給構建帶來了巨大的復雜性,并且看到了太多的項目,甚至沒有管理正常Maven項目所需的技能,這對我來說根本不是解決方案。 我嘗試了Craig Day完成的靜態編織插件。
向simpleweb添加靜態編織
因此,讓我們從昨天的項目中打開pom.xml并引入新的插件:
<plugin><artifactId>eclipselink-staticweave-maven-plugin</artifactId><groupId>au.com.alderaan</groupId><version>1.0.1</version><executions><execution><goals><goal>weave</goal></goals><phase>process-classes</phase></execution></executions></plugin>
做完了 現在,您的類已經編好了,如果您通過插件配置引入一些日志記錄,您實際上可以看到,實體類會發生什么。 該插件可通過repo1.maven.org獲得。 我遇到的唯一問題是,對EclipseLink 2.2.0的引入依賴關系(或當然)不能通過相同的存儲庫獲得,因此您可能需要使用正確的存儲庫和依賴關系為自己構建它。 您可以通過插件的Google代碼頁獲取源代碼。
不要忘記將編織屬性添加到您的test-persistance.xml中:
<property name="eclipselink.weaving" value="static" />
[更新:2012年1月19日]
Craig發布了該插件的新1.0.2版本,該版本解決了EclipseLink依賴項的問題。 現在,您可以簡單地包括所需的EclipseLink版本作為插件的依賴項。 還需要正確的EclipseLink Maven存儲庫。 具有配置的日志級別的完整示例如下所示:
<repository><id>eclipselink</id><name>Repository hosting the eclipselink artifacts</name><url>http://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo/</url></repository>[...]<plugin><artifactId>eclipselink-staticweave-maven-plugin</artifactId><groupId>au.com.alderaan</groupId><version>1.0.2</version><executions><execution><goals><goal>weave</goal></goals><phase>process-classes</phase><configuration><logLevel>ALL</logLevel></configuration></execution></executions><dependencies><dependency><groupId>org.eclipse.persistence</groupId><artifactId>eclipselink</artifactId><version>2.3.1</version></dependency></dependencies></plugin>
參考: 具有NetBeans,嵌入式GlassFish,JPA和MySQL數據源的 Arquillian 和具有NetBeans,GlassFish嵌入式,JPA和MySQL數據源的 Arquillian –來自我們JCG合作伙伴 Markus Eisele在企業軟件開發和Java博客上的第二部分。
翻譯自: https://www.javacodegeeks.com/2012/01/arquillian-with-netbeans-glassfish.html