JPersist is a suite of modern, high-performance, and Gradle Configuration Cache-compliant plugins that automate the configuration of enterprise Jakarta Persistence API (JPA) environments. It provides zero-configuration support for Hibernate and EclipseLink multi-module builds.
1. Getting Started
This section covers the requirements and basic setup to start using JPersist plugins in your Gradle project.
1.1. Requirements
-
Gradle: 7.4+ or 8.x+ / 9.x+
-
Java: JDK 17 or higher (required by modern Jakarta specifications)
1.2. Choosing a Plugin
JPersist provides three main plugins depending on your JPA provider:
| Plugin ID | Description | Provider |
|---|---|---|
|
Generates or merges |
Provider-agnostic |
|
Descriptor generation, metamodel generation, and bytecode enhancement |
Hibernate |
|
Descriptor generation, metamodel generation, and static weaving |
EclipseLink |
The provider-specific plugins (hibernate-persistence and eclipse-persistence) automatically apply the io.github.jpersist.jpa plugin, so you only need to apply one.
|
1.3. Applying the Plugin
1.3.1. Hibernate example
plugins {
id 'io.github.jpersist.hibernate-persistence' version '1.5.0'
}
plugins {
id("io.github.jpersist.hibernate-persistence") version "1.5.0"
}
1.3.2. EclipseLink example
plugins {
id 'io.github.jpersist.eclipse-persistence' version '1.5.0'
}
plugins {
id("io.github.jpersist.eclipse-persistence") version "1.5.0"
}
1.4. Adding Dependencies
Use the jpa configuration to declare your JPA provider platform BOM. This centralizes version management across all compilation scopes.
1.4.1. Hibernate example
dependencies {
jpa platform('org.hibernate.orm:hibernate-platform:6.6.56.Final')
implementation 'org.hibernate.orm:hibernate-core'
}
dependencies {
jpa(platform("org.hibernate.orm:hibernate-platform:6.6.56.Final"))
implementation("org.hibernate.orm:hibernate-core")
}
1.4.2. EclipseLink example
dependencies {
jpa platform('org.eclipse.persistence:org.eclipse.persistence.parent:4.0.9')
compileOnly 'jakarta.persistence:jakarta.persistence-api'
implementation 'org.eclipse.persistence:org.eclipse.persistence.core'
}
dependencies {
jpa(platform("org.eclipse.persistence:org.eclipse.persistence.parent:4.0.9"))
compileOnly("jakarta.persistence:jakarta.persistence-api")
implementation("org.eclipse.persistence:org.eclipse.persistence.core")
}
That’s it — no additional XML configuration or annotation processing setup is required.
The plugin automatically detects your entity classes and generates the appropriate persistence.xml at build time.
2. Jakarta Persistence Plugin
Plugin ID: io.github.jpersist.jpa
The io.github.jpersist.jpa plugin is the core implementation of the JPersist plugin suite and facilitates the integration of provider platform plugins such as EclipseLink and Hibernate.
It automatically applies the java plugin, registers a persistence DSL extension, and creates per-source-set tasks for descriptor generation, schema validation, and GraalVM native image metadata generation.
2.1. Applying the Plugin
plugins {
id 'io.github.jpersist.jpa' version '1.5.0'
}
plugins {
id("io.github.jpersist.jpa") version "1.5.0"
}
2.2. The jpa Configuration
The plugin registers a jpa dependency configuration that propagates platform/BOM version constraints into all standard Java configurations (implementation, compileOnly, annotationProcessor, runtimeOnly).
When the java-library plugin is also applied, the api and compileOnlyApi configurations are extended as well.
dependencies {
jpa platform('org.hibernate.orm:hibernate-platform:6.6.56.Final')
implementation 'org.hibernate.orm:hibernate-core'
}
dependencies {
jpa(platform("org.hibernate.orm:hibernate-platform:6.6.56.Final"))
implementation("org.hibernate.orm:hibernate-core")
}
2.3. DSL Extension: persistence
The persistence block is a NamedDomainObjectContainer scoped per Java source set.
The plugin automatically creates one entry per source set (e.g. main, test).
persistence {
main {
version = '3.0'
persistenceUnits {
'my-unit' {
provider = 'org.hibernate.jpa.HibernatePersistenceProvider'
transactionType = 'RESOURCE_LOCAL'
properties {
property 'hibernate.show_sql', 'true'
}
}
}
validation {
url = 'jdbc:h2:mem:my_db;DB_CLOSE_DELAY=-1'
}
transformer {
outputProperty 'indent', 'yes'
outputProperty '{http://xml.apache.org/xslt}indent-amount', '2'
}
}
}
persistence {
create("main") {
version.set("3.0")
persistenceUnits {
create("my-unit") {
provider.set("org.hibernate.jpa.HibernatePersistenceProvider")
transactionType.set("RESOURCE_LOCAL")
properties.put("hibernate.show_sql", "true")
}
}
validation {
url.set("jdbc:h2:mem:my_db;DB_CLOSE_DELAY=-1")
}
outputProperties.put("indent", "yes")
outputProperties.put("{http://xml.apache.org/xslt}indent-amount", "2")
}
}
2.3.1. PersistenceExtension Properties
| Property | Type | Default | Description |
|---|---|---|---|
|
|
|
JPA specification version written into the root |
|
|
auto-populated |
Named container of persistence unit definitions. Each entry maps to a |
|
|
see below |
Nested database connection configuration for the schema validation task. |
|
|
see below |
Key-value pairs passed to the XML |
Default Output Properties
-
indent=yes -
omit-xml-declaration=no -
encoding=UTF-8 -
\{http://xml.apache.org/xslt}indent-amount=4
These can be customized via the transformer block (Groovy) or by setting entries directly on outputProperties (Kotlin):
persistence {
main {
transformer {
outputProperty 'indent', 'yes'
outputProperty '{http://xml.apache.org/xslt}indent-amount', '2'
}
}
}
persistence {
create("main") {
outputProperties.put("indent", "yes")
outputProperties.put("{http://xml.apache.org/xslt}indent-amount", "2")
}
}
2.3.2. PersistenceUnitExtension Properties
| Property | Type | Default | Description |
|---|---|---|---|
|
|
(container key) |
Read-only. The persistence-unit name used as the |
|
|
|
When set to |
|
|
|
The JPA transaction type ( |
|
|
none |
An optional human-readable description for the persistence unit. |
|
|
none |
Fully qualified class name of the JPA persistence provider (e.g. |
|
|
none |
The JNDI name of the data source for this persistence unit. |
|
|
none |
Whether the data source is JTA-managed. When |
|
|
empty |
A list of ORM mapping file paths to include in the persistence unit. |
|
|
empty |
Custom jar-file element layout translations. Key: project path or |
|
|
|
Whether unlisted entity classes should be excluded from the persistence unit. |
|
|
|
Whether all discovered entity classes should be included automatically. |
|
|
none |
The shared (second-level) cache mode. When present, emitted as a |
|
|
none |
The Bean Validation mode ( |
|
|
empty |
Vendor-specific JPA properties included in the |
Example with multiple properties:
persistence {
main {
persistenceUnits {
'my-unit' {
provider = 'org.hibernate.jpa.HibernatePersistenceProvider'
transactionType = 'RESOURCE_LOCAL'
sharedCacheMode = 'ENABLE_SELECTIVE'
validationMode = 'AUTO'
properties {
property 'hibernate.show_sql', 'true'
property 'hibernate.format_sql', 'true'
}
}
}
}
}
persistence {
create("main") {
persistenceUnits {
create("my-unit") {
provider.set("org.hibernate.jpa.HibernatePersistenceProvider")
transactionType.set("RESOURCE_LOCAL")
sharedCacheMode.set("ENABLE_SELECTIVE")
validationMode.set("AUTO")
properties.put("hibernate.show_sql", "true")
properties.put("hibernate.format_sql", "true")
}
}
}
}
2.3.3. ValidationExtension Properties
| Property | Type | Default | Description |
|---|---|---|---|
|
|
|
The JDBC connection URL used for schema validation. |
|
|
|
The fully qualified JDBC driver class name. |
|
|
|
The database user name. |
|
|
|
The database password. |
persistence {
main {
validation {
url = 'jdbc:h2:mem:my_validation_db;DB_CLOSE_DELAY=-1'
driver = 'org.h2.Driver'
user = 'sa'
password = ''
}
}
}
persistence {
create("main") {
validation {
url.set("jdbc:h2:mem:my_validation_db;DB_CLOSE_DELAY=-1")
driver.set("org.h2.Driver")
user.set("sa")
password.set("")
}
}
}
2.4. Dependency Routing with jarFile
For multi-module projects, the plugin registers a jarFile dependency configuration per source set that allows you to declare module dependencies injected as <jar-file> entries in the generated persistence.xml.
The jarFile configuration extends implementation (and api when the java-library plugin is present).
2.4.1. Using the Location Attribute
dependencies {
jarFile(project(':common-entities')) {
attributes {
attribute(persist.jakarta.gradle.plugin.JakartaPersistencePlugin.JAR_LOCATION_ATTRIBUTE, 'lib/')
}
}
}
dependencies {
jarFile(project(":common-entities")) {
attributes {
attribute(persist.jakarta.gradle.plugin.JakartaPersistencePlugin.JAR_LOCATION_ATTRIBUTE, "lib/")
}
}
}
2.4.2. Using DSL Jar File Mappings
You can also declare custom jar-file path mappings directly inside a persistence unit:
persistence {
main {
persistenceUnits {
'my-unit' {
jarFile(project(':ejb-module')) { jarTask ->
"${jarTask.archiveBaseName.get()}.jar"
}
jarFile 'com.example:external-persistence', 'lib/external-persistence-custom.jar'
}
}
}
}
persistence {
create("main") {
persistenceUnits {
create("my-unit") {
jarFileMappings.put(":ejb-module", "ejb-module.jar")
jarFileMappings.put("com.example:external-persistence", "lib/external-persistence-custom.jar")
}
}
}
}
2.5. Tasks
The plugin registers the following tasks per Java source set. For the main source set the task names are as shown below; for other source sets (e.g. test) the source set name is capitalized and inserted (e.g. processTestPersistenceDescriptor).
2.5.1. processPersistenceDescriptor
Group: build
Type: ProcessPersistenceDescriptor
Generates or merges the persistence.xml descriptor for the source set.
-
Merge mode: When a user-provided
src/main/resources/META-INF/persistence.xmlexists, the task parses it, applies extension-defined overrides (provider, data source, properties), injects resolved<class>and<jar-file>entries, and writes the result to the destination. -
Generate mode: When no source descriptor is present, the task builds a complete
persistence.xmlfrom scratch using the DSL configuration.
The task automatically discovers JPA entity classes annotated with @Entity, @Embeddable, @MappedSuperclass, or @Converter using ASM bytecode scanning on the compiled class output.
| Property | Type | Default | Description |
|---|---|---|---|
|
|
|
The JPA specification version for the root |
|
|
from extension |
The list of active (enabled) persistence unit configurations to process. |
|
|
auto-discovered |
Fully qualified class names of discovered JPA entity classes injected as |
|
|
from |
Resolved JAR file names injected as |
|
|
optional |
Path to the user-provided |
|
|
|
The output location of the generated or merged descriptor. |
|
|
from extension |
XML Transformer output properties controlling indentation, encoding, and formatting. |
| The task is automatically skipped when no persistence units are enabled. |
2.5.2. validatePersistenceSchema
Group: verification
Type: ValidatePersistenceSchema
Validates that the JPA entity mappings align correctly with the database schema by booting an isolated JVM worker process.
Each persistence unit is validated using the standard JPA Persistence.createEntityManagerFactory API with the validate schema generation action against an in-memory H2 database.
| Property | Type | Default | Description |
|---|---|---|---|
|
|
from extension |
A comma-separated list of active persistence unit names to validate. |
|
|
from extension |
Nested database connection configuration (URL, driver, user, password). |
|
|
from `processResources` |
The resources directory containing |
|
|
auto-configured |
The full classpath including compiled entity classes, JPA provider binaries, and the H2 driver. |
The H2 JDBC driver (com.h2database:h2:2.2.224) is transparently injected into the task classpath — no manual dependency declaration is needed.
|
| The task is automatically skipped when no active persistence unit names are present. |
2.5.3. generateJPAGraalVMMetadata
Group: build
Type: GenerateJPAGraalVMMetadata
Generates a GraalVM native image reflect-config.json file containing all discovered JPA entity classes to support AOT reflection in native images.
The generated JSON follows the GraalVM reachability metadata format and registers each entity class with allDeclaredConstructors, allDeclaredFields, and allDeclaredMethods set to true.
| Property | Type | Default | Description |
|---|---|---|---|
|
|
auto-discovered |
Fully qualified class names of discovered JPA entity classes. |
|
|
|
The location where the |
The generated resource directory is automatically added to the source set resources, ensuring the JSON file is indexed by IDEs and packaged into the final JAR.
3. Hibernate Plugin
Plugin ID: io.github.jpersist.hibernate-persistence
The io.github.jpersist.hibernate-persistence plugin provides a complete Hibernate persistence pipeline out-of-the-box.
It automatically applies the core io.github.jpersist.jpa plugin (see Jakarta Persistence Plugin), the Hibernate JPA static metamodel generator, and compile-time bytecode enhancement for Hibernate-based projects.
3.1. Applying the Plugin
plugins {
id 'io.github.jpersist.hibernate-persistence' version '1.5.0'
}
dependencies {
jpa platform('org.hibernate.orm:hibernate-platform:6.6.56.Final')
implementation 'org.hibernate.orm:hibernate-core'
}
plugins {
id("io.github.jpersist.hibernate-persistence") version "1.5.0"
}
dependencies {
jpa(platform("org.hibernate.orm:hibernate-platform:6.6.56.Final"))
implementation("org.hibernate.orm:hibernate-core")
}
The jpa configuration is provided by the core Jakarta Persistence plugin (applied transitively).
Use it to declare a Hibernate platform BOM so that all Hibernate module versions are aligned automatically.
|
3.2. Sub-Plugins
The aggregate io.github.jpersist.hibernate-persistence plugin is a convenience macro that applies the following three plugins:
| Plugin ID | Description |
|---|---|
|
The core Jakarta Persistence plugin — registers the |
|
Configures Hibernate’s JPA static metamodel generator ( |
|
Registers the |
You can apply sub-plugins individually if you only need a subset of the functionality:
plugins {
id 'io.github.jpersist.hibernate-enhancement' version '1.5.0'
}
plugins {
id("io.github.jpersist.hibernate-enhancement") version "1.5.0"
}
3.3. JPA Static Metamodel Generation
The io.github.jpersist.hibernate-jpamodelgen sub-plugin automatically:
-
Applies the
javaplugin. -
Adds
org.hibernate.orm:hibernate-jpamodelgenas anannotationProcessordependency for every source set. -
Registers the annotation processor generated source directory (
build/generated/sources/annotationProcessor/java/<sourceSet>) into the source set’s Java source directories for seamless IDE indexing.
No additional configuration is needed — the annotation processor version is resolved from the Hibernate platform BOM declared through the jpa configuration.
For each JPA entity class annotated with @Entity, @Embeddable, or @MappedSuperclass, Hibernate generates a corresponding static metamodel class (e.g. Person_) that provides compile-time-safe attribute references for Criteria API queries.
3.4. DSL Extension: hibernate
The io.github.jpersist.hibernate-enhancement sub-plugin registers a hibernate DSL extension block at the project level.
It exposes a nested enhancement sub-block to control compile-time bytecode transformation behavior.
hibernate {
enhancement {
enableLazyInitialization = true
enableDirtyTracking = true
enableAssociationManagement = true
enableExtendedEnhancement = false
}
}
hibernate {
enhancement {
enableLazyInitialization.set(true)
enableDirtyTracking.set(true)
enableAssociationManagement.set(true)
enableExtendedEnhancement.set(false)
}
}
3.4.1. HibernateExtension Properties
| Property | Type | Default | Description |
|---|---|---|---|
|
|
see below |
Nested configuration block controlling Hibernate compile-time bytecode enhancement options. |
3.4.2. EnhancementExtension Properties
| Property | Type | Default | Description |
|---|---|---|---|
|
|
|
Enhances entity bytecode to support field-level lazy initialization. When enabled, fields or relationships annotated for lazy fetching can be loaded individually on-demand via their getters, instead of initializing the entire containing entity. |
|
|
|
Enhances entities to actively track their own internal state mutations. This allows Hibernate to discover which fields changed during flush, avoiding heavy reflection-based state array snapshot comparisons. |
|
|
|
Automatically manages bidirectional associations — setting one side of a relationship updates the other side in memory (e.g. adding an item to a child collection updates the parent reference). |
|
|
|
Expands the bytecode enhancement scope beyond simple entity definitions to intercept non-proxy boundaries or customized orchestration scenarios. |
Example enabling only dirty tracking and lazy initialization:
hibernate {
enhancement {
enableLazyInitialization = true
enableDirtyTracking = true
enableAssociationManagement = false
enableExtendedEnhancement = false
}
}
hibernate {
enhancement {
enableLazyInitialization.set(true)
enableDirtyTracking.set(true)
enableAssociationManagement.set(false)
enableExtendedEnhancement.set(false)
}
}
3.5. Tasks
The plugin registers the following task per Java source set.
For the main source set the task name is hibernateEnhanceClasses; for other source sets (e.g. test) the source set name is used (e.g. hibernateEnhanceTestClasses).
In addition, all tasks inherited from the core io.github.jpersist.jpa plugin (processPersistenceDescriptor, validatePersistenceSchema, generateJPAGraalVMMetadata) are also available. See Jakarta Persistence Plugin for their documentation.
3.5.1. hibernateEnhanceClasses
Group: build
Type: HibernateEnhancementTask
Performs compile-time bytecode enhancement on Hibernate entity classes using Hibernate’s internal Enhancer engine.
The task reads raw compiled .class files from the Java compilation output directory, runs multi-pass bytecode transformation (type discovery and byte-level rewriting), and writes the enhanced classes to an isolated output directory.
The enhanced classes are automatically included in the final JAR with higher priority than the original unenhanced classes (using DuplicatesStrategy.EXCLUDE), so no additional packaging configuration is needed.
| Property | Type | Default | Description |
|---|---|---|---|
|
|
from |
The input directory containing the raw, unenhanced compiled Java class files. Bound from the Java compilation task’s destination directory. |
|
|
|
The isolated output directory where enhanced class files are written. Keeping this separate from the compile output preserves Gradle’s incremental build and |
|
|
from source set |
The full compilation classpath necessary for Hibernate to inspect, resolve, and validate complex relationships, types, or embedded enums during the bytecode analysis phase. |
|
|
|
Whether to enhance entities for field-level lazy initialization. Bound from |
|
|
|
Whether to inject inline dirty tracking code into entity fields. Bound from |
|
|
|
Whether to automatically manage bidirectional associations. Bound from |
|
|
|
Whether to enable extended bytecode enhancement beyond standard entity boundaries. Bound from |
The task is annotated with @DisableCachingByDefault because enhancement modifies class bytecode in place. It is automatically skipped with a NO-SOURCE outcome when no compiled classes are present in the source directory.
|
The task is wired into the build lifecycle automatically — it runs after compileJava and before classes, so the enhanced bytecode is ready for both testing and packaging without manual task ordering.
|
4. EclipseLink Plugin
Plugin ID: io.github.jpersist.eclipse-persistence
The io.github.jpersist.eclipse-persistence plugin provides a complete EclipseLink persistence pipeline out-of-the-box.
It is the core implementation of the JPersist plugin suite for EclipseLink and facilitates the integration of provider platform capabilities such as JPA static metamodel generation and compile-time static bytecode weaving.
It automatically applies the core io.github.jpersist.jpa plugin (see Jakarta Persistence Plugin), the EclipseLink canonical metamodel generator, and compile-time static weaving for EclipseLink-based projects.
4.1. Applying the Plugin
plugins {
id 'io.github.jpersist.eclipse-persistence' version '1.5.0'
}
dependencies {
jpa platform('org.eclipse.persistence:org.eclipse.persistence.parent:4.0.9')
compileOnly 'jakarta.persistence:jakarta.persistence-api'
implementation 'org.eclipse.persistence:org.eclipse.persistence.core'
}
plugins {
id("io.github.jpersist.eclipse-persistence") version "1.5.0"
}
dependencies {
jpa(platform("org.eclipse.persistence:org.eclipse.persistence.parent:4.0.9"))
compileOnly("jakarta.persistence:jakarta.persistence-api")
implementation("org.eclipse.persistence:org.eclipse.persistence.core")
}
The jpa configuration is provided by the core Jakarta Persistence plugin (applied transitively).
Use it to declare an EclipseLink platform BOM so that all EclipseLink module versions are aligned automatically.
|
4.2. Sub-Plugins
The aggregate io.github.jpersist.eclipse-persistence plugin is a convenience macro that applies the following three plugins:
| Plugin ID | Description |
|---|---|
|
The core Jakarta Persistence plugin — registers the |
|
Configures EclipseLink’s canonical metamodel generator ( |
|
Registers the |
You can apply sub-plugins individually if you only need a subset of the functionality:
plugins {
id 'io.github.jpersist.eclipse-static-weave' version '1.5.0'
}
plugins {
id("io.github.jpersist.eclipse-static-weave") version "1.5.0"
}
4.3. JPA Static Metamodel Generation
The io.github.jpersist.eclipse-jpa-modelgen sub-plugin automatically:
-
Applies the
javaplugin. -
Creates the
eclipselinkDSL extension — aNamedDomainObjectContainerscoped per source set (see DSL Extension:eclipselink). -
Adds
org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen.processoras anannotationProcessordependency for every source set. -
Injects the
-Aeclipselink.persistencexml=<path>compiler argument pointing to the configuredpersistence.xmllocation. -
Registers the annotation processor generated source directory (
build/generated/sources/annotationProcessor/java/<sourceSet>) into the source set’s Java source directories for seamless IDE indexing.
For each JPA entity class annotated with @Entity, @Embeddable, or @MappedSuperclass, EclipseLink generates a corresponding static metamodel class (e.g. Person_) that provides compile-time-safe attribute references for Criteria API queries.
While it is possible to work without a user-provided persistence.xml and rely only on the persistence DSL extension, the io.github.jpersist.eclipse-jpa-modelgen sub-plugin may not work properly.
This is because in this scenario, the persistence.xml will be generated after the compileJava task and without static metamodel classes.
For this reason, the user must provide a persistence.xml template with at least the persistence unit name (mandatory) and the full list of entity classes to include.
|
persistence.xml template for metamodel generation<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence
https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
version="3.0">
<persistence-unit name="example-unit">
<class>com.example.entity.Person</class>
</persistence-unit>
</persistence>
4.4. DSL Extension: eclipselink
The io.github.jpersist.eclipse-jpa-modelgen sub-plugin registers an eclipselink DSL extension block at the project level.
It is a NamedDomainObjectContainer<EclipselinkExtension>, meaning an entry is automatically created for each source set (e.g. main, test).
Each entry exposes a nested jpaModelgen sub-block to control the canonical metamodel generation parameters.
eclipselink {
main {
jpaModelgen {
persistenceXml = 'src/main/resources/META-INF/persistence.xml'
}
}
}
eclipselink {
named("main") {
jpaModelgen {
persistenceXml.set(layout.projectDirectory.file("src/main/resources/META-INF/persistence.xml"))
}
}
}
4.4.1. EclipselinkExtension Properties
| Property | Type | Default | Description |
|---|---|---|---|
|
|
source set name |
The name of the source set associated with this configuration block. Populated automatically by Gradle’s container instantiation engine. |
|
|
see below |
Nested configuration block controlling the EclipseLink canonical metamodel generator options for this source set. |
4.4.2. JpaModelgenExtension Properties
| Property | Type | Default | Description |
|---|---|---|---|
|
|
|
Path to the |
Example overriding the persistence.xml location for a custom source set:
eclipselink {
integrationTest {
jpaModelgen {
persistenceXml = 'src/integrationTest/resources/META-INF/persistence.xml'
}
}
}
eclipselink {
named("integrationTest") {
jpaModelgen {
persistenceXml.set(layout.projectDirectory.file("src/integrationTest/resources/META-INF/persistence.xml"))
}
}
}
4.5. Tasks
The plugin registers the following task per Java source set.
In addition, all tasks inherited from the core io.github.jpersist.jpa plugin (processPersistenceDescriptor, validatePersistenceSchema, generateJPAGraalVMMetadata) are also available. See Jakarta Persistence Plugin for their documentation.
4.5.1. eclipseWeaveClasses
Group: build
Type: EclipseWeaveTask
Performs compile-time static bytecode weaving on EclipseLink entity classes using the official EclipseLink StaticWeave command-line processor in an isolated JVM process.
The task reads raw compiled .class files from the Java compilation output directory, executes the weaving process, and writes the woven classes to an isolated output directory.
For the main source set the task name is eclipseWeaveClasses; for other source sets (e.g. test) the source set name is used (e.g. eclipseWeaveTestClasses).
The woven classes are automatically included in the final JAR with higher priority than the original unwoven classes (using DuplicatesStrategy.EXCLUDE), so no additional packaging configuration is needed.
| Property | Type | Default | Description |
|---|---|---|---|
|
|
from |
The input directory containing the raw, unwoven compiled Java class files. Bound from the Java compilation task’s destination directory. |
|
|
|
The isolated output directory where woven class files are written. Keeping this separate from the compile output preserves Gradle’s incremental build and |
|
|
from |
The root directory containing persistence configuration metadata files (e.g. |
|
|
from |
The classpath carrying the EclipseLink core libraries and tool binaries required to execute the |
|
|
from source set |
The full compilation classpath necessary for EclipseLink to inspect, map, and validate structural relationship models while modifying entity classes. |
The task is annotated with @DisableCachingByDefault because weaving modifies class bytecode in place. It is automatically skipped with a NO-SOURCE outcome when no compiled classes are present in the source directory.
|
The task is wired into the build lifecycle automatically — it runs after compileJava and before classes, so the woven bytecode is ready for both testing and packaging without manual task ordering.
|
4.6. The weave Configuration
The io.github.jpersist.eclipse-static-weave sub-plugin creates a weave dependency configuration that carries the EclipseLink runtime libraries needed by the StaticWeave processor.
-
If the
jpaconfiguration exists (e.g. when the coreio.github.jpersist.jpaplugin is applied), theweaveconfiguration automatically extends from it, inheriting all platform version constraints. -
The plugin adds
org.eclipse.persistence:org.eclipse.persistence.jpato theweaveconfiguration by default.
dependencies {
jpa platform('org.eclipse.persistence:org.eclipse.persistence.parent:4.0.9')
// The 'weave' configuration automatically inherits from 'jpa'
}
dependencies {
jpa(platform("org.eclipse.persistence:org.eclipse.persistence.parent:4.0.9"))
// The 'weave' configuration automatically inherits from 'jpa'
}
5. Configuration
This section covers advanced configuration topics for JPersist plugins.
5.1. Multi-Module Projects
In multi-module Gradle projects, declare the provider-specific plugin once in the root build file with apply false, then apply it individually in each module that contains JPA entities.
Use the jarFile dependency configuration together with DSL jar-file mappings to declare cross-module entity dependencies so that <jar-file> entries are correctly generated in persistence.xml.
5.1.1. Root build.gradle
plugins {
id 'base'
id 'io.github.jpersist.hibernate-persistence' version '1.5.0' apply false
}
subprojects {
repositories {
mavenCentral()
}
}
plugins {
base
id("io.github.jpersist.hibernate-persistence") version "1.5.0" apply false
}
subprojects {
repositories {
mavenCentral()
}
}
Declaring the plugin with apply false in the root project makes the plugin available to subprojects without applying it at the root level. Each subproject then opts in explicitly.
|
5.1.2. Entity Module build.gradle
The entity module defines JPA entity classes and applies both java-library and the Hibernate persistence plugin.
Because the plugin version is already declared in the root build.gradle, the subproject does not need to repeat it.
plugins {
id 'java-library'
id 'io.github.jpersist.hibernate-persistence'
}
dependencies {
jpa platform('org.hibernate.orm:hibernate-platform:6.6.56.Final')
implementation 'org.hibernate.orm:hibernate-core'
}
plugins {
`java-library`
id("io.github.jpersist.hibernate-persistence")
}
dependencies {
jpa(platform("org.hibernate.orm:hibernate-platform:6.6.56.Final"))
implementation("org.hibernate.orm:hibernate-core")
}
5.1.3. Service Module build.gradle
The service module depends on the entity module.
It declares a jarFile project dependency and maps the jar-file location directly inside the persistence unit DSL block.
plugins {
id 'java-library'
id 'io.github.jpersist.hibernate-persistence'
}
dependencies {
jpa platform('org.hibernate.orm:hibernate-platform:6.6.56.Final')
implementation 'org.hibernate.orm:hibernate-core'
jarFile project(':entity-module')
}
persistence {
main {
persistenceUnits {
'service-persistence-unit' {
jarFile(project(':entity-module')) { jarTask ->
"lib/${jarTask.archiveFileName.get()}"
}
}
}
}
}
plugins {
`java-library`
id("io.github.jpersist.hibernate-persistence")
}
dependencies {
jpa(platform("org.hibernate.orm:hibernate-platform:6.6.56.Final"))
implementation("org.hibernate.orm:hibernate-core")
jarFile(project(":entity-module"))
}
persistence {
create("main") {
persistenceUnits {
create("service-persistence-unit") {
jarFileMappings.put(":entity-module", "lib/entity-module.jar")
}
}
}
}
The jarFile dependency ensures that the entity module’s JAR is resolved at build time.
The DSL jarFile mapping inside persistenceUnits controls the exact <jar-file> path written to persistence.xml.
See Jakarta Persistence Plugin for the full documentation on the jarFile dependency routing and DSL jar-file mappings.
5.2. JPA Version Selection
The persistence extension defaults to JPA 3.0. To target a different specification version, set the version property:
persistence {
main {
version = '2.1' // JPA 2.1
}
}
persistence {
create("main") {
version.set("2.1") // JPA 2.1
}
}
Supported versions: 2.0, 2.1, 2.2, 3.0, 3.1 and 3.2.
5.3. Gradle Configuration Cache
All JPersist plugins are fully compatible with Gradle’s Configuration Cache.
No special configuration is required — the plugins use lazy Property and Provider APIs throughout to ensure safe serialization of the build configuration.
5.4. IDE Integration
JPersist automatically hooks into Buildship (Eclipse) and IntelliJ IDEA project synchronization. Generated source directories for metamodel classes are registered as source roots, so IDE indexing works out of the box.
6. Examples
Complete runnable examples are available in the examples/ directory of the repository.
Each example demonstrates a minimal JPA project using one of the supported plugins.
6.1. Hibernate Example
This example applies the io.github.jpersist.hibernate-persistence aggregator plugin to generate persistence.xml descriptors and perform compile-time bytecode enhancement via Hibernate.
plugins {
id 'java-library'
id 'io.github.jpersist.hibernate-persistence' version '1.5.0'
}
dependencies {
jpa platform('org.hibernate.orm:hibernate-platform:6.6.56.Final')
implementation 'org.hibernate.orm:hibernate-core'
}
repositories {
mavenCentral()
}
plugins {
`java-library`
id("io.github.jpersist.hibernate-persistence") version "1.5.0"
}
dependencies {
jpa(platform("org.hibernate.orm:hibernate-platform:6.6.56.Final"))
implementation("org.hibernate.orm:hibernate-core")
}
repositories {
mavenCentral()
}
See Hibernate Plugin for the full list of extension properties and tasks.
6.2. EclipseLink Example
This example applies the io.github.jpersist.eclipse-persistence aggregator plugin to generate persistence.xml descriptors and perform compile-time static weaving via EclipseLink.
plugins {
id 'java-library'
id 'io.github.jpersist.eclipse-persistence' version '1.5.0'
}
dependencies {
jpa platform('org.eclipse.persistence:org.eclipse.persistence.parent:4.0.9')
compileOnly 'jakarta.persistence:jakarta.persistence-api'
implementation 'org.eclipse.persistence:org.eclipse.persistence.core'
}
repositories {
mavenCentral()
}
plugins {
`java-library`
id("io.github.jpersist.eclipse-persistence") version "1.5.0"
}
dependencies {
jpa(platform("org.eclipse.persistence:org.eclipse.persistence.parent:4.0.9"))
compileOnly("jakarta.persistence:jakarta.persistence-api")
implementation("org.eclipse.persistence:org.eclipse.persistence.core")
}
repositories {
mavenCentral()
}
See EclipseLink Plugin for the full list of extension properties and tasks.
6.3. Jakarta Persistence Example
This example demonstrates standalone descriptor generation using the core io.github.jpersist.jpa plugin without a specific JPA provider aggregator.
It explicitly configures a persistence unit with a provider class and custom properties via the persistence DSL extension.
plugins {
id 'java-library'
id 'io.github.jpersist.jpa' version '1.5.0'
}
dependencies {
compileOnly 'jakarta.persistence:jakarta.persistence-api:3.1.0'
}
persistence {
main {
persistenceUnits {
'example-persistence-unit' {
provider = 'org.hibernate.jpa.HibernatePersistenceProvider'
properties {
property 'hibernate.show_sql', 'true'
}
}
}
}
}
repositories {
mavenCentral()
}
plugins {
`java-library`
id("io.github.jpersist.jpa") version "1.5.0"
}
dependencies {
compileOnly("jakarta.persistence:jakarta.persistence-api:3.1.0")
}
persistence {
named("main") {
persistenceUnits {
create("example-persistence-unit") {
provider.set("org.hibernate.jpa.HibernatePersistenceProvider")
properties {
property("hibernate.show_sql", "true")
}
}
}
}
}
repositories {
mavenCentral()
}
See Jakarta Persistence Plugin for the full documentation on the persistence DSL extension.
6.4. Entity Class
Each example uses a simple Person entity annotated with standard Jakarta Persistence annotations:
package com.example.entity;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.Objects;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Enumerated;
import jakarta.persistence.Id;
@Entity
public class Person implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Id
private Long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "birth_date")
private LocalDate birthDate;
@Enumerated
private Gender gender;
public Person() {
// Default no-arg constructor
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public LocalDate getBirthDate() {
return birthDate;
}
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
@Override
public int hashCode() {
return Objects.hash(birthDate, firstName, gender, id, lastName);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
return Objects.equals(birthDate, other.birthDate) && Objects.equals(firstName, other.firstName)
&& gender == other.gender && Objects.equals(id, other.id) && Objects.equals(lastName, other.lastName);
}
public enum Gender {
FEMALE, MALE
}
}
6.5. Persistence Descriptor Template
Each example includes a persistence.xml template in src/main/resources/META-INF/.
The plugin merges auto-detected entity classes with the entries defined in this template.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="3.0"
xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence
https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd">
<persistence-unit name="example-persistence-unit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.example.entity.Person</class>
</persistence-unit>
</persistence>
Providing a persistence.xml template is optional when using the Hibernate or core JPA plugin.
However, it is required when applying the io.github.jpersist.eclipse-jpa-modelgen sub-plugin.
See EclipseLink Plugin for details.
|
7. FAQ
7.1. 1. Do I need to write a persistence.xml manually?
No. The plugin automatically scans your compiled classes for JPA entity annotations and generates a complete persistence.xml.
If you provide a template persistence.xml in src/main/resources/META-INF/, the plugin merges your entries with the auto-detected entities.
When applying the io.github.jpersist.eclipse-jpa-modelgen sub-plugin, you must provide a persistence.xml template with at least the persistence unit name and the full list of entity classes.
Without it, metamodel generation may not work correctly because the persistence.xml is generated after the compileJava task.
See EclipseLink Plugin — JPA Static Metamodel Generation for details and a minimal template example.
|
7.2. 2. Can I use both Hibernate and EclipseLink in the same project?
Each module should use only one provider plugin. However, different modules within a multi-module project can use different providers.
It is also possible to combine sub-plugins from different providers within the same module.
For example, instead of applying one of the aggregator plugins (io.github.jpersist.hibernate-persistence or io.github.jpersist.eclipse-persistence), you can manually apply the core io.github.jpersist.jpa plugin first, then cherry-pick individual sub-plugins:
plugins {
id 'io.github.jpersist.jpa' version '1.5.0'
id 'io.github.jpersist.hibernate-jpamodelgen' version '1.5.0'
id 'io.github.jpersist.eclipse-static-weave' version '1.5.0'
}
plugins {
id("io.github.jpersist.jpa") version "1.5.0"
id("io.github.jpersist.hibernate-jpamodelgen") version "1.5.0"
id("io.github.jpersist.eclipse-static-weave") version "1.5.0"
}
In this example, JPA static metamodel generation is handled by Hibernate’s annotation processor while compile-time bytecode weaving is performed by EclipseLink’s static weaver. Note that in this scenario, the target JPA platform is EclipseLink — the static weaving step produces EclipseLink-enhanced bytecode, so the runtime persistence provider must be EclipseLink.
7.3. 3. Which JPA specification versions are supported?
The plugin supports JPA 2.0, 2.1, 2.2, 3.0, 3.1, and 3.2.
The default version is 3.0 (Jakarta Persistence 3.0).
See Configuration — JPA Version Selection for how to change the target version.
7.4. 4. Is the Gradle Configuration Cache supported?
Yes. All JPersist plugins are fully compatible with Gradle’s Configuration Cache and Isolated Projects features.
7.5. 5. Do I need a runtime -javaagent for bytecode enhancement?
No. Both the Hibernate enhancement and EclipseLink static weaving plugins perform bytecode modification at compile time. No runtime agent is required.
See Hibernate Plugin — hibernateEnhanceClasses and EclipseLink Plugin — eclipseWeaveClasses for details.
7.6. 6. Where can I find the API documentation?
The full Groovydoc API reference is published at jpersist.github.io/persistence/api/latest. The User Guide is available at jpersist.github.io/persistence/guide/latest.