diff --git a/build-logic/docs-core/src/main/groovy/org/apache/grails/gradle/tasks/bom/PropertyNameCalculator.groovy b/build-logic/docs-core/src/main/groovy/org/apache/grails/gradle/tasks/bom/PropertyNameCalculator.groovy index cdc3c7024a5..af4761e3157 100644 --- a/build-logic/docs-core/src/main/groovy/org/apache/grails/gradle/tasks/bom/PropertyNameCalculator.groovy +++ b/build-logic/docs-core/src/main/groovy/org/apache/grails/gradle/tasks/bom/PropertyNameCalculator.groovy @@ -117,6 +117,21 @@ class PropertyNameCalculator { possibleKey = lastIndex > 0 ? possibleKey.substring(0, lastIndex) : null } + // Fallback: check if any existing version property is a prefix of the artifact key. + // This handles cases like 'derbyclient' matching 'derby.version' to align with + // Spring Boot's BOM property naming conventions. + String artifactKey = keyMappings[found.coordinates] + if (artifactKey) { + String match = versions.keySet() + .findAll { it.endsWith('.version') } + .collect { it - '.version' } + .findAll { artifactKey.startsWith(it) } + .max { it.length() } + if (match) { + return "${match}.version" as String + } + } + null } } diff --git a/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy index a8116836a0c..8718cd3e510 100644 --- a/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy +++ b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy @@ -58,8 +58,9 @@ class CompilePlugin implements Plugin { } private static void configureJavaVersion(Project project) { + Integer javaVersion = lookupPropertyByType(project, 'javaVersion', Integer) project.tasks.withType(JavaCompile).configureEach { - it.options.release.set(lookupPropertyByType(project, 'javaVersion', Integer)) + it.options.release.set(javaVersion) } } diff --git a/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsDependencyValidatorPlugin.groovy b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsDependencyValidatorPlugin.groovy index 74b1a7c0751..7dc312d79fb 100644 --- a/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsDependencyValidatorPlugin.groovy +++ b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsDependencyValidatorPlugin.groovy @@ -55,7 +55,7 @@ class GrailsDependencyValidatorPlugin implements Plugin { */ static final String ALLOWED_OVERRIDES_EXT = 'allowedBomOverrides' - private static final Set BOM_PROJECT_NAMES = ['grails-bom', 'grails-gradle-bom', 'grails-base-bom', 'grails-hibernate5-bom', 'grails-micronaut-bom'].toSet() + private static final Set BOM_PROJECT_NAMES = ['grails-bom', 'grails-gradle-bom', 'grails-base-bom', 'grails-hibernate5-bom', 'grails-micronaut-bom', 'grails-hibernate5-micronaut-bom'].toSet() @Override void apply(Project project) { diff --git a/dependencies.gradle b/dependencies.gradle index d2a51fb8e09..ba88b6d077c 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -217,14 +217,23 @@ ext { // grails-micronaut-bom project. Declared with `strictly` in the BOM project so // they win over Micronaut platform's higher versions when consumers use // enforcedPlatform(:grails-micronaut-bom). - else if (project.name == 'grails-micronaut-bom') { + else if (project.name in ['grails-micronaut-bom', 'grails-hibernate5-micronaut-bom']) { customBomVersions = [ + 'liquibase-hibernate.version': '4.27.0', + 'liquibase.version' : '4.27.0', + 'hibernate.version' : '5.6.15.Final', 'groovy.version' : '5.0.5', 'spock.version' : '2.4-groovy-5.0', 'protobuf.version': '4.30.2', ] combinedVersions += customBomVersions customBomDependencies = [ + 'liquibase' : "org.liquibase:liquibase:${combinedVersions['liquibase.version']}", + 'liquibase-cdi' : "org.liquibase:liquibase-cdi:${combinedVersions['liquibase.version']}", + 'liquibase-core' : "org.liquibase:liquibase-core:${combinedVersions['liquibase.version']}", + 'liquibase-hibernate' : "org.liquibase.ext:liquibase-hibernate5:${combinedVersions['liquibase-hibernate.version']}", + 'hibernate-core-jakarta': "org.hibernate:hibernate-core-jakarta:${combinedVersions['hibernate.version']}", + 'hibernate-ehcache' : "org.hibernate:hibernate-ehcache:${combinedVersions['hibernate.version']}", 'groovy' : "org.apache.groovy:groovy:${combinedVersions['groovy.version']}", 'groovy-ant' : "org.apache.groovy:groovy-ant:${combinedVersions['groovy.version']}", 'groovy-astbuilder' : "org.apache.groovy:groovy-astbuilder:${combinedVersions['groovy.version']}", diff --git a/gradle/publish-root-config.gradle b/gradle/publish-root-config.gradle index b0ba7c29dfa..6757868df34 100644 --- a/gradle/publish-root-config.gradle +++ b/gradle/publish-root-config.gradle @@ -33,7 +33,6 @@ def publishedProjects = [ 'grails-base-bom', 'grails-bom', 'grails-hibernate5-bom', - 'grails-micronaut-bom', 'grails-bootstrap', 'grails-cache', 'grails-codecs', @@ -68,7 +67,6 @@ def publishedProjects = [ 'grails-interceptors', 'grails-layout', 'grails-logging', - 'grails-micronaut', 'grails-mimetypes', 'grails-rest-transforms', 'grails-scaffolding', @@ -143,6 +141,15 @@ def publishedProjects = [ 'grails-profiles-web-plugin', ] +def skipMicronautProjects = providers.gradleProperty('skipMicronautProjects').isPresent() +if (!skipMicronautProjects) { + publishedProjects.addAll([ + 'grails-hibernate5-micronaut-bom', + 'grails-micronaut', + 'grails-micronaut-bom', + ]) +} + subprojects { if (name in publishedProjects) { // This has to be applied here in the root project due to the nexus plugin requirements diff --git a/grails-bom/hibernate5-micronaut/build.gradle b/grails-bom/hibernate5-micronaut/build.gradle new file mode 100644 index 00000000000..9d91c8b5b8c --- /dev/null +++ b/grails-bom/hibernate5-micronaut/build.gradle @@ -0,0 +1,258 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.grails.gradle.tasks.bom.ExtractDependenciesTask +import org.apache.grails.gradle.tasks.bom.ExtractedDependencyConstraint +import org.apache.grails.gradle.tasks.bom.PropertyNameCalculator + +buildscript { + apply from: rootProject.layout.projectDirectory.file('dependencies.gradle') +} + +plugins { + id 'java-platform' + id 'org.apache.grails.buildsrc.publish' + id 'org.apache.grails.buildsrc.sbom' +} + +version = projectVersion +group = 'org.apache.grails' + +javaPlatform { + allowDependencies() +} + +ext { + isReleaseBuild = System.getenv('GRAILS_PUBLISH_RELEASE') == 'true' + isPublishedExternal = System.getenv().containsKey('NEXUS_PUBLISH_STAGING_PROFILE_ID') + // TODO: It should be possible to pull these build names using includedBuild, but I haven't found a way to do so + gradleBuildProjects = [ + 'grails-gradle-plugins':'org.apache.grails', + 'grails-gradle-model':'org.apache.grails.gradle', + 'grails-gradle-common':'org.apache.grails.gradle', + 'grails-gradle-tasks':'org.apache.grails', + ] +} + +// Register the Micronaut platform in combinedPlatforms/combinedVersions so +// PropertyNameCalculator (used by extractConstraints and pomCustomization) can +// resolve a property name for the micronaut-platform constraint. +project.ext.combinedPlatforms = combinedPlatforms + ['micronaut-platform': "io.micronaut.platform:micronaut-platform:$micronautPlatformVersion".toString()] +project.ext.combinedVersions = combinedVersions + ['micronaut-platform.version': micronautPlatformVersion as String] + +// Coordinates we override via customBomDependencies — these must be excluded from the +// inherited platform chain so they don't conflict with our strictly-versioned overrides +// when consumers apply this BOM via enforcedPlatform. +def overriddenModules = customBomDependencies.values().collect { String coord -> + def parts = coord.split(':') + [group: parts[0], module: parts[1]] +} +Set overriddenCoords = overriddenModules.collect { "${it.group}:${it.module}".toString() } as Set + +dependencies { + api(platform(project(':grails-base-bom'))) { + overriddenModules.each { ovr -> + exclude group: ovr.group, module: ovr.module + } + } + + // Re-export the Micronaut platform so consumers inherit Micronaut's managed versions + // transitively. Exclude Groovy since we declare the required version explicitly via + // customBomDependencies. Exclude Spock since we manage that version ourselves. + // Exclude Jackson 3 (tools.jackson) since spring-boot-dependencies manages that version, + // and Micronaut can lag behind Spring Boot's patch bumps (e.g. SB 4.0.6 ships + // jackson-bom 3.1.2 while micronaut-platform 5.0.0-M2 still pins 3.1.0). + api(platform("io.micronaut.platform:micronaut-platform:$micronautPlatformVersion")) { + exclude group: 'org.apache.groovy' + exclude group: 'org.spockframework' + exclude group: 'tools.jackson' + } + + constraints { + // Re-declare base BOM constraints directly so enforcedPlatform() consumers + // get forced versions. Constraints inherited via platform() are not enforced + // by enforcedPlatform — only direct constraints are. + // Skip entries we override below in customBomDependencies to avoid conflicting + // strictly constraints under enforcedPlatform. + gradleBomDependencies.values().each { String coord -> + def parts = coord.split(':') + String key = parts[0] + ':' + parts[1] + if (key in overriddenCoords) { + return + } + api coord + } + bomDependencies.values().each { String coord -> + def parts = coord.split(':') + String key = parts[0] + ':' + parts[1] + if (key in overriddenCoords) return + api coord + } + for (def entry : bomPlatformDependencies.entrySet()) { + api entry.value + } + // Re-declare the Micronaut platform as a constraint for enforcedPlatform support + api "io.micronaut.platform:micronaut-platform:$micronautPlatformVersion" + for (def entry : customBomDependencies.entrySet()) { + def parts = entry.value.split(':') + if (parts.length == 3) { + api("${parts[0]}:${parts[1]}") { + version { + strictly parts[2] + } + } + } else { + api entry.value + } + } + } +} + +configurations.register('bomDependencies').configure { + it.canBeResolved = true + it.transitive = true + it.extendsFrom(configurations.named('api').get()) +} + +tasks.register('extractConstraints', ExtractDependenciesTask).configure { ExtractDependenciesTask it -> + it.captureProjectServices(project.dependencies, project.configurations) + it.configuration = configurations.named('bomDependencies') + it.configurationName = 'bomDependencies' + it.destination = project.layout.buildDirectory.file('grails-hibernate5-micronaut-bom-constraints.adoc') + it.platformDefinitions = combinedPlatforms + it.definitions = combinedDependencies + it.projectName = project.name + it.versions = combinedVersions + // Micronaut's platform imports many sub-BOMs (micronaut-*-bom, netty-bom, etc.) that are + // not explicitly registered in dependencies.gradle. Auto-register them so extractConstraints + // can document their versions without requiring manual entries for every transitive platform. + // this is required because the micronaut bom format uses gradle modules instead of a pom like spring boot + it.autoRegisterTransitivePlatforms = true + rootProject.subprojects.each { p -> + evaluationDependsOn(p.path) + } + it.projectArtifactIds.set(project.provider { + Map artifactIdMappings = [:] + + rootProject.subprojects.each { p -> + artifactIdMappings[p.name] = p.findProperty('pomArtifactId') ?: p.name + } + + for (Map.Entry dependency : project.ext.gradleBuildProjects.entrySet()) { + artifactIdMappings[dependency.key] = dependency.key + } + + artifactIdMappings + }) + it.forcedGroupPrefixes.set(['org.apache.grails.profiles': 'grails-profile']) + it.projectCoordinateProperties.set(project.provider { + Map projectCoordinates = [:] + + rootProject.subprojects.each { p -> + String artifactId = p.findProperty('pomArtifactId') as String ?: p.name + String baseVersionName = artifactId.replaceAll('[.]', '-') + projectCoordinates["${p.group}:${artifactId}:${p.version}" as String] = baseVersionName + } + + for (Map.Entry dependency : project.ext.gradleBuildProjects.entrySet()) { + projectCoordinates["${dependency.value}:${dependency.key}:${project.version}" as String] = dependency.key + } + + projectCoordinates + }) + + it.dependsOn(project.tasks.named('generateMetadataFileForMavenPublication'), project.tasks.named('generatePomFileForMavenPublication')) +} + +def validateNoSnapshotDependencies = tasks.register('validateNoSnapshotDependencies') +validateNoSnapshotDependencies.configure { Task it -> + it.group = 'publishing' + it.description = 'Validates that no snapshot dependencies are present in the project when performing a release.' + + it.doLast { + configurations.each { config -> + config.allDependencies.each { dep -> + if (dep.version && dep.version.contains('-SNAPSHOT')) { + throw new GradleException("Releases cannot have a snapshot dependency: ${dep.group}:${dep.name} (${dep.version})") + } + } + } + } +} + +if (ext.isReleaseBuild && ext.isPublishedExternal) { + project.afterEvaluate { + tasks.named('generateMetadataFileForMavenPublication').configure { + dependsOn(validateNoSnapshotDependencies) + } + tasks.named('generatePomFileForMavenPublication').configure { + dependsOn(validateNoSnapshotDependencies) + } + } +} + +ext { + pomDescription = 'Grails Hibernate 5 Micronaut BOM (Bill of Materials) for Grails projects integrating with Micronaut and Hibernate 5. Layers Hibernate 5 dependency management on top of grails-micronaut-bom; consume as enforcedPlatform.' + pomCustomization = { xml -> + def root = xml.asNode() + + def propertiesNode = root.properties ? root.properties[0] : root.appendNode('properties') + + def depMgmt = root.dependencyManagement?.getAt(0) + def deps = depMgmt?.dependencies?.getAt(0) + if (deps) { + PropertyNameCalculator propertyNameCalculator = new PropertyNameCalculator(combinedPlatforms, combinedDependencies, combinedVersions) + propertyNameCalculator.addForcedGroupPrefix('org.apache.grails.profiles', 'grails-profile') + propertyNameCalculator.addProjects(rootProject.subprojects) + for (String gradleArtifactId : project.ext.gradleBuildProjects) { + propertyNameCalculator.addProject('org.apache.grails.gradle', gradleArtifactId, project.version as String, gradleArtifactId) + } + + Map pomProperties = [:] + deps.dependency.each { dep -> + String groupId = dep.groupId.text().trim() + String artifactId = dep.artifactId.text().trim() + boolean isBom = dep.scope.text().trim() == 'import' + + String inlineVersion = dep.version.text().trim() + if (inlineVersion == 'null') { + inlineVersion = null + } + + if (inlineVersion) { + ExtractedDependencyConstraint extractedConstraint = propertyNameCalculator.calculate(groupId, artifactId, inlineVersion, isBom) + if (extractedConstraint?.versionPropertyReference) { + // use the property reference instead of the hard coded version so that it can be + // overridden by the spring boot dependency management plugin + dep.version[0].value = extractedConstraint.versionPropertyReference + + // Add an entry in the node with the actual version number + pomProperties.put(extractedConstraint.versionPropertyName, inlineVersion) + } + } else if (!inlineVersion) { + throw new GradleException("Dependency $groupId:$artifactId does not have a version.") + } + } + + for (Map.Entry property : pomProperties.entrySet()) { + propertiesNode.appendNode(property.key, property.value) + } + } + } +} diff --git a/grails-doc/src/en/guide/conf/micronaut.adoc b/grails-doc/src/en/guide/conf/micronaut.adoc index be08a4b7628..cf2429985ce 100644 --- a/grails-doc/src/en/guide/conf/micronaut.adoc +++ b/grails-doc/src/en/guide/conf/micronaut.adoc @@ -43,7 +43,24 @@ dependencies { The `grails-micronaut-bom` layers Micronaut-specific dependency overrides on top of `grails-bom` and pins the `io.micronaut.platform:micronaut-platform` version it was built against. Applying it as `enforcedPlatform` makes all of its constraints strictly versioned so that no transitive dependency (including Micronaut's own platform) can override them — there is no need to set a `micronautPlatformVersion` Gradle property. See link:{versionsRef}Grails%20BOM%20Micronaut.html[Grails Micronaut BOM Dependencies] for the full list of managed versions. -When the `grails-micronaut` plugin is present, the Grails Gradle plugin will automatically apply the required annotation processors to your project and validate that `grails-micronaut-bom` is applied as `enforcedPlatform`. The validation fails the build at configuration time with an actionable error if the BOM is missing or applied as plain `platform(...)`. +==== Hibernate-Specific Micronaut BOMs + +If your project targets a specific Hibernate version, use the corresponding Hibernate-specific Micronaut BOM instead of the generic `grails-micronaut-bom`: + +* `org.apache.grails:grails-hibernate5-micronaut-bom` -- Micronaut + Hibernate 5 (the default). + +[source,groovy] +.build.gradle - Hibernate 5 with Micronaut +---- +dependencies { + implementation enforcedPlatform("org.apache.grails:grails-hibernate5-micronaut-bom:$grailsVersion") + implementation 'org.apache.grails:grails-micronaut' +} +---- + +The generic `grails-micronaut-bom` remains available and currently tracks the Hibernate 5 default. If the framework changes its default Hibernate version in the future, `grails-micronaut-bom` will follow the new default while the Hibernate-specific BOMs remain pinned. + +When the `grails-micronaut` plugin is present, the Grails Gradle plugin will automatically apply the required annotation processors to your project and validate that a Micronaut-compatible BOM (`grails-micronaut-bom` or `grails-hibernate5-micronaut-bom`) is applied as `enforcedPlatform`. The validation fails the build at configuration time with an actionable error if no such BOM is applied or it is applied as plain `platform(...)`. ==== Disabling the Micronaut Auto-Setup diff --git a/grails-doc/src/en/guide/upgrading/upgrading80x.adoc b/grails-doc/src/en/guide/upgrading/upgrading80x.adoc index ef5dd4e1ede..ad5424f1373 100644 --- a/grails-doc/src/en/guide/upgrading/upgrading80x.adoc +++ b/grails-doc/src/en/guide/upgrading/upgrading80x.adoc @@ -267,6 +267,25 @@ This affects any code path that goes through Micronaut's HTTP client, filters, o NOTE: The Grails Forge generator enforces this requirement: selecting any Micronaut feature with a JDK version below 25 will fail with `IllegalArgumentException` at generation time. +===== 7.4 Hibernate-Specific Micronaut BOMs + +Grails 8 introduces a new BOM for projects that combine Micronaut integration with a specific Hibernate version: + +* `org.apache.grails:grails-hibernate5-micronaut-bom` -- For Micronaut projects using Hibernate 5. This is the default Micronaut BOM for Hibernate 5 users (analogous to how `grails-micronaut-bom` is the default). Use this when your Micronaut-enabled Grails application targets Hibernate 5. + +This BOM extends `grails-base-bom` and the Micronaut platform directly, and includes the appropriate Hibernate dependency versions alongside the Micronaut-specific overrides (Groovy 5, Spock 2.4, etc.). This ensures no version conflicts when consumed via `enforcedPlatform`. + +[source,groovy] +.build.gradle - Hibernate 5 with Micronaut (default) +---- +dependencies { + implementation enforcedPlatform("org.apache.grails:grails-hibernate5-micronaut-bom:$grailsVersion") + implementation 'org.apache.grails:grails-micronaut' +} +---- + +The existing `grails-micronaut-bom` remains available and is equivalent to `grails-hibernate5-micronaut-bom` for backward compatibility. If the framework changes its default Hibernate version in the future, `grails-micronaut-bom` will track the new default while the Hibernate-specific BOM remains pinned to its version. + ==== 8. Enum Serialization Default Changed As announced in the Grails 7.0.2 deprecation notice, the `SimpleEnumMarshaller` is now the default for JSON and XML enum serialization in Grails 8. diff --git a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy index 4399d3fb184..277982d1f72 100644 --- a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy +++ b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy @@ -464,11 +464,11 @@ ${importStatements} } /** - * Validates that grails-micronaut-bom is applied as an enforcedPlatform when micronaut is used. - * The grails-micronaut-bom layers Micronaut-specific overrides (e.g. javaparser-core) on top - * of grails-bom; without enforcedPlatform, Micronaut's platform would override these versions - * via Gradle's conflict resolution. Regular Grails projects (without Micronaut) should continue - * to use the spring-managed versions via plain platform(:grails-bom). + * Validates that a Micronaut-compatible BOM is applied as an enforcedPlatform when micronaut is used. + * The grails-micronaut-bom (and its hibernate-specific variants) layers Micronaut-specific overrides + * (e.g. javaparser-core) on top of grails-bom; without enforcedPlatform, Micronaut's platform would + * override these versions via Gradle's conflict resolution. Regular Grails projects (without Micronaut) + * should continue to use the spring-managed versions via plain platform(:grails-bom). */ @CompileStatic protected static void validateMicronautBom(Project project) { @@ -477,8 +477,13 @@ ${importStatements} return } + Set validMicronautBoms = [ + 'grails-micronaut-bom', + 'grails-hibernate5-micronaut-bom', + ] as Set + for (Dependency dep : implConfig.dependencies) { - if (dep.name == 'grails-micronaut-bom' && dep instanceof ModuleDependency) { + if (dep.name in validMicronautBoms && dep instanceof ModuleDependency) { Object categoryAttr = ((ModuleDependency) dep).attributes.getAttribute( org.gradle.api.attributes.Category.CATEGORY_ATTRIBUTE ) @@ -489,10 +494,11 @@ ${importStatements} } throw new GradleException( - "Project '${project.name}' uses Micronaut but does not apply grails-micronaut-bom as an enforcedPlatform. " + + "Project '${project.name}' uses Micronaut but does not apply a Micronaut BOM as an enforcedPlatform. " + "Micronaut's platform declares higher versions of javaparser-core and other libraries that would " + - 'override the grails-bom versions via conflict resolution. Change to:\n\n' + - ' implementation enforcedPlatform(project(\':grails-micronaut-bom\'))\n' + 'override the grails-bom versions via conflict resolution. Change to one of:\n\n' + + ' implementation enforcedPlatform("org.apache.grails:grails-micronaut-bom:$grailsVersion")\n' + + ' implementation enforcedPlatform("org.apache.grails:grails-hibernate5-micronaut-bom:$grailsVersion")\n' ) } diff --git a/grails-test-examples/micronaut-hibernate5/build.gradle b/grails-test-examples/micronaut-hibernate5/build.gradle new file mode 100644 index 00000000000..2ef04fb941d --- /dev/null +++ b/grails-test-examples/micronaut-hibernate5/build.gradle @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +plugins { + id 'org.apache.grails.buildsrc.properties' + id 'org.apache.grails.buildsrc.compile' + id 'org.apache.grails.buildsrc.dependency-validator' +} + +version = '0.1' +group = 'micronaut.hibernate5' + +apply plugin: 'org.apache.grails.gradle.grails-web' +apply plugin: 'cloud.wondrify.asset-pipeline' +apply plugin: 'org.apache.grails.gradle.grails-gsp' + +dependencies { + implementation enforcedPlatform(project(':grails-hibernate5-micronaut-bom')) + + implementation 'io.micronaut:micronaut-http-client' + implementation 'io.micronaut.serde:micronaut-serde-jackson' + implementation 'org.apache.grails:grails-dependencies-starter-web' + implementation 'org.apache.grails:grails-data-hibernate5' + implementation 'org.apache.grails:grails-micronaut' + + annotationProcessor enforcedPlatform(project(':grails-hibernate5-micronaut-bom')) + annotationProcessor 'io.micronaut:micronaut-inject-java' + annotationProcessor 'jakarta.annotation:jakarta.annotation-api' + + testAndDevelopmentOnly enforcedPlatform(project(':grails-hibernate5-micronaut-bom')) + testAndDevelopmentOnly 'org.apache.grails:grails-dependencies-assets' + + runtimeOnly 'cloud.wondrify:asset-pipeline-grails' + runtimeOnly 'com.h2database:h2' + runtimeOnly 'org.apache.tomcat:tomcat-jdbc' + + testImplementation 'org.apache.grails:grails-dependencies-test' + + integrationTestImplementation testFixtures('org.apache.grails:grails-geb') +} + +apply { + from rootProject.layout.projectDirectory.file('gradle/functional-test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/test-webjar-asset-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/grails-extension-gradle-config.gradle') +} diff --git a/grails-test-examples/micronaut-hibernate5/grails-app/conf/application.yml b/grails-test-examples/micronaut-hibernate5/grails-app/conf/application.yml new file mode 100644 index 00000000000..1100bfd590b --- /dev/null +++ b/grails-test-examples/micronaut-hibernate5/grails-app/conf/application.yml @@ -0,0 +1,74 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +grails: + profile: web + codegen: + defaultPackage: micronaut.hibernate5 +info: + app: + name: '@info.app.name@' + version: '@info.app.version@' + grailsVersion: '@info.app.grailsVersion@' +app: + name: test-micronaut-hibernate5-app + +--- +grails: + mime: + types: + all: '*/*' + html: + - text/html + - application/xhtml+xml + json: + - application/json + - text/json + xml: + - text/xml + - application/xml + views: + gsp: + encoding: UTF-8 + htmlcodec: xml + codecs: + scriptlet: html +--- +hibernate: + cache: + queries: false + use_second_level_cache: false + use_query_cache: false +dataSource: + pooled: true + jmxExport: true + driverClassName: org.h2.Driver + username: sa + password: '' + +environments: + development: + dataSource: + dbCreate: create-drop + url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE + test: + dataSource: + dbCreate: update + url: jdbc:h2:mem:testDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE + production: + dataSource: + dbCreate: none + url: jdbc:h2:./prodDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE diff --git a/grails-test-examples/micronaut-hibernate5/grails-app/conf/logback.xml b/grails-test-examples/micronaut-hibernate5/grails-app/conf/logback.xml new file mode 100644 index 00000000000..11f34868ac6 --- /dev/null +++ b/grails-test-examples/micronaut-hibernate5/grails-app/conf/logback.xml @@ -0,0 +1,37 @@ + + + + + + + + + + UTF-8 + %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wex + + + + + + + \ No newline at end of file diff --git a/grails-test-examples/micronaut-hibernate5/grails-app/controllers/micronaut/hibernate5/UrlMappings.groovy b/grails-test-examples/micronaut-hibernate5/grails-app/controllers/micronaut/hibernate5/UrlMappings.groovy new file mode 100644 index 00000000000..2758d738e57 --- /dev/null +++ b/grails-test-examples/micronaut-hibernate5/grails-app/controllers/micronaut/hibernate5/UrlMappings.groovy @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package micronaut.hibernate5 + +class UrlMappings { + + static mappings = { + "/$controller/$action?/$id?(.$format)?"{ + constraints { + } + } + + "/"(view: "/index") + } +} diff --git a/grails-test-examples/micronaut-hibernate5/grails-app/init/micronaut/hibernate5/Application.groovy b/grails-test-examples/micronaut-hibernate5/grails-app/init/micronaut/hibernate5/Application.groovy new file mode 100644 index 00000000000..99100b79039 --- /dev/null +++ b/grails-test-examples/micronaut-hibernate5/grails-app/init/micronaut/hibernate5/Application.groovy @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package micronaut.hibernate5 + +import grails.boot.GrailsApp +import grails.boot.config.GrailsAutoConfiguration +import groovy.transform.CompileStatic +import io.micronaut.spring.boot.starter.EnableMicronaut + +@CompileStatic +@EnableMicronaut +class Application extends GrailsAutoConfiguration { + static void main(String[] args) { + GrailsApp.run(Application, args) + } +} diff --git a/grails-test-examples/micronaut-hibernate5/grails-app/views/index.gsp b/grails-test-examples/micronaut-hibernate5/grails-app/views/index.gsp new file mode 100644 index 00000000000..1c032d67936 --- /dev/null +++ b/grails-test-examples/micronaut-hibernate5/grails-app/views/index.gsp @@ -0,0 +1,25 @@ +<%-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--%> + + + + Micronaut Hibernate 5 Test App + + +

Micronaut Hibernate 5 Test Application

+ + diff --git a/grails-test-examples/micronaut-hibernate5/src/integration-test/groovy/micronaut/hibernate5/ApplicationStartupSpec.groovy b/grails-test-examples/micronaut-hibernate5/src/integration-test/groovy/micronaut/hibernate5/ApplicationStartupSpec.groovy new file mode 100644 index 00000000000..4fd91a3bc84 --- /dev/null +++ b/grails-test-examples/micronaut-hibernate5/src/integration-test/groovy/micronaut/hibernate5/ApplicationStartupSpec.groovy @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package micronaut.hibernate5 + +import grails.plugin.geb.ContainerGebSpec +import grails.testing.mixin.integration.Integration + +@Integration +class ApplicationStartupSpec extends ContainerGebSpec { + + void "test the application starts and the home page renders"() { + when: 'The home page is visited' + go '/' + + then: 'The page loads successfully' + title == 'Micronaut Hibernate 5 Test App' + driver.currentUrl.contains('/') + } +} diff --git a/settings.gradle b/settings.gradle index 969f1c7f65c..cf9363143c2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -511,14 +511,18 @@ includeBuild('./build-logic') { if (!skipMicronautProjects) { include( 'grails-micronaut-bom', + 'grails-hibernate5-micronaut-bom', 'grails-micronaut', 'grails-test-examples-issue-11767', 'grails-test-examples-micronaut', 'grails-test-examples-micronaut-groovy-only', + 'grails-test-examples-micronaut-hibernate5', 'grails-test-examples-plugins-issue-11767', 'grails-test-examples-plugins-micronaut-singleton', ) project(':grails-micronaut-bom').projectDir = file('grails-bom/micronaut') + project(':grails-hibernate5-micronaut-bom').projectDir = file('grails-bom/hibernate5-micronaut') + project(':grails-test-examples-micronaut-hibernate5').projectDir = file('grails-test-examples/micronaut-hibernate5') project(':grails-test-examples-issue-11767').projectDir = file('grails-test-examples/issue-11767') project(':grails-test-examples-micronaut').projectDir = file('grails-test-examples/micronaut') project(':grails-test-examples-micronaut-groovy-only').projectDir = file('grails-test-examples/micronaut-groovy-only')