个人简介
我是红帽Hibernate团队的成员,主要负责 Hibernate OGM、Hibernate Validator 和 Hibernate Search。我还担任 JSR 349 专家组(Bean Validation)的成员。
在业余时间,我领导 MapStruct 项目,这是一个用于对象之间映射的代码生成器。
标签
作者
在测试Java EE应用程序时,我们有各种各样的工具和方法可供选择。根据特定测试的具体目标和要求,选项从单个类的简单单元测试到部署到容器(例如,通过Arquillian)的全面集成测试不等,这些测试可以通过如REST Assured等工具进行驱动。
在这篇文章中,我想讨论一种代表某种中间位置的测试方法:启动一个本地CDI容器和一个JPA运行时,与内存数据库连接。这样,你就可以在普通的Java SE环境下测试CDI Bean(例如,包含业务逻辑)与持久层(例如,基于JPA的存储库)的结合。
尽管Java 9在本周早些时候已经达到其生命周期的尽头,但Java平台模块系统(JPMS,JSR 376)仍然存在。这意味着像Java持久性API或Bean验证这样的规范也将最终需要调整,以支持并利用模块系统。
这篇博客文章是关于探索JPMS模块化规范API模式系列的第一篇。在本部分中,我们将探讨如何以可移植的方式启动规范API的实现,以及这些实现如何访问API用户的模块的私有状态。正如之前讨论的那样,后者是一个常见需求;例如,JPA提供者必须这样做以读取和写入实体状态。
Bean Validation 2.0(JSR 380)最显著的功能是支持容器元素约束。也就是说,你现在可以通过注解其类型参数(这得益于Java 8)来对容器类型(如List
、Map
或Optional
)的内容应用约束:List<@Future LocalDate> shipmentDates
。
在这篇博客文章中,你将了解如何利用这一点来验证自定义容器类型,例如来自Google广为人知的Guava库中的Multimap
、Table
或Graph
。
Java 9中最激动人心的特性之一是模块化运行时镜像。使用新的jlink实用程序,您可以创建包含您的应用程序、其依赖项以及它需要的仅有的JDK模块的自定义发行版。例如,一个基于Undertow网络服务器的简单服务可以打包成一个仅25MB的镜像,包括电池。
虽然这已经很酷了,但还有更酷的。因为jlink提供了一个插件机制,允许在创建模块化运行时镜像时对其进行微调。JDK附带了一系列jlink插件,例如用于压缩镜像内容或删除调试符号。但许多其他用例可能也会受益于这个API,例如,可以想象用于删除未使用代码或对JPA实体进行字节码插装的插件。在接下来的内容中,我们将创建一个插件,用于向创建的镜像添加注解索引。在运行时,可以使用这个索引非常高效地发现注解,也就是说,不加载类也不使用反射。
听起来很棒?当然,但有一个问题:截至Java 9,jlink插件API不是JDK的支持部分。实际上,其包甚至没有被从jdk.jlink
模块导出。这意味着需要一些技巧来创建自定义插件并使用这些插件启用jlink工具。API可能在未来的Java版本中发生变化,所以任何自定义插件都可能中断。
尽管如此,探索这个API并看看它能做什么绝对值得。我希望它最终会被提升为一个公共API。
毫无疑问,模块系统(JPMS)是Java 9最突出的特性。但还有许多其他有用的JDK添加功能,还没有被广泛讨论。
其中之一是新的ToolProvider
SPI,它定义了一种统一的方式来以程序方式调用JDK附带的所有工具(例如jar
、jlink
等)。例如,想象一下,您想在Java应用程序内创建JAR归档。在Java 9之前,您有两种方法来完成此操作
-
启动一个单独的进程来运行
jar
二进制文件 -
找出
jar
命令内部使用的哪些类,并直接调用它们
这两个选项都不理想。前者在分叉操作系统级别进程方面产生了开销,并且需要一些编码来定位Java家目录中要执行的二进制文件以及正确捕获分叉进程的任何输出。第二个选项没有分叉新进程的缺点,但它需要了解要执行的工具的实现。例如,对于jar
命令,您必须知道java.util.jar.JarOutputStream
用于生成JAR文件。
WildFly应用服务器自带一个补丁机制,这使得升级服务器现有模块或添加新模块变得非常简单。例如,Hibernate Validator提供了补丁文件,可以使您将WildFly 10.1升级到Bean Validation 2.0的预览版本。
但您还可以使用补丁机制将自定义库添加到WildFly中,使它们可供部署的应用程序使用。即使您只为一个WildFly实例部署单个应用程序,这也可以非常实用,因为它可以使您的部署单元(WAR等)的体积更小,从而加快构建和部署时间。
那么,WildFly补丁是如何创建的呢?补丁文件通常是包含要添加或更新的模块以及一些附加元数据的ZIP文件。因此,从理论上讲,您可以通过手动创建它们,但有一个patch-gen工具可以极大地简化这个任务。
以下我们将逐步描述如何使用patch-gen-maven-plugin创建WildFly补丁。作为一个例子,我们将生成一个补丁文件,将Eclipse Collections库添加到WildFly实例中。
以数据为中心的库通常需要访问库用户提供的类的私有状态。
例如,Hibernate ORM。当在实体的字段上给出@Id
注解时,Hibernate默认会直接访问字段(而不是调用属性获取器和设置器)来读取和写入实体的状态。
通常,这些字段是私有的。从外部代码访问它们从未是问题。Java反射API允许使私有成员可访问,并从其他类中随后访问它们。但是,随着Java 9模块系统的出现,这些规则将略有变化。
以下我们将探讨库的作者作为Java 9模块提供的库有哪种选项可以访问在其他模块中定义的类的私有状态。
Java 9 为库作者带来一个非常有用的新功能:多版本 JAR(JEP 238)。
多版本 JAR(MR JAR)可以包含相同类的一个或多个变体,每个变体针对特定的 Java 版本。在运行时,将根据所使用的 Java 版本自动加载类的正确变体。
这使得库作者可以在保持与旧版本兼容的同时,尽早利用新的 Java 版本。例如,如果你的库在变量上执行原子比较并设置操作,你目前可能正在使用 sun.misc.Unsafe
类。由于 Unsafe
从未打算用于 JDK 之外的用途,Java 9 提供了用于 CAS 逻辑的支持替代方案,即 var handles。通过将您的库作为 MR JAR 提供,您可以在 Java 9 上使用 var handles,同时当在旧平台上运行时坚持使用 Unsafe
。
以下我们将讨论如何使用 Apache Maven 创建 MR JAR。
如果你看过优秀的节目 "Home Improvement",你会知道一个 不懂装懂的人 仍然是个傻瓜。然而,同时,如果用对了工具,可以非常有效地解决复杂问题。
在这篇文章中,我想介绍一个名为 jQAssistant 的工具,我发现它在运行各种项目代码库分析时非常有用,例如,防止库的公共 API 中内部类型的泄漏。这是关于我们在为 Hibernate 家族的各个库工作期间所重视的开发者工具的博客系列的第一篇文章。