Skip to content

Commit

Permalink
#91 - Consider multi-project / multi-jar set up for hibernate-models
Browse files Browse the repository at this point in the history
#85 - Consider ways to make Jandex not required at runtime
  • Loading branch information
sebersole committed Aug 26, 2024
1 parent 9947aa8 commit eec7336
Show file tree
Hide file tree
Showing 283 changed files with 2,083 additions and 1,786 deletions.
22 changes: 13 additions & 9 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
:fn-managed: footnote:[The application's domain and related classes]
== Hibernate models

Uses a mix of https://smallrye.io/jandex/[Jandex] and Java reflection to build the de-typed abstraction model of
classes and annotations referenced by an application's managed resources{fn-managed}.
Provides support for dealing with an application's managed resources{fn-managed} as a de-typed abstraction model
backed by one or more sources. Consumers can then access details from that abstraction model in a unified way,
regardless of the underlying source.

Consumers can then access details from that abstraction model in a unified way, regardless of the underlying
source. For classes which we are able to access from a Jandex index, this has the benefit that the classes are
not loaded into the ClassLoader which is important because once a classes is loaded into a ClassLoader, its
bytecode cannot be changed and run-time bytecode enhancement is not possible.

This work is intended to replace the https://github.com/hibernate/hibernate-commons-annotations[`hibernate-commons-annotation`] (HCANN)
library, which suffered from a number of shortcomings.
NOTE: This work replaces the https://github.com/hibernate/hibernate-commons-annotations[`hibernate-commons-annotation`] library, which suffered from a number of shortcomings.


=== Annotations
Expand All @@ -37,3 +32,12 @@ FieldDetails:: Think `java.lang.reflect.Field`
MethodDetails:: Think `java.lang.reflect.Method`
RecordComponentDetails:: Think `java.lang.reflect.RecordComponent`
ClassDetailsRegistry:: registry of `ClassDetails` references


=== Artifacts

hibernate-models:: The base support, using Java reflection as the backing source.
hibernate-models-jandex:: Optional support for using https://smallrye.io/jandex/[Jandex] as the backing source. Using
definitions from a Jandex index has the benefit that the classes are not loaded into the ClassLoader which can be important
in a few scenarios (e.g. retain the ability to enhance a class's bytecode).

123 changes: 14 additions & 109 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,118 +1,23 @@
plugins {
id "java-library"

id "base-information"

id "checkstyle"
id "jacoco"

id "maven-publish"
id "io.github.gradle-nexus.publish-plugin" version "2.0.0"
id "publishing-config"
id "signing-config"
id "release-process"
id "io.github.gradle-nexus.publish-plugin"
}

dependencies {
implementation libs.jandex
implementation libs.logging

compileOnly libs.loggingAnnotations

annotationProcessor libs.loggingProcessor
annotationProcessor libs.logging
annotationProcessor libs.loggingAnnotations

testImplementation jakartaLibs.jpa
testImplementation testLibs.junit5Api
testImplementation testLibs.assertjCore

testRuntimeOnly testLibs.junit5Engine
testRuntimeOnly testLibs.log4j
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Java handling
// OSSRH publishing
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// To force the build produce the same byte-for-byte archives and hence make Hibernate Models build reproducible.
// See also https://docs.gradle.org/current/userguide/working_with_files.html#sec:reproducible_archives
tasks.withType(AbstractArchiveTask).configureEach {
preserveFileTimestamps = false
reproducibleFileOrder = true
}

java {
sourceCompatibility = jdks.versions.baseline.get() as int
targetCompatibility = jdks.versions.baseline.get() as int

withJavadocJar()
withSourcesJar()
}

test {
useJUnitPlatform()
}
String hibernatePublishUsername = project.hasProperty( 'hibernatePublishUsername' )
? project.property( 'hibernatePublishUsername' )
: null
String hibernatePublishPassword = project.hasProperty( 'hibernatePublishPassword' )
? project.property( 'hibernatePublishPassword' )
: null

// create a single "compile" task
tasks.register( "compile" ).configure {
dependsOn tasks.withType( JavaCompile )
}

tasks.withType( JavaCompile ).configureEach {javaCompile->
options.encoding = "UTF-8"
options.warnings false
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Javadoc
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

tasks.named( "javadoc", Javadoc ) {
options {
use = true
encoding = "UTF-8"

addStringOption( "Xdoclint:none", "-quiet" )

tags(
"todo:X",
"apiNote:a:API Note:",
"implSpec:a:Implementation Specification:",
"implNote:a:Implementation Note:"
)
nexusPublishing {
repositories {
sonatype {
username = hibernatePublishUsername
password = hibernatePublishPassword
}
}
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Checkstyle
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

checkstyle {
sourceSets = [ project.sourceSets.main ]
showViolations = false
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JaCoCo
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def jacocoReportTask = tasks.named( "jacocoTestReport" ) {
dependsOn tasks.named( "test" )
}

jacocoTestReport {
reports {
xml.required = false
csv.required = false
html.outputLocation = layout.buildDirectory.dir( "jacocoHtml" )
}
}

tasks.named( "check" ) {
dependsOn jacocoReportTask
}
2 changes: 1 addition & 1 deletion buildSrc/src/main/groovy/base-information.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ group = "org.hibernate.models"
// Version handling
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def versionFile = project.file( "version.txt" )
def versionFile = rootProject.file( "version.txt" )
def releaseVersion = determineVersion("releaseVersion", versionFile )
def developmentVersion = determineVersion("developmentVersion", versionFile)

Expand Down
103 changes: 103 additions & 0 deletions buildSrc/src/main/groovy/java-module.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
plugins {
id "base-information"
id "java-library"

id "checkstyle"
id "jacoco"
}

dependencies {
implementation libs.logging

compileOnly libs.loggingAnnotations

annotationProcessor libs.loggingProcessor
annotationProcessor libs.logging
annotationProcessor libs.loggingAnnotations

testImplementation jakartaLibs.jpa
testImplementation testLibs.junit5Api
testImplementation testLibs.assertjCore

testRuntimeOnly testLibs.junit5Engine
testRuntimeOnly testLibs.log4j
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Java handling
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

java {
sourceCompatibility = jdks.versions.baseline.get() as int
targetCompatibility = jdks.versions.baseline.get() as int

withJavadocJar()
withSourcesJar()
}

test {
useJUnitPlatform()
}

// create a single "compile" task
tasks.register( "compile" ).configure {
dependsOn tasks.withType( JavaCompile )
}

tasks.withType( JavaCompile ).configureEach {javaCompile->
options.encoding = "UTF-8"
options.warnings false
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Javadoc
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

tasks.named( "javadoc", Javadoc ) {
options {
use = true
encoding = "UTF-8"

addStringOption( "Xdoclint:none", "-quiet" )

tags(
"todo:X",
"apiNote:a:API Note:",
"implSpec:a:Implementation Specification:",
"implNote:a:Implementation Note:"
)
}
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Checkstyle
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

checkstyle {
sourceSets = [ project.sourceSets.main ]
showViolations = false
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JaCoCo
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def jacocoReportTask = tasks.named( "jacocoTestReport" ) {
dependsOn tasks.named( "test" )
}

jacocoTestReport {
reports {
xml.required = false
csv.required = false
html.outputLocation = layout.buildDirectory.dir( "jacocoHtml" )
}
}

tasks.named( "check" ) {
dependsOn jacocoReportTask
}
8 changes: 8 additions & 0 deletions buildSrc/src/main/groovy/published-java-module.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
plugins {
id "java-module"

id "maven-publish"
id "publishing-config"
id "signing-config"
id "release-process"
}
23 changes: 2 additions & 21 deletions buildSrc/src/main/groovy/publishing-config.gradle
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
plugins {
id "java-library"
id "io.github.gradle-nexus.publish-plugin"
id "java-module"
id "maven-publish"
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// OSSRH publishing
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

String hibernatePublishUsername = project.hasProperty( 'hibernatePublishUsername' )
? project.property( 'hibernatePublishUsername' )
: null
String hibernatePublishPassword = project.hasProperty( 'hibernatePublishPassword' )
? project.property( 'hibernatePublishPassword' )
: null

publishing {
publications {
Expand Down Expand Up @@ -62,12 +52,3 @@ publishing {
}
}

nexusPublishing {
repositories {
sonatype {
username = hibernatePublishUsername
password = hibernatePublishPassword
}
}
}

13 changes: 13 additions & 0 deletions hibernate-models-jandex/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
plugins {
id "published-java-module"
}

description = "Jandex support for hibernate-models (isolated dependency)"

dependencies {
api project( ":hibernate-models" )

implementation libs.jandex

testImplementation project( ":hibernate-models-testing" )
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.models.internal.jandex;
package org.hibernate.models.jandex.internal;

import java.lang.annotation.Annotation;
import java.util.Map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.models.internal.jandex;
package org.hibernate.models.jandex.internal;

import org.hibernate.models.jandex.spi.JandexModelBuildingContext;
import org.hibernate.models.jandex.spi.JandexValueExtractor;
import org.hibernate.models.spi.SourceModelBuildingContext;
import org.hibernate.models.spi.JandexValueExtractor;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationValue;
Expand Down Expand Up @@ -38,6 +39,6 @@ protected AnnotationValue resolveAnnotationValue(
return explicitValue;
}

return annotation.valueWithDefault( buildingContext.getJandexIndex(), attributeName );
return annotation.valueWithDefault( buildingContext.as( JandexModelBuildingContext.class ).getJandexIndex(), attributeName );
}
}
Loading

0 comments on commit eec7336

Please sign in to comment.