From 09fafcab5376302e1ca7d294e4f04c87d6b216dd Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 11 Jul 2025 21:37:22 -0400 Subject: [PATCH 01/22] fix: update type to remove CompileDynamic --- grails-core/src/main/groovy/grails/boot/GrailsApp.groovy | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy b/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy index a4ab18592e1..624b26eaa13 100644 --- a/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy +++ b/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy @@ -21,7 +21,6 @@ package grails.boot import java.util.concurrent.ConcurrentLinkedQueue -import groovy.transform.CompileDynamic import groovy.transform.CompileStatic import groovy.util.logging.Slf4j import org.codehaus.groovy.control.CompilationFailedException @@ -145,7 +144,6 @@ class GrailsApp extends SpringApplication { configuredEnvironment = environment } - @CompileDynamic // TODO: Report Groovy VerifierError protected void enableDevelopmentModeWatch(Environment environment, ConfigurableApplicationContext applicationContext, String... args) { def location = environment.getReloadLocation() @@ -236,7 +234,7 @@ class GrailsApp extends SpringApplication { while (isDevelopmentModeActive()) { // Workaround for some IDE / OS combos - 2 events (new + update) for the same file - def uniqueChangedFiles = changedFiles as Set + def uniqueChangedFiles = changedFiles as Set def i = uniqueChangedFiles.size() try { From d1e9e7b7d747cbbbc1eaa1b9ae6a887b94c08359 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sat, 12 Jul 2025 20:08:36 -0400 Subject: [PATCH 02/22] chore: update minimum grails version --- .../plugins/web/async/ControllersAsyncGrailsPlugin.groovy | 2 +- .../main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy | 2 +- .../groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy | 2 +- .../groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy | 2 +- .../org/grails/plugins/events/EventBusGrailsPlugin.groovy | 2 +- .../src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy | 2 +- .../grails/plugin/scaffolding/ScaffoldingGrailsPlugin.groovy | 2 +- .../src/main/groovy/issue11005/Issue11005GrailsPlugin.groovy | 2 +- .../src/main/groovy/loadfirst/LoadfirstGrailsPlugin.groovy | 2 +- .../src/main/groovy/loadsecond/LoadsecondGrailsPlugin.groovy | 2 +- .../groovy/grails/plugin/json/view/JsonViewGrailsPlugin.groovy | 2 +- .../grails/plugin/markup/view/MarkupViewGrailsPlugin.groovy | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/ControllersAsyncGrailsPlugin.groovy b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/ControllersAsyncGrailsPlugin.groovy index 1e6edee50bb..63fc49a3ed7 100644 --- a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/ControllersAsyncGrailsPlugin.groovy +++ b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/ControllersAsyncGrailsPlugin.groovy @@ -31,7 +31,7 @@ import org.grails.plugins.web.async.spring.PromiseFactoryBean */ class ControllersAsyncGrailsPlugin extends Plugin { - def grailsVersion = '7.0.0 > *' + def grailsVersion = '7.0.0-SNAPSHOT > *' def loadAfter = ['controllers'] Closure doWithSpring() { { -> diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy b/grails-cache/src/main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy index 70bd287ece8..507cdb89477 100644 --- a/grails-cache/src/main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy +++ b/grails-cache/src/main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy @@ -30,7 +30,7 @@ import org.grails.plugin.cache.GrailsCacheManager @Slf4j class CacheGrailsPlugin extends Plugin { - def grailsVersion = '7.0.0 > *' + def grailsVersion = '7.0.0-SNAPSHOT > *' def observe = ['controllers', 'services'] def loadAfter = ['controllers', 'services'] def authorEmail = 'brownj@objectcomputing.com' diff --git a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy index c596d4949d9..b36df9c2a44 100644 --- a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy +++ b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy @@ -47,7 +47,7 @@ class HibernateGrailsPlugin extends Plugin { public static final String DEFAULT_DATA_SOURCE_NAME = HibernateDatastoreSpringInitializer.DEFAULT_DATA_SOURCE_NAME - def grailsVersion = '7.0.0 > *' + def grailsVersion = '7.0.0-SNAPSHOT > *' def author = 'Grails Core Team' def title = 'Hibernate 5 for Grails' diff --git a/grails-data-mongodb/grails-plugin/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy b/grails-data-mongodb/grails-plugin/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy index f4a5f86f83c..24d7a530e01 100644 --- a/grails-data-mongodb/grails-plugin/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy +++ b/grails-data-mongodb/grails-plugin/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy @@ -41,7 +41,7 @@ class MongodbGrailsPlugin extends Plugin { def organization = [name: 'Grails', url: 'https://grails.apache.org/'] def issueManagement = [system: 'Github', url: 'https://github.com/apache/grails-core/issues'] def scm = [url: 'https://github.com/apache/grails-core'] - def grailsVersion = '7.0.0 > *' + def grailsVersion = '7.0.0-SNAPSHOT > *' def observe = ['services', 'domainClass'] def loadAfter = ['domainClass', 'hibernate', 'hibernate5', 'hibernate6', 'services'] def title = 'GORM MongoDB' diff --git a/grails-events/plugin/src/main/groovy/org/grails/plugins/events/EventBusGrailsPlugin.groovy b/grails-events/plugin/src/main/groovy/org/grails/plugins/events/EventBusGrailsPlugin.groovy index ea16599d1fe..82e1f5d566a 100644 --- a/grails-events/plugin/src/main/groovy/org/grails/plugins/events/EventBusGrailsPlugin.groovy +++ b/grails-events/plugin/src/main/groovy/org/grails/plugins/events/EventBusGrailsPlugin.groovy @@ -35,7 +35,7 @@ import org.grails.events.spring.SpringEventTranslator */ class EventBusGrailsPlugin extends Plugin { - def grailsVersion = '7.0.0 > *' + def grailsVersion = '7.0.0-SNAPSHOT > *' /** * Whether to translate GORM events into reactor events diff --git a/grails-geb/src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy b/grails-geb/src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy index a690a160ddc..fdb81483bf4 100644 --- a/grails-geb/src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy +++ b/grails-geb/src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy @@ -28,7 +28,7 @@ import grails.plugins.metadata.PluginSource @CompileStatic class GebGrailsPlugin extends Plugin { - def grailsVersion = '7.0.0 > *' + def grailsVersion = '7.0.0-SNAPSHOT > *' def pluginExcludes = [] def title = 'Grails Geb Plugin' def author = 'Graeme Rocher' diff --git a/grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/ScaffoldingGrailsPlugin.groovy b/grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/ScaffoldingGrailsPlugin.groovy index a5b4e084631..d9d721a3798 100644 --- a/grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/ScaffoldingGrailsPlugin.groovy +++ b/grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/ScaffoldingGrailsPlugin.groovy @@ -26,7 +26,7 @@ import grails.util.Metadata class ScaffoldingGrailsPlugin extends Plugin { // the version or versions of Grails the plugin is designed for - def grailsVersion = '4.0.0.BUILD-SNAPSHOT > *' + def grailsVersion = '7.0.0-SNAPSHOT > *' // resources that are excluded from plugin packaging def pluginExcludes = [ 'grails-app/views/error.gsp' diff --git a/grails-test-examples/plugins/issue11005/src/main/groovy/issue11005/Issue11005GrailsPlugin.groovy b/grails-test-examples/plugins/issue11005/src/main/groovy/issue11005/Issue11005GrailsPlugin.groovy index 0f443f1e49e..ee3e7b4c4d1 100644 --- a/grails-test-examples/plugins/issue11005/src/main/groovy/issue11005/Issue11005GrailsPlugin.groovy +++ b/grails-test-examples/plugins/issue11005/src/main/groovy/issue11005/Issue11005GrailsPlugin.groovy @@ -24,7 +24,7 @@ import grails.plugins.* class Issue11005GrailsPlugin extends Plugin { // the version or versions of Grails the plugin is designed for - def grailsVersion = "3.3.6 > *" + def grailsVersion = '7.0.0-SNAPSHOT > *' // resources that are excluded from plugin packaging def pluginExcludes = [ "grails-app/views/error.gsp" diff --git a/grails-test-examples/plugins/loadfirst/src/main/groovy/loadfirst/LoadfirstGrailsPlugin.groovy b/grails-test-examples/plugins/loadfirst/src/main/groovy/loadfirst/LoadfirstGrailsPlugin.groovy index 4f1ae6013fe..518005a70fe 100644 --- a/grails-test-examples/plugins/loadfirst/src/main/groovy/loadfirst/LoadfirstGrailsPlugin.groovy +++ b/grails-test-examples/plugins/loadfirst/src/main/groovy/loadfirst/LoadfirstGrailsPlugin.groovy @@ -24,7 +24,7 @@ import grails.plugins.* class LoadfirstGrailsPlugin extends Plugin { // the version or versions of Grails the plugin is designed for - def grailsVersion = "3.0.0.BUILD-SNAPSHOT > *" + def grailsVersion = '7.0.0.SNAPSHOT > *' // resources that are excluded from plugin packaging def pluginExcludes = [ "grails-app/views/error.gsp" diff --git a/grails-test-examples/plugins/loadsecond/src/main/groovy/loadsecond/LoadsecondGrailsPlugin.groovy b/grails-test-examples/plugins/loadsecond/src/main/groovy/loadsecond/LoadsecondGrailsPlugin.groovy index ad3d579bef8..ceedbf926a7 100644 --- a/grails-test-examples/plugins/loadsecond/src/main/groovy/loadsecond/LoadsecondGrailsPlugin.groovy +++ b/grails-test-examples/plugins/loadsecond/src/main/groovy/loadsecond/LoadsecondGrailsPlugin.groovy @@ -24,7 +24,7 @@ import grails.plugins.* class LoadsecondGrailsPlugin extends Plugin { // the version or versions of Grails the plugin is designed for - def grailsVersion = "3.0.0.BUILD-SNAPSHOT > *" + def grailsVersion = '7.0.0.SNAPSHOT > *' // resources that are excluded from plugin packaging def pluginExcludes = [ "grails-app/views/error.gsp" diff --git a/grails-views-gson/src/main/groovy/grails/plugin/json/view/JsonViewGrailsPlugin.groovy b/grails-views-gson/src/main/groovy/grails/plugin/json/view/JsonViewGrailsPlugin.groovy index aebdb30ef70..c777908b466 100644 --- a/grails-views-gson/src/main/groovy/grails/plugin/json/view/JsonViewGrailsPlugin.groovy +++ b/grails-views-gson/src/main/groovy/grails/plugin/json/view/JsonViewGrailsPlugin.groovy @@ -28,7 +28,7 @@ import grails.views.resolve.PluginAwareTemplateResolver class JsonViewGrailsPlugin extends Plugin { // the version or versions of Grails the plugin is designed for - def grailsVersion = '7.0.0 > *' + def grailsVersion = '7.0.0-SNAPSHOT > *' def title = 'JSON Views' // Headline display name of the plugin def author = 'Graeme Rocher' diff --git a/grails-views-markup/src/main/groovy/grails/plugin/markup/view/MarkupViewGrailsPlugin.groovy b/grails-views-markup/src/main/groovy/grails/plugin/markup/view/MarkupViewGrailsPlugin.groovy index 776fd869134..612f4357eb5 100644 --- a/grails-views-markup/src/main/groovy/grails/plugin/markup/view/MarkupViewGrailsPlugin.groovy +++ b/grails-views-markup/src/main/groovy/grails/plugin/markup/view/MarkupViewGrailsPlugin.groovy @@ -33,7 +33,7 @@ import grails.views.resolve.PluginAwareTemplateResolver class MarkupViewGrailsPlugin extends Plugin { // the version or versions of Grails the plugin is designed for - def grailsVersion = '7.0.0 > *' + def grailsVersion = '7.0.0-SNAPSHOT > *' def title = 'Markup Views' // Headline display name of the plugin def author = 'Graeme Rocher' From 7e6cb8378535a442566b0cdb451d3771ca1358df Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Tue, 5 Aug 2025 13:18:17 -0400 Subject: [PATCH 03/22] ci: re-enable sitemesh3 tests --- .../src/integration-test/groovy/EndToEndSpec.groovy | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/grails-test-examples/gsp-sitemesh3/src/integration-test/groovy/EndToEndSpec.groovy b/grails-test-examples/gsp-sitemesh3/src/integration-test/groovy/EndToEndSpec.groovy index df9dba72322..76810804398 100644 --- a/grails-test-examples/gsp-sitemesh3/src/integration-test/groovy/EndToEndSpec.groovy +++ b/grails-test-examples/gsp-sitemesh3/src/integration-test/groovy/EndToEndSpec.groovy @@ -24,6 +24,7 @@ import spock.lang.PendingFeature @Integration class EndToEndSpec extends ContainerGebSpec { + @PendingFeature def 'simple layout'() { when: go('endToEnd/simpleLayout') @@ -34,6 +35,7 @@ class EndToEndSpec extends ContainerGebSpec { """ } + @PendingFeature def 'title in subtemplate'() { when: go('endToEnd/titleInSubtemplate') @@ -56,6 +58,7 @@ class EndToEndSpec extends ContainerGebSpec { """ } + @PendingFeature def 'parameters'() { when: go('endToEnd/parameters') @@ -64,6 +67,7 @@ class EndToEndSpec extends ContainerGebSpec { pageSource == """

pageProperty: here!

""" } + @PendingFeature def 'parameters with logic'() { when: go('endToEnd/parametersWithLogic') @@ -72,6 +76,7 @@ class EndToEndSpec extends ContainerGebSpec { pageSource == "good" } + @PendingFeature def 'multiline title'() { when: go('endToEnd/multilineTitle') From 9d73131e49f60e07161a4e084dcc1e61e57ab987 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sat, 12 Jul 2025 20:50:44 -0400 Subject: [PATCH 04/22] Make scripts executable --- gradle.properties | 8 +- gradle/publish-root-config.gradle | 1 + grails-dependencies/starter-web/build.gradle | 2 +- .../plugin/core/GrailsGradlePlugin.groovy | 27 +++--- .../gsp/GroovyPageForkCompileTask.groovy | 1 + grails-micronaut/build.gradle | 84 +++++++++++++++++++ .../GrailsMicronautGrailsPlugin.groovy | 74 ++++++++++++++++ grails-test-examples/app1/build.gradle | 2 +- .../async-events-pubsub-demo/build.gradle | 2 +- .../hibernate5/issue450/build.gradle | 2 +- grails-test-examples/issue-11102/build.gradle | 2 +- grails-test-examples/issue-11767/build.gradle | 29 ++----- .../init/issue11767/app/Application.groovy | 2 + .../issue11767/app/ConfigLoadingSpec.groovy | 4 +- .../issue-views-182/build.gradle | 2 +- grails-test-examples/micronaut/build.gradle | 69 ++------------- .../init/micronaut/Application.groovy | 3 +- .../init/micronaut/BootStrap.groovy | 2 + .../micronaut/BeanInjectionServiceSpec.groovy | 4 +- .../build.gradle | 6 +- .../grails-app/conf/plugin.yml | 0 .../init/issue11767/plugin/Application.groovy | 2 +- .../plugin/MyPluginGrailsPlugin.groovy | 3 +- .../plugin/PluginGroovyMicronautBean.groovy | 0 .../plugin/PluginGroovySpringBean.groovy | 0 .../plugin/PluginJavaMicronautBean.java | 0 .../views-functional-tests/build.gradle | 4 +- settings.gradle | 17 ++-- 28 files changed, 229 insertions(+), 123 deletions(-) create mode 100644 grails-micronaut/build.gradle create mode 100644 grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy rename grails-test-examples/plugins/{issue-11767-plugin => issue-11767}/build.gradle (90%) rename grails-test-examples/plugins/{issue-11767-plugin => issue-11767}/grails-app/conf/plugin.yml (100%) rename grails-test-examples/plugins/{issue-11767-plugin => issue-11767}/grails-app/init/issue11767/plugin/Application.groovy (96%) rename grails-test-examples/plugins/{issue-11767-plugin => issue-11767}/src/main/groovy/issue11767/plugin/MyPluginGrailsPlugin.groovy (97%) rename grails-test-examples/plugins/{issue-11767-plugin => issue-11767}/src/main/groovy/issue11767/plugin/PluginGroovyMicronautBean.groovy (100%) rename grails-test-examples/plugins/{issue-11767-plugin => issue-11767}/src/main/groovy/issue11767/plugin/PluginGroovySpringBean.groovy (100%) rename grails-test-examples/plugins/{issue-11767-plugin => issue-11767}/src/main/java/issue11767/plugin/PluginJavaMicronautBean.java (100%) diff --git a/gradle.properties b/gradle.properties index 5f4e60bd819..6ab9faeca1d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -49,11 +49,15 @@ apacheRatVersion=0.8.1 gradleChecksumPluginVersion=1.4.0 gradleLicensePluginVersion=0.16.1 +# micronaut libraries not in the bom due to the potential for spring mismatches +micronautPlatformVersion=4.9.2 + # Libraries only specific to test apps, these should not be exposed grailsSpringSecurityVersion=7.0.0-SNAPSHOT jbossTransactionApiVersion=2.0.0.Final -micronautVersion=4.9.10 -micronautSerdeJacksonVersion=2.15.1 +# note: we do not import the micronaut bom in our tests to avoid spring version mismatches +micronautHttpClientVersion=4.9.9 +micronautSerdeJacksonVersion=2.11.0 # build dependencies for code quality checks checkstyleVersion=11.0.0 diff --git a/gradle/publish-root-config.gradle b/gradle/publish-root-config.gradle index 149999c7446..1a47399dcbf 100644 --- a/gradle/publish-root-config.gradle +++ b/gradle/publish-root-config.gradle @@ -65,6 +65,7 @@ def publishedProjects = [ 'grails-interceptors', 'grails-logging', 'grails-mimetypes', + 'grails-micronaut', 'grails-rest-transforms', 'grails-scaffolding', 'grails-services', diff --git a/grails-dependencies/starter-web/build.gradle b/grails-dependencies/starter-web/build.gradle index fec01d0cde0..e12252310f7 100644 --- a/grails-dependencies/starter-web/build.gradle +++ b/grails-dependencies/starter-web/build.gradle @@ -47,7 +47,7 @@ def configurations = [ ':grails-gsp', ':grails-i18n', ':grails-interceptors', - ':grails-layout', // layout will be the default because it's fully functional while sitemesh3 still has issues + System.getenv('SITEMESH3_TESTING_ENABLED') == 'true' ? ':grails-sitemesh3' : ':grails-layout', ':grails-logging', ':grails-rest-transforms', ':grails-services', 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 a8a86a6465a..f7f358d7522 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 @@ -27,7 +27,6 @@ import io.spring.gradle.dependencymanagement.DependencyManagementPlugin import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension import org.apache.tools.ant.filters.EscapeUnicode import org.apache.tools.ant.filters.ReplaceTokens -import org.gradle.api.Action import org.gradle.api.GradleException import org.gradle.api.NamedDomainObjectProvider import org.gradle.api.Plugin @@ -386,17 +385,21 @@ class GrailsGradlePlugin extends GroovyPlugin { @CompileStatic protected void configureMicronaut(Project project) { - final String micronautVersion = project.properties['micronautVersion'] - if (micronautVersion) { - project.configurations.configureEach({ Configuration configuration -> - configuration.resolutionStrategy.eachDependency({ DependencyResolveDetails details -> - String dependencyName = details.requested.name - String group = details.requested.group - if (group == 'io.micronaut' && dependencyName.startsWith('micronaut')) { - details.useVersion(micronautVersion) - } - } as Action) - } as Action) + project.afterEvaluate { + boolean micronautEnabled = project.getConfigurations().getByName("implementation").getDependencies().findAll { Dependency dep -> dep.group == 'org.apache.grails' && dep.name == 'grails-micronaut' } as boolean + if (!micronautEnabled) { + return + } + project.logger.lifecycle('Micronaut Support Detected for {} - adding annotation processor dependencies for Micronaut', project.path) + + final String micronautPlatformVersion = project.properties['micronautPlatformVersion'] + if (!micronautPlatformVersion) { + throw new GradleException("`micronautPlatformVersion` property must be set to use the Grails Micronaut plugin.") + } + + project.getDependencies().add('annotationProcessor', project.dependencies.platform("io.micronaut.platform:micronaut-platform:$micronautPlatformVersion")) + project.getDependencies().add('annotationProcessor', 'io.micronaut:micronaut-inject-java') + project.getDependencies().add('annotationProcessor', 'jakarta.annotation:jakarta.annotation-api') } } diff --git a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/views/gsp/GroovyPageForkCompileTask.groovy b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/views/gsp/GroovyPageForkCompileTask.groovy index c9f181895d2..65dec308d0c 100644 --- a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/views/gsp/GroovyPageForkCompileTask.groovy +++ b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/views/gsp/GroovyPageForkCompileTask.groovy @@ -145,6 +145,7 @@ abstract class GroovyPageForkCompileTask extends AbstractCompile { void execute(JavaExecSpec javaExecSpec) { javaExecSpec.mainClass.set(getCompilerName()) javaExecSpec.setClasspath(getClasspath()) + //javaExecSpec.setJvmArgs(['-Xmx2g', '-Xdebug', '-Xnoagent','-Djava.compiler=NONE', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005']) def jvmArgs = compileOptions.forkOptions.jvmArgs if (jvmArgs) { diff --git a/grails-micronaut/build.gradle b/grails-micronaut/build.gradle new file mode 100644 index 00000000000..69cc35d10cf --- /dev/null +++ b/grails-micronaut/build.gradle @@ -0,0 +1,84 @@ +/* + * 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 'groovy' + id 'java-library' + id 'project-report' +} + +version = projectVersion +group = 'org.apache.grails' + +// force a local build version for debugging +//project.configurations.configureEach({ Configuration configuration -> +// configuration.resolutionStrategy.eachDependency({ DependencyResolveDetails details -> +// String dependencyName = details.requested.name +// String group = details.requested.group +// if (group == 'io.micronaut' && dependencyName.startsWith('micronaut-core-processor')) { +// logger.lifecycle("Forcing Micronaut Core Processor version to 4.9.99 for Grails Micronaut plugin") +// details.useVersion('4.9.99') +// } +// } as Action) +//} as Action) + +dependencies { + annotationProcessor platform(project(':grails-bom')) + annotationProcessor platform("io.micronaut.platform:micronaut-platform:$micronautPlatformVersion") + annotationProcessor 'io.micronaut:micronaut-inject-java' + annotationProcessor 'jakarta.annotation:jakarta.annotation-api' + + compileOnlyApi platform("io.micronaut.platform:micronaut-platform:$micronautPlatformVersion") + compileOnlyApi 'io.micronaut:micronaut-inject-groovy' + compileOnlyApi 'io.micronaut:micronaut-inject-java' + + api platform("io.micronaut.platform:micronaut-platform:$micronautPlatformVersion") + api 'io.micronaut.spring:micronaut-spring-boot-starter' + api "io.micronaut.spring:micronaut-spring-context", { + // required to load the micronaut environment with plugin configuration + exclude group: "org.slf4j", module: "slf4j-simple" + } + api "io.micronaut.cache:micronaut-cache-core", { + exclude group:"org.slf4j", module: "slf4j-simple" + } + + implementation platform(project(':grails-bom')) + compileOnly project(':grails-core') + + // Logging + compileOnly 'org.slf4j:slf4j-api' + compileOnly 'org.slf4j:jcl-over-slf4j' + + // Testing + testImplementation platform(project(':grails-bom')) + testImplementation 'org.slf4j:slf4j-simple' + testImplementation('org.spockframework:spock-core') { transitive = false } + + // Required by Spock's Mocking + testRuntimeOnly 'net.bytebuddy:byte-buddy' + testImplementation 'org.objenesis:objenesis' +} + +apply { + // java-configuration must be applied first since tasks are now lazy registered + from rootProject.layout.projectDirectory.file('gradle/java-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') +} \ No newline at end of file diff --git a/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy new file mode 100644 index 00000000000..7aa6aeeb287 --- /dev/null +++ b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy @@ -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. + */ + +package org.apache.grails.micronaut + +import grails.plugins.GrailsPlugin +import grails.plugins.GrailsPluginManager +import grails.plugins.Plugin +import groovy.util.logging.Slf4j +import io.micronaut.context.ConfigurableApplicationContext +import io.micronaut.context.env.AbstractPropertySourceLoader +import io.micronaut.context.env.Environment +import io.micronaut.context.env.PropertySource + +@Slf4j +class GrailsMicronautGrailsPlugin extends Plugin { + + def grailsVersion = '7.0.0-SNAPSHOT > *' + def title = 'Grails Micronaut Plugin' + + @Override + void doWithApplicationContext() { + String[] beanNames = applicationContext.getBeanNamesForType(GrailsPluginManager) + GrailsPluginManager pluginManagerFromContext = beanNames.length ? + applicationContext.getBean(GrailsPluginManager) : + null + + if (!pluginManagerFromContext && !pluginManager) { + // No plugin managers to search for plugin configurations + return + } + + if (!applicationContext.containsBean('micronautApplicationContext')) { + throw new IllegalStateException("A Micronaut Application Context should exist prior to the loading of the Grails Micronaut plugin.") + } + + ConfigurableApplicationContext micronautContext = applicationContext.getBean('micronautApplicationContext', ConfigurableApplicationContext) + Environment micronautEnv = micronautContext.getEnvironment() + + log.debug("Loading configurations from the plugins to the parent Micronaut context") + final GrailsPlugin[] plugins = pluginManager.allPlugins + final GrailsPlugin[] pluginsFromContext = pluginManagerFromContext ? pluginManagerFromContext.allPlugins : new GrailsPlugin[]{} + Integer priority = AbstractPropertySourceLoader.DEFAULT_POSITION + [plugins, pluginsFromContext].each { GrailsPlugin[] pluginsToProcess -> + Arrays.stream(pluginsToProcess) + .filter({ GrailsPlugin plugin -> plugin.propertySource != null }) + .forEach({ GrailsPlugin plugin -> + if (log.isDebugEnabled()) { + log.debug("Loading configurations from {} plugin to the parent Micronaut context", plugin.name) + } + // If invoking the source as `.source`, the NavigableMapPropertySource will return null, while invoking the getter, it will return the correct value + micronautEnv.addPropertySource(PropertySource.of("grails.plugins.$plugin.name", (Map) plugin.propertySource.getSource(), --priority)) + }) + } + micronautEnv.refresh() +// applicationContext.setParent(parentApplicationContext) + } +} diff --git a/grails-test-examples/app1/build.gradle b/grails-test-examples/app1/build.gradle index fa205be7e65..5bc62da0c78 100644 --- a/grails-test-examples/app1/build.gradle +++ b/grails-test-examples/app1/build.gradle @@ -55,7 +55,7 @@ dependencies { testImplementation 'org.apache.grails:grails-testing-support-datamapping' console 'org.apache.grails:grails-console' - testImplementation "io.micronaut:micronaut-http-client:$micronautVersion" + testImplementation "io.micronaut:micronaut-http-client:$micronautHttpClientVersion" testImplementation "io.micronaut.serde:micronaut-serde-jackson:$micronautSerdeJacksonVersion" implementation project(':grails-test-examples-plugins-loadfirst') diff --git a/grails-test-examples/async-events-pubsub-demo/build.gradle b/grails-test-examples/async-events-pubsub-demo/build.gradle index 81d03b7781f..e251d0a55fe 100644 --- a/grails-test-examples/async-events-pubsub-demo/build.gradle +++ b/grails-test-examples/async-events-pubsub-demo/build.gradle @@ -61,7 +61,7 @@ dependencies { runtimeOnly 'com.zaxxer:HikariCP' testImplementation "io.micronaut.serde:micronaut-serde-jackson:$micronautSerdeJacksonVersion" - testImplementation "io.micronaut:micronaut-http-client:$micronautVersion" + testImplementation "io.micronaut:micronaut-http-client:$micronautHttpClientVersion" testImplementation 'org.apache.grails:grails-testing-support-web' } diff --git a/grails-test-examples/hibernate5/issue450/build.gradle b/grails-test-examples/hibernate5/issue450/build.gradle index 23ce7ad3f55..3ff6b9847d2 100644 --- a/grails-test-examples/hibernate5/issue450/build.gradle +++ b/grails-test-examples/hibernate5/issue450/build.gradle @@ -56,7 +56,7 @@ dependencies { runtimeOnly 'org.springframework.boot:spring-boot-starter-logging' runtimeOnly 'org.springframework.boot:spring-boot-starter-tomcat' - integrationTestImplementation "io.micronaut:micronaut-http-client:$micronautVersion" + integrationTestImplementation "io.micronaut:micronaut-http-client:$micronautHttpClientVersion" integrationTestImplementation 'org.apache.grails.testing:grails-testing-support-core' integrationTestImplementation 'org.spockframework:spock-core' diff --git a/grails-test-examples/issue-11102/build.gradle b/grails-test-examples/issue-11102/build.gradle index 8a2c325d323..ec92fe30b30 100644 --- a/grails-test-examples/issue-11102/build.gradle +++ b/grails-test-examples/issue-11102/build.gradle @@ -69,7 +69,7 @@ dependencies { testImplementation 'org.apache.grails:grails-testing-support-web' testImplementation 'org.apache.grails:grails-testing-support-datamapping' - testImplementation "io.micronaut:micronaut-http-client:$micronautVersion" + testImplementation "io.micronaut:micronaut-http-client:$micronautHttpClientVersion" testImplementation "io.micronaut.serde:micronaut-serde-jackson:$micronautSerdeJacksonVersion" integrationTestImplementation testFixtures("org.apache.grails:grails-geb") diff --git a/grails-test-examples/issue-11767/build.gradle b/grails-test-examples/issue-11767/build.gradle index 7626b918523..fa4e9657e4f 100644 --- a/grails-test-examples/issue-11767/build.gradle +++ b/grails-test-examples/issue-11767/build.gradle @@ -17,6 +17,7 @@ * under the License. */ +version = '0.1' group = 'issue11767.app' apply plugin: 'org.apache.grails.gradle.grails-web' @@ -24,31 +25,17 @@ apply plugin: 'org.apache.grails.gradle.grails-web' dependencies { implementation platform(project(':grails-bom')) - implementation project(':issue-11767-plugin') + implementation 'org.apache.grails:grails-dependencies-starter-web' + implementation 'org.apache.grails:grails-micronaut' + implementation project(':grails-test-examples-plugins-issue-11767') - implementation 'org.apache.grails:grails-core' - implementation 'org.apache.grails:grails-logging' - implementation 'org.apache.grails:grails-url-mappings' - implementation 'org.springframework.boot:spring-boot-starter-tomcat' - if(System.getenv('SITEMESH3_TESTING_ENABLED') == 'true') { - implementation 'org.apache.grails:grails-sitemesh3' - } - else { - implementation 'org.apache.grails:grails-layout' - } - - compileOnly 'io.micronaut:micronaut-inject-groovy' - - testImplementation "io.micronaut:micronaut-http-client:$micronautVersion" - testImplementation "io.micronaut.serde:micronaut-serde-jackson:$micronautSerdeJacksonVersion" + testImplementation platform("io.micronaut.platform:micronaut-platform:$micronautPlatformVersion") + testImplementation "io.micronaut:micronaut-http-client" + testImplementation "io.micronaut.serde:micronaut-serde-jackson" testImplementation 'io.micronaut:micronaut-inject-groovy' + testImplementation 'org.apache.grails:grails-testing-support-web' testImplementation 'org.spockframework:spock-core' - -} - -application { - mainClass = 'issue11767.Application' } apply { diff --git a/grails-test-examples/issue-11767/grails-app/init/issue11767/app/Application.groovy b/grails-test-examples/issue-11767/grails-app/init/issue11767/app/Application.groovy index 7359a5e03c3..697db1f6530 100644 --- a/grails-test-examples/issue-11767/grails-app/init/issue11767/app/Application.groovy +++ b/grails-test-examples/issue-11767/grails-app/init/issue11767/app/Application.groovy @@ -22,7 +22,9 @@ package issue11767.app import grails.boot.GrailsApp import grails.boot.config.GrailsAutoConfiguration import groovy.transform.CompileStatic +import io.micronaut.spring.boot.starter.EnableMicronaut +@EnableMicronaut @CompileStatic class Application extends GrailsAutoConfiguration { static void main(String[] args) { diff --git a/grails-test-examples/issue-11767/src/integration-test/groovy/issue11767/app/ConfigLoadingSpec.groovy b/grails-test-examples/issue-11767/src/integration-test/groovy/issue11767/app/ConfigLoadingSpec.groovy index 84cc2de89ed..63c15bfc4eb 100644 --- a/grails-test-examples/issue-11767/src/integration-test/groovy/issue11767/app/ConfigLoadingSpec.groovy +++ b/grails-test-examples/issue-11767/src/integration-test/groovy/issue11767/app/ConfigLoadingSpec.groovy @@ -20,7 +20,6 @@ package issue11767.app import grails.testing.mixin.integration.Integration -import grails.testing.spock.OnceBefore import io.micronaut.http.HttpRequest import io.micronaut.http.client.HttpClient import spock.lang.AutoCleanup @@ -35,8 +34,7 @@ class ConfigLoadingSpec extends Specification { @AutoCleanup HttpClient httpClient - @OnceBefore - void init() { + void setup() { def baseUrl = "http://localhost:$serverPort" httpClient = HttpClient.create(baseUrl.toURL()) } diff --git a/grails-test-examples/issue-views-182/build.gradle b/grails-test-examples/issue-views-182/build.gradle index 4a9a73f3998..0885c09545e 100644 --- a/grails-test-examples/issue-views-182/build.gradle +++ b/grails-test-examples/issue-views-182/build.gradle @@ -63,7 +63,7 @@ dependencies { testImplementation 'org.apache.grails:grails-testing-support-web' testImplementation 'org.apache.grails:grails-testing-support-datamapping' - testImplementation "io.micronaut:micronaut-http-client:$micronautVersion" + testImplementation "io.micronaut:micronaut-http-client:$micronautHttpClientVersion" testImplementation "io.micronaut.serde:micronaut-serde-jackson:$micronautSerdeJacksonVersion" } diff --git a/grails-test-examples/micronaut/build.gradle b/grails-test-examples/micronaut/build.gradle index a9f9d220010..02be63b2a1f 100644 --- a/grails-test-examples/micronaut/build.gradle +++ b/grails-test-examples/micronaut/build.gradle @@ -20,83 +20,30 @@ version = '0.1' group = 'micronaut' -apply plugin:'org.apache.grails.gradle.grails-web' -apply plugin:'cloud.wondrify.asset-pipeline' +apply plugin: 'org.apache.grails.gradle.grails-web' +apply plugin: 'cloud.wondrify.asset-pipeline' // The grails-gsp Gradle plugin is not needed for running the functional tests. // It is applied as a smoke test to check that compiling gsp // for production does not fail during build task. apply plugin: 'org.apache.grails.gradle.grails-gsp' -configurations { - developmentOnly - runtimeClasspath { - extendsFrom developmentOnly - } -} - dependencies { implementation platform(project(':grails-bom')) - developmentOnly('org.springframework.boot:spring-boot-devtools') - implementation 'org.springframework.boot:spring-boot-starter-logging' - implementation 'org.springframework.boot:spring-boot-autoconfigure' - implementation 'org.apache.grails:grails-core' - implementation 'org.springframework.boot:spring-boot-starter-actuator' - implementation 'org.springframework.boot:spring-boot-starter-tomcat' - implementation 'org.apache.grails:grails-web-boot' - if(System.getenv('SITEMESH3_TESTING_ENABLED') == 'true') { - implementation 'org.apache.grails:grails-sitemesh3' - } - else { - implementation 'org.apache.grails:grails-layout' - } - implementation 'org.apache.grails:grails-logging' - implementation 'org.apache.grails:grails-rest-transforms' - implementation 'org.apache.grails:grails-databinding' - implementation 'org.apache.grails:grails-i18n' - implementation 'org.apache.grails:grails-services' - implementation 'org.apache.grails:grails-url-mappings' - implementation 'org.apache.grails:grails-interceptors' - implementation 'org.apache.grails:grails-cache' - implementation 'org.apache.grails:grails-async' - implementation 'org.apache.grails:grails-scaffolding' - implementation 'org.apache.grails:grails-events' - implementation 'org.apache.grails:grails-data-hibernate5' - implementation 'org.apache.grails:grails-gsp' - compileOnly 'io.micronaut:micronaut-inject-groovy' + implementation 'org.apache.grails:grails-dependencies-starter-web' + implementation 'org.apache.grails:grails-micronaut' testAndDevelopmentOnly platform(project(':grails-bom')) - testAndDevelopmentOnly 'org.webjars.npm:bootstrap' - testAndDevelopmentOnly 'org.webjars.npm:jquery' + testAndDevelopmentOnly 'org.apache.grails:grails-dependencies-assets' - console 'org.apache.grails:grails-console' - profile 'org.apache.grails.profiles:web' runtimeOnly 'com.h2database:h2' runtimeOnly 'org.apache.tomcat:tomcat-jdbc' - runtimeOnly 'jakarta.xml.bind:jakarta.xml.bind-api' runtimeOnly 'cloud.wondrify:asset-pipeline-grails' - testImplementation 'org.apache.grails:grails-testing-support-datamapping' - testImplementation 'org.mockito:mockito-core' - testImplementation 'org.apache.grails:grails-testing-support-web' - - integrationTestImplementation testFixtures('org.apache.grails:grails-geb') -} -bootRun { - jvmArgs( - '-Dspring.output.ansi.enabled=always', - '-noverify', - '-XX:TieredStopAtLevel=1', - '-Xmx1024m') - sourceResources sourceSets.main - String springProfilesActive = 'spring.profiles.active' - systemProperty springProfilesActive, System.getProperty(springProfilesActive) -} + testImplementation 'org.apache.grails:grails-dependencies-test' -tasks.named('assetCompile').configure { - // No need to compile assets in functional tests - enabled = false + integrationTestImplementation testFixtures('org.apache.grails:grails-geb') } apply { @@ -104,4 +51,4 @@ apply { from rootProject.layout.projectDirectory.file('gradle/java-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-webjar-asset-config.gradle') from rootProject.layout.projectDirectory.file('gradle/grails-extension-gradle-config.gradle') -} \ No newline at end of file +} diff --git a/grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy b/grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy index 0524a40ab2f..5c9b44f908b 100644 --- a/grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy +++ b/grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy @@ -21,10 +21,11 @@ package micronaut 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/grails-app/init/micronaut/BootStrap.groovy b/grails-test-examples/micronaut/grails-app/init/micronaut/BootStrap.groovy index f38351695fc..de6dd8ee9d6 100644 --- a/grails-test-examples/micronaut/grails-app/init/micronaut/BootStrap.groovy +++ b/grails-test-examples/micronaut/grails-app/init/micronaut/BootStrap.groovy @@ -19,6 +19,8 @@ package micronaut +import jakarta.servlet.ServletContext + class BootStrap { def init = { diff --git a/grails-test-examples/micronaut/src/integration-test/groovy/micronaut/BeanInjectionServiceSpec.groovy b/grails-test-examples/micronaut/src/integration-test/groovy/micronaut/BeanInjectionServiceSpec.groovy index 3eb5da83727..7eb32a95ab7 100644 --- a/grails-test-examples/micronaut/src/integration-test/groovy/micronaut/BeanInjectionServiceSpec.groovy +++ b/grails-test-examples/micronaut/src/integration-test/groovy/micronaut/BeanInjectionServiceSpec.groovy @@ -49,9 +49,9 @@ class BeanInjectionServiceSpec extends Specification { service != null } - void "test there are two beans for a Grails service when we inject Micronaut bean in it"() { + void "test there are 1 bean for a Grails service when we inject Micronaut bean in it"() { expect: bInjectService != null - bInjectService.size() == 2 + bInjectService.size() == 1 } } diff --git a/grails-test-examples/plugins/issue-11767-plugin/build.gradle b/grails-test-examples/plugins/issue-11767/build.gradle similarity index 90% rename from grails-test-examples/plugins/issue-11767-plugin/build.gradle rename to grails-test-examples/plugins/issue-11767/build.gradle index 93838f884b2..93a9a152120 100644 --- a/grails-test-examples/plugins/issue-11767-plugin/build.gradle +++ b/grails-test-examples/plugins/issue-11767/build.gradle @@ -18,16 +18,14 @@ */ version = '0.1-SNAPSHOT' -group 'issue11767.plugin' +group = 'issue11767.plugin' apply plugin: 'org.apache.grails.gradle.grails-plugin' dependencies { implementation platform(project(':grails-bom')) - - annotationProcessor 'io.micronaut:micronaut-inject-java' + implementation 'org.apache.grails:grails-micronaut' implementation 'org.apache.grails:grails-core' - compileOnly 'io.micronaut:micronaut-inject-groovy' } apply { diff --git a/grails-test-examples/plugins/issue-11767-plugin/grails-app/conf/plugin.yml b/grails-test-examples/plugins/issue-11767/grails-app/conf/plugin.yml similarity index 100% rename from grails-test-examples/plugins/issue-11767-plugin/grails-app/conf/plugin.yml rename to grails-test-examples/plugins/issue-11767/grails-app/conf/plugin.yml diff --git a/grails-test-examples/plugins/issue-11767-plugin/grails-app/init/issue11767/plugin/Application.groovy b/grails-test-examples/plugins/issue-11767/grails-app/init/issue11767/plugin/Application.groovy similarity index 96% rename from grails-test-examples/plugins/issue-11767-plugin/grails-app/init/issue11767/plugin/Application.groovy rename to grails-test-examples/plugins/issue-11767/grails-app/init/issue11767/plugin/Application.groovy index 9a52a7c0a01..325d11da5a1 100644 --- a/grails-test-examples/plugins/issue-11767-plugin/grails-app/init/issue11767/plugin/Application.groovy +++ b/grails-test-examples/plugins/issue-11767/grails-app/init/issue11767/plugin/Application.groovy @@ -21,8 +21,8 @@ package issue11767.plugin import grails.boot.GrailsApp import grails.boot.config.GrailsAutoConfiguration +import grails.plugins.metadata.PluginSource import groovy.transform.CompileStatic -import grails.plugins.metadata.* import org.springframework.context.annotation.ComponentScan @CompileStatic diff --git a/grails-test-examples/plugins/issue-11767-plugin/src/main/groovy/issue11767/plugin/MyPluginGrailsPlugin.groovy b/grails-test-examples/plugins/issue-11767/src/main/groovy/issue11767/plugin/MyPluginGrailsPlugin.groovy similarity index 97% rename from grails-test-examples/plugins/issue-11767-plugin/src/main/groovy/issue11767/plugin/MyPluginGrailsPlugin.groovy rename to grails-test-examples/plugins/issue-11767/src/main/groovy/issue11767/plugin/MyPluginGrailsPlugin.groovy index b2063dc28be..1c17f36ef07 100644 --- a/grails-test-examples/plugins/issue-11767-plugin/src/main/groovy/issue11767/plugin/MyPluginGrailsPlugin.groovy +++ b/grails-test-examples/plugins/issue-11767/src/main/groovy/issue11767/plugin/MyPluginGrailsPlugin.groovy @@ -19,7 +19,8 @@ package issue11767.plugin -import grails.plugins.* + +import grails.plugins.Plugin class Issue11767GrailsPlugin extends Plugin { diff --git a/grails-test-examples/plugins/issue-11767-plugin/src/main/groovy/issue11767/plugin/PluginGroovyMicronautBean.groovy b/grails-test-examples/plugins/issue-11767/src/main/groovy/issue11767/plugin/PluginGroovyMicronautBean.groovy similarity index 100% rename from grails-test-examples/plugins/issue-11767-plugin/src/main/groovy/issue11767/plugin/PluginGroovyMicronautBean.groovy rename to grails-test-examples/plugins/issue-11767/src/main/groovy/issue11767/plugin/PluginGroovyMicronautBean.groovy diff --git a/grails-test-examples/plugins/issue-11767-plugin/src/main/groovy/issue11767/plugin/PluginGroovySpringBean.groovy b/grails-test-examples/plugins/issue-11767/src/main/groovy/issue11767/plugin/PluginGroovySpringBean.groovy similarity index 100% rename from grails-test-examples/plugins/issue-11767-plugin/src/main/groovy/issue11767/plugin/PluginGroovySpringBean.groovy rename to grails-test-examples/plugins/issue-11767/src/main/groovy/issue11767/plugin/PluginGroovySpringBean.groovy diff --git a/grails-test-examples/plugins/issue-11767-plugin/src/main/java/issue11767/plugin/PluginJavaMicronautBean.java b/grails-test-examples/plugins/issue-11767/src/main/java/issue11767/plugin/PluginJavaMicronautBean.java similarity index 100% rename from grails-test-examples/plugins/issue-11767-plugin/src/main/java/issue11767/plugin/PluginJavaMicronautBean.java rename to grails-test-examples/plugins/issue-11767/src/main/java/issue11767/plugin/PluginJavaMicronautBean.java diff --git a/grails-test-examples/views-functional-tests/build.gradle b/grails-test-examples/views-functional-tests/build.gradle index 8f87d7f0b44..a2d5d87077d 100644 --- a/grails-test-examples/views-functional-tests/build.gradle +++ b/grails-test-examples/views-functional-tests/build.gradle @@ -73,8 +73,8 @@ dependencies { testImplementation 'org.apache.grails.testing:grails-testing-support-core' integrationTestImplementation 'com.fasterxml.jackson.core:jackson-databind' - integrationTestImplementation "io.micronaut:micronaut-http-client:$micronautVersion" - integrationTestImplementation "io.micronaut:micronaut-jackson-databind:$micronautVersion" + integrationTestImplementation "io.micronaut:micronaut-http-client:$micronautHttpClientVersion" + integrationTestImplementation "io.micronaut:micronaut-jackson-databind:$micronautHttpClientVersion" } apply { diff --git a/settings.gradle b/settings.gradle index 8be9e206cfc..48fcb0b678b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -171,7 +171,10 @@ include( 'grails-data-test-report', // wrapper - 'grails-wrapper' + 'grails-wrapper', + + // micronaut plugin for integration with Grails + 'grails-micronaut', ) // Instead of using : to separate nested projects, fix the project directories by setting the projectDir explicitly @@ -359,13 +362,13 @@ include( 'grails-test-examples-issue-views-182', 'grails-test-examples-issue-11102', 'grails-test-examples-demo33', - // 'grails-test-examples-micronaut', // micronaut has been removed from Grails can be restored based on https://micronaut-projects.github.io/micronaut-spring/latest/guide/#springBootStarter + 'grails-test-examples-micronaut', 'grails-test-examples-plugins-loadfirst', 'grails-test-examples-plugins-loadsecond', 'grails-test-examples-plugins-loadafter', 'grails-test-examples-plugins-issue11005', - // 'grails-test-examples-issue-11767', // micronaut has been removed from Grails can be restored based on https://micronaut-projects.github.io/micronaut-spring/latest/guide/#springBootStarter - // 'grails-test-examples-plugins-issue-11767-plugin', // micronaut has been removed from Grails can be restored based on https://micronaut-projects.github.io/micronaut-spring/latest/guide/#springBootStarter + 'grails-test-examples-issue-11767', + 'grails-test-examples-plugins-issue-11767', 'grails-test-examples-cache', 'grails-test-examples-views-functional-tests', 'grails-test-examples-views-functional-tests-plugin' @@ -388,13 +391,13 @@ project(':grails-test-examples-hyphenated').projectDir = file('grails-test-examp project(':grails-test-examples-issue-views-182').projectDir = file('grails-test-examples/issue-views-182') project(':grails-test-examples-issue-11102').projectDir = file('grails-test-examples/issue-11102') project(':grails-test-examples-demo33').projectDir = file('grails-test-examples/demo33') -// project(':grails-test-examples-micronaut').projectDir = file('grails-test-examples/micronaut') +project(':grails-test-examples-micronaut').projectDir = file('grails-test-examples/micronaut') project(':grails-test-examples-plugins-loadfirst').projectDir = file('grails-test-examples/plugins/loadfirst') project(':grails-test-examples-plugins-loadsecond').projectDir = file('grails-test-examples/plugins/loadsecond') project(':grails-test-examples-plugins-loadafter').projectDir = file('grails-test-examples/plugins/loadafter') project(':grails-test-examples-plugins-issue11005').projectDir = file('grails-test-examples/plugins/issue11005') -// project(':grails-test-examples-issue-11767').projectDir = file('grails-test-examples/issue-11767') -// project(':grails-test-examples-plugins-issue-11767-plugin').projectDir = file('grails-test-examples/plugins/issue-11767-plugin') +project(':grails-test-examples-issue-11767').projectDir = file('grails-test-examples/issue-11767') +project(':grails-test-examples-plugins-issue-11767').projectDir = file('grails-test-examples/plugins/issue-11767') project(':grails-test-examples-cache').projectDir = file('grails-test-examples/cache') project(':grails-test-examples-views-functional-tests').projectDir = file('grails-test-examples/views-functional-tests') project(':grails-test-examples-views-functional-tests-plugin').projectDir = file('grails-test-examples/views-functional-tests-plugin') From 27d928469fc398111fe1b0812c36a5c946298bc8 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Tue, 5 Aug 2025 13:43:57 -0400 Subject: [PATCH 05/22] feature: #14017 - add micronaut feature to forge --- .../feature/micronaut/GrailsMicronaut.java | 72 +++++++++++++++++++ .../MicronautHttpClient.java | 2 +- .../grails/forge/create/CreateAppSpec.groovy | 14 ++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/micronaut/GrailsMicronaut.java rename grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/{other => micronaut}/MicronautHttpClient.java (98%) diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/micronaut/GrailsMicronaut.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/micronaut/GrailsMicronaut.java new file mode 100644 index 00000000000..c51a709799e --- /dev/null +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/micronaut/GrailsMicronaut.java @@ -0,0 +1,72 @@ +/* + * 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 org.grails.forge.feature.micronaut; + +import io.micronaut.core.annotation.NonNull; +import jakarta.inject.Singleton; +import org.grails.forge.application.ApplicationType; +import org.grails.forge.application.generator.GeneratorContext; +import org.grails.forge.build.dependencies.Dependency; +import org.grails.forge.feature.Category; +import org.grails.forge.feature.Feature; + +@Singleton +public class GrailsMicronaut implements Feature { + + @Override + @NonNull + public String getName() { + return "grails-micronaut"; + } + + @Override + public String getTitle() { + return "Micronaut Support"; + } + + @Override + public String getDescription() { + return "Adds support for Micronaut to Grails using the Spring Starter"; + } + + @Override + public boolean supports(ApplicationType applicationType) { + return true; + } + + @Override + public String getCategory() { + return Category.SPRING; + } + + @Override + public String getDocumentation() { + return "https://micronaut-projects.github.io/micronaut-spring/latest/guide/#springBootStarter"; + } + + @Override + public void apply(GeneratorContext generatorContext) { + generatorContext.addDependency(Dependency.builder() + .groupId("org.apache.grails") + .artifactId("grails-micronaut") + .implementation()); + + generatorContext.getBuildProperties().put("micronautPlatformVersion", "4.9.2"); + } +} diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/other/MicronautHttpClient.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/micronaut/MicronautHttpClient.java similarity index 98% rename from grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/other/MicronautHttpClient.java rename to grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/micronaut/MicronautHttpClient.java index 96d9a263987..ee9c4a24262 100644 --- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/other/MicronautHttpClient.java +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/micronaut/MicronautHttpClient.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.grails.forge.feature.other; +package org.grails.forge.feature.micronaut; import io.micronaut.core.annotation.NonNull; import jakarta.inject.Singleton; diff --git a/grails-forge/test-core/src/test/groovy/org/grails/forge/create/CreateAppSpec.groovy b/grails-forge/test-core/src/test/groovy/org/grails/forge/create/CreateAppSpec.groovy index 89d3297bf3e..94c41d3836a 100644 --- a/grails-forge/test-core/src/test/groovy/org/grails/forge/create/CreateAppSpec.groovy +++ b/grails-forge/test-core/src/test/groovy/org/grails/forge/create/CreateAppSpec.groovy @@ -81,6 +81,20 @@ class CreateAppSpec extends CommandSpec { '''.stripIndent(8) } + void "test create-app with micronaut feature"() { + given: + generateProject(OperatingSystem.MACOS_ARCH64, ['grails-micronaut'], ApplicationType.WEB) + + def gradleProperties = new File(dir, 'gradle.properties') + def gradleBuildFile = new File(dir, 'build.gradle') + + expect: + gradleProperties.exists() + gradleProperties.text.contains('micronautPlatformVersion=4.9.2') + gradleBuildFile.exists() + gradleBuildFile.text.contains('implementation "org.apache.grails:grails-micronaut"') + } + void "test create-app web-plugin creates a correct Application.groovy"() { given: generateProject(OperatingSystem.MACOS_ARCH64, [], ApplicationType.WEB_PLUGIN) From e0de1ac33028e5629d659afb9cc456b58c312aa0 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Tue, 5 Aug 2025 14:20:53 -0400 Subject: [PATCH 06/22] feature: #14017 - grails gradle plugin should enforce micronaut version like before --- .../plugin/core/GrailsGradlePlugin.groovy | 19 ++++++++++++++++--- grails-micronaut/build.gradle | 14 +------------- 2 files changed, 17 insertions(+), 16 deletions(-) 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 f7f358d7522..3c24703efe4 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 @@ -386,17 +386,30 @@ class GrailsGradlePlugin extends GroovyPlugin { @CompileStatic protected void configureMicronaut(Project project) { project.afterEvaluate { - boolean micronautEnabled = project.getConfigurations().getByName("implementation").getDependencies().findAll { Dependency dep -> dep.group == 'org.apache.grails' && dep.name == 'grails-micronaut' } as boolean + boolean micronautEnabled = project.getConfigurations().getByName('implementation').getDependencies().findAll { Dependency dep -> dep.group == 'org.apache.grails' && dep.name == 'grails-micronaut' } as boolean if (!micronautEnabled) { return } - project.logger.lifecycle('Micronaut Support Detected for {} - adding annotation processor dependencies for Micronaut', project.path) + project.logger.lifecycle('Micronaut Support Detected for {}', project.name) final String micronautPlatformVersion = project.properties['micronautPlatformVersion'] if (!micronautPlatformVersion) { - throw new GradleException("`micronautPlatformVersion` property must be set to use the Grails Micronaut plugin.") + throw new GradleException('`micronautPlatformVersion` property must be set to use the Grails Micronaut plugin.') } + // grails-micronaut exports the platform, but force the version to the user specified version + project.configurations.configureEach { Configuration configuration -> + configuration.resolutionStrategy.eachDependency { DependencyResolveDetails details -> + String dependencyName = details.requested.name + String group = details.requested.group + if (group == 'io.micronaut' && dependencyName.startsWith('micronaut-platform')) { + project.logger.info('Forcing Micronaut Platform version to {}', micronautPlatformVersion) + details.useVersion(micronautPlatformVersion) + } + } + } + + project.logger.info('Adding Micronaut annotationProcessor dependencies to project {}', project.name) project.getDependencies().add('annotationProcessor', project.dependencies.platform("io.micronaut.platform:micronaut-platform:$micronautPlatformVersion")) project.getDependencies().add('annotationProcessor', 'io.micronaut:micronaut-inject-java') project.getDependencies().add('annotationProcessor', 'jakarta.annotation:jakarta.annotation-api') diff --git a/grails-micronaut/build.gradle b/grails-micronaut/build.gradle index 69cc35d10cf..f421630829f 100644 --- a/grails-micronaut/build.gradle +++ b/grails-micronaut/build.gradle @@ -26,18 +26,6 @@ plugins { version = projectVersion group = 'org.apache.grails' -// force a local build version for debugging -//project.configurations.configureEach({ Configuration configuration -> -// configuration.resolutionStrategy.eachDependency({ DependencyResolveDetails details -> -// String dependencyName = details.requested.name -// String group = details.requested.group -// if (group == 'io.micronaut' && dependencyName.startsWith('micronaut-core-processor')) { -// logger.lifecycle("Forcing Micronaut Core Processor version to 4.9.99 for Grails Micronaut plugin") -// details.useVersion('4.9.99') -// } -// } as Action) -//} as Action) - dependencies { annotationProcessor platform(project(':grails-bom')) annotationProcessor platform("io.micronaut.platform:micronaut-platform:$micronautPlatformVersion") @@ -58,7 +46,7 @@ dependencies { exclude group:"org.slf4j", module: "slf4j-simple" } - implementation platform(project(':grails-bom')) + compileOnly platform(project(':grails-bom')) compileOnly project(':grails-core') // Logging From b1e928dfd6631eabf537d5a04eb801a2c78b7e66 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Tue, 5 Aug 2025 14:21:32 -0400 Subject: [PATCH 07/22] doc: #14017 - document how to integrate Micronaut with Grails --- grails-doc/src/en/guide/conf/micronaut.adoc | 44 +++++++++++++++++++ grails-doc/src/en/guide/index.adoc | 5 +++ .../src/en/guide/upgrading/upgrading60x.adoc | 40 ++++++++++------- 3 files changed, 73 insertions(+), 16 deletions(-) create mode 100644 grails-doc/src/en/guide/conf/micronaut.adoc diff --git a/grails-doc/src/en/guide/conf/micronaut.adoc b/grails-doc/src/en/guide/conf/micronaut.adoc new file mode 100644 index 00000000000..041d236d6b4 --- /dev/null +++ b/grails-doc/src/en/guide/conf/micronaut.adoc @@ -0,0 +1,44 @@ +//// +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 Integration + +Grails supports using the Micronaut framework via the `grails-micronaut` plugin. The `grails-micronaut` plugin uses the https://micronaut-projects.github.io/micronaut-spring/latest/guide/#springBootStarter[Micronaut Spring Boot Starter] so that both the Micronaut Application Context & Grails Application Context exist side by side. + +To enable Micronaut in your Grails application, two steps must be completed. First, the `grails-micronaut` plugin needs added to the build file. Second, the property `micronautPlatformVersion` needs set to your desired version. Only Micronaut 4.9.2 or higher is supported for Grails. + +Here's an example build file: + +[source,groovy] +.build.gradle +---- +dependencies { + implementation 'org.apache.grails:grails-micronaut' +} +---- + +Here's an example `gradle.properties` file: + +[source,properties] +.gradle.properties +---- +micronautPlatformVersion=4.9.2 +---- + +When the `grails-micronaut` plugin is present, the Grails Gradle plugin will automatically apply the required annotation processors to your project & ensure the specified Micronaut version is used. \ No newline at end of file diff --git a/grails-doc/src/en/guide/index.adoc b/grails-doc/src/en/guide/index.adoc index 3f6439b814b..0f32264d6bc 100644 --- a/grails-doc/src/en/guide/index.adoc +++ b/grails-doc/src/en/guide/index.adoc @@ -200,6 +200,11 @@ include::conf/applicationClass/applicationLifeCycle.adoc[] include::conf/environments.adoc[] +[[micronaut]] +=== Micronaut + +include::conf/micronaut.adoc[] + [[dataSource]] === The DataSource diff --git a/grails-doc/src/en/guide/upgrading/upgrading60x.adoc b/grails-doc/src/en/guide/upgrading/upgrading60x.adoc index 127688e3417..c40caab79a8 100644 --- a/grails-doc/src/en/guide/upgrading/upgrading60x.adoc +++ b/grails-doc/src/en/guide/upgrading/upgrading60x.adoc @@ -72,15 +72,9 @@ grailsVersion={version} ==== 4. Unified Bill of Materials -Previously Grails did not have a single Bill of Materials (BOM). -Instead it had a `micronaut-bom` and a `spring-bom`. -With the removal of Micronaut from the Grails, the `micronaut-bom` is no longer needed. -Instead, we can have a single bom that inherits from the `spring-bom`. +Previously Grails did not have a single Bill of Materials (BOM). Instead it had a `micronaut-bom` and a `spring-bom` that existed side by side. As of Grails 7, a `grails-bom` is published that inherits from the `spring-bom` and the `micronaut-bom` is not included by default. -Grails 7 introduces a BOM that includes all the dependencies required for a Grails application. -This BOM is available in the `org.apache.grails:grails-bom` artifact. -The BOM is automatically applied when a Grails Gradle plugin is applied via the Spring Dependency Management plugin. -For projects that do not use a Grails Gradle plugin, you can apply the BOM via a https://docs.gradle.org/current/userguide/java_platform_plugin.html#sec:java_platform_consumption[Gradle Platform]: +Grails 7 introduces a BOM that includes all the dependencies required for a Grails application. This BOM is available in the `org.apache.grails:grails-bom` artifact. The BOM is automatically applied when a Grails Gradle plugin is applied via the Spring Dependency Management plugin. For projects that do not use a Grails Gradle plugin, you can apply the BOM via a https://docs.gradle.org/current/userguide/java_platform_plugin.html#sec:java_platform_consumption[Gradle Platform]: [source,groovy] .build.gradle @@ -256,14 +250,28 @@ jakartaeeMigration { 6. `grails.beans.util.LazyBeanMap` -> `grails.beans.util.LazyMetaPropertyMap` 7. `org.grails.plugins.databinding.DataBindingGrailsPlugin` -> `DataBindingConfiguration` -===== 12.4 Micronaut in Grails is now supported via the Micronaut Spring Boot Starter -- This change was made based on community input: https://github.com/apache/grails-core/discussions/13517 -- The removal of Micronaut enabled simplification of the Grails codebase and the return of Live Reload via https://github.com/HotswapProjects/HotswapAgent -- The Micronaut Parent Context is no longer in Grails by default. -- The following dependencies are no longer included in Grails or grails-bom: io.micronaut:micronaut-\*, io.micronaut.cache:micronaut-cache-core, io.micronaut.groovy:micronaut-runtime-groovy and io.micronaut.spring:micronaut-spring-* -- Micronaut can be added via the Micronaut Spring Boot Starter: https://micronaut-projects.github.io/micronaut-spring/latest/guide/#springBootStarter. -- Using Micronaut Parent Context: https://micronaut-projects.github.io/micronaut-spring/latest/guide/#springParentContext -- Using a Bean Post Processor: https://micronaut-projects.github.io/micronaut-spring/latest/guide/#beanPostProcessor +===== 12.4 Micronaut in Grails is now supported via the plugin `grails-micronaut` +In Grails 4 to Grails 6, Micronaut was integrated by making Micronaut the parent context of the Grails application. As of Grails 7, Micronaut is set up via the https://micronaut-projects.github.io/micronaut-spring/latest/guide/#springBootStarter[micronaut-spring-starter] using the `grails-micronaut` plugin. Discussion around this change can be found https://github.com/apache/grails-core/discussions/13517[here]. + +To enable Micronaut in your Grails application, two steps must be completed. First, the `grails-micronaut` plugin needs added to the build file. Second, the property `micronautPlatformVersion` needs set to your desired version. Only Micronaut 4.9.2 or higher is supported for Grails. + +Here's an example build file: + +[source,groovy] +.build.gradle +---- +dependencies { + implementation 'org.apache.grails:grails-micronaut' +} +---- + +Here's an example `gradle.properties` file: + +[source,properties] +.gradle.properties +---- +micronautPlatformVersion=4.9.2 +---- ===== 12.5 hibernate-ehcache From 15db168680696cff1442b4087b314b4ee2e29bf9 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sun, 10 Aug 2025 10:02:38 -0400 Subject: [PATCH 08/22] feedback - dependency & styling clean ups --- gradle/publish-root-config.gradle | 30 +++++++++---------- grails-micronaut/build.gradle | 27 ++--------------- .../init/micronaut/BootStrap.groovy | 2 -- 3 files changed, 18 insertions(+), 41 deletions(-) diff --git a/gradle/publish-root-config.gradle b/gradle/publish-root-config.gradle index 1a47399dcbf..28e48695841 100644 --- a/gradle/publish-root-config.gradle +++ b/gradle/publish-root-config.gradle @@ -24,9 +24,9 @@ version = projectVersion group = 'this.will.be.overridden' def publishedProjects = [ + 'grails-async', 'grails-async-core', 'grails-async-gpars', - 'grails-async', 'grails-async-rxjava', 'grails-async-rxjava2', 'grails-async-rxjava3', @@ -43,15 +43,15 @@ def publishedProjects = [ 'grails-databinding', 'grails-databinding-core', 'grails-datasource', - 'grails-dependencies-starter-web', 'grails-dependencies-assets', + 'grails-dependencies-starter-web', 'grails-dependencies-test', 'grails-domain-class', 'grails-encoder', + 'grails-events', 'grails-events-compat', 'grails-events-core', 'grails-events-gpars', - 'grails-events', 'grails-events-rxjava', 'grails-events-rxjava2', 'grails-events-rxjava3', @@ -63,15 +63,15 @@ def publishedProjects = [ 'grails-gsp-core', 'grails-i18n', 'grails-interceptors', + 'grails-layout', 'grails-logging', - 'grails-mimetypes', 'grails-micronaut', + 'grails-mimetypes', 'grails-rest-transforms', 'grails-scaffolding', 'grails-services', 'grails-shell-cli', 'grails-sitemesh3', - 'grails-layout', 'grails-spring', 'grails-taglib', 'grails-test-core', @@ -95,11 +95,11 @@ def publishedProjects = [ 'grails-web-taglib', 'grails-web-url-mappings', // datastore - 'grails-datastore-async', - 'grails-datastore-core', + 'grails-datamapping-async', 'grails-datamapping-core', 'grails-datamapping-core-test', - 'grails-datamapping-async', + 'grails-datastore-async', + 'grails-datastore-core', //'grails-datamapping-rx', 'grails-datamapping-support', 'grails-datamapping-tck', @@ -109,23 +109,23 @@ def publishedProjects = [ // simple 'grails-data-simple', // hibernate5 - 'grails-data-hibernate5-spring-boot', - 'grails-data-hibernate5-dbmigration', - 'grails-data-hibernate5-core', 'grails-data-hibernate5', + 'grails-data-hibernate5-core', + 'grails-data-hibernate5-dbmigration', + 'grails-data-hibernate5-spring-boot', // mongodb - 'grails-data-mongodb-spring-boot', - 'grails-data-mongodb-core', + 'grails-data-mongodb', 'grails-data-mongodb-bson', + 'grails-data-mongodb-core', 'grails-data-mongodb-ext', - 'grails-data-mongodb', 'grails-data-mongodb-gson-templates', + 'grails-data-mongodb-spring-boot', // wrapper 'grails-wrapper', // profiles 'grails-profiles-base', - 'grails-profiles-profile', 'grails-profiles-plugin', + 'grails-profiles-profile', 'grails-profiles-rest-api', 'grails-profiles-rest-api-plugin', 'grails-profiles-web', diff --git a/grails-micronaut/build.gradle b/grails-micronaut/build.gradle index f421630829f..9b322cc2574 100644 --- a/grails-micronaut/build.gradle +++ b/grails-micronaut/build.gradle @@ -27,40 +27,20 @@ version = projectVersion group = 'org.apache.grails' dependencies { - annotationProcessor platform(project(':grails-bom')) - annotationProcessor platform("io.micronaut.platform:micronaut-platform:$micronautPlatformVersion") - annotationProcessor 'io.micronaut:micronaut-inject-java' - annotationProcessor 'jakarta.annotation:jakarta.annotation-api' - compileOnlyApi platform("io.micronaut.platform:micronaut-platform:$micronautPlatformVersion") compileOnlyApi 'io.micronaut:micronaut-inject-groovy' compileOnlyApi 'io.micronaut:micronaut-inject-java' api platform("io.micronaut.platform:micronaut-platform:$micronautPlatformVersion") api 'io.micronaut.spring:micronaut-spring-boot-starter' - api "io.micronaut.spring:micronaut-spring-context", { + api 'io.micronaut.spring:micronaut-spring-context', { // required to load the micronaut environment with plugin configuration - exclude group: "org.slf4j", module: "slf4j-simple" - } - api "io.micronaut.cache:micronaut-cache-core", { - exclude group:"org.slf4j", module: "slf4j-simple" + exclude group: 'org.slf4j', module: 'slf4j-simple' } + // For the grails plugin interface compileOnly platform(project(':grails-bom')) compileOnly project(':grails-core') - - // Logging - compileOnly 'org.slf4j:slf4j-api' - compileOnly 'org.slf4j:jcl-over-slf4j' - - // Testing - testImplementation platform(project(':grails-bom')) - testImplementation 'org.slf4j:slf4j-simple' - testImplementation('org.spockframework:spock-core') { transitive = false } - - // Required by Spock's Mocking - testRuntimeOnly 'net.bytebuddy:byte-buddy' - testImplementation 'org.objenesis:objenesis' } apply { @@ -68,5 +48,4 @@ apply { from rootProject.layout.projectDirectory.file('gradle/java-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') - from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') } \ No newline at end of file diff --git a/grails-test-examples/micronaut/grails-app/init/micronaut/BootStrap.groovy b/grails-test-examples/micronaut/grails-app/init/micronaut/BootStrap.groovy index de6dd8ee9d6..f38351695fc 100644 --- a/grails-test-examples/micronaut/grails-app/init/micronaut/BootStrap.groovy +++ b/grails-test-examples/micronaut/grails-app/init/micronaut/BootStrap.groovy @@ -19,8 +19,6 @@ package micronaut -import jakarta.servlet.ServletContext - class BootStrap { def init = { From 7d094d475fc5b0f41df0cad4726dfe55ded8f6fc Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 15 Aug 2025 22:32:42 -0400 Subject: [PATCH 09/22] chore: simplify rat config --- gradle/rat-root-config.gradle | 3 --- 1 file changed, 3 deletions(-) diff --git a/gradle/rat-root-config.gradle b/gradle/rat-root-config.gradle index e581a0c9129..60527f64371 100644 --- a/gradle/rat-root-config.gradle +++ b/gradle/rat-root-config.gradle @@ -21,8 +21,6 @@ tasks.named('rat') { def allExcludes = [ '.asf.yaml', // ASF metadata for github integration excluded from src zip 'CODE_OF_CONDUCT.md', - 'LICENSE', - 'NOTICE', 'BUILD_DATE', // build artifact for storing the build date / verifying 'CHECKSUMS', // build artifact for storing checksums for easy verification 'PUBLISHED_ARTIFACTS', // build artifact for storing published artifacts coordinates & paths @@ -34,7 +32,6 @@ tasks.named('rat') { 'grails-web-common/src/main/groovy/org/grails/web/json/JSONElement.java', 'grails-web-common/src/main/groovy/org/grails/web/json/JSONException.java', 'grails-web-common/src/main/groovy/org/grails/web/json/JSONWriter.java', - 'gradle/wrapper/gradle-wrapper.properties', // gradle wrapper excluded from src zip '**/.gitattributes', // git configuration isn't code '**/.gradle/**', '**/wrapper/**', 'gradlew*', // gradle wrapper files excluded from src zip '**/*.html', // html files are only in test From a370d5cfb11c6609dc90d9529b151cfd129e2c07 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sun, 31 Aug 2025 22:55:24 -0400 Subject: [PATCH 10/22] 14017 - fix - do not use bean replacement for jspViewResolver & ensure all view resolvers are lazy init --- grails-gsp/grails-layout/build.gradle | 2 +- ...ailsLayoutViewResolverPostProcessor.groovy | 30 +++++++----- .../web/GroovyPagesGrailsPlugin.groovy | 7 +-- .../web/GroovyPagesPostProcessor.groovy | 49 +++++++++++++++++++ .../groovy/EndToEndSpec.groovy | 5 -- 5 files changed, 70 insertions(+), 23 deletions(-) create mode 100644 grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesPostProcessor.groovy diff --git a/grails-gsp/grails-layout/build.gradle b/grails-gsp/grails-layout/build.gradle index 0b2442e94d9..7a1403ac627 100644 --- a/grails-gsp/grails-layout/build.gradle +++ b/grails-gsp/grails-layout/build.gradle @@ -44,7 +44,7 @@ dependencies { implementation platform(project(':grails-bom')) implementation project(':grails-web-common') // GrailsViewResolver implementation project(':grails-core') // for plugin & groovy - implementation project(':grails-gsp-core') // for grails layout preprocessor + implementation project(':grails-gsp') // for grails layout preprocessor & gsp configuration classes runtimeOnly project(':grails-web-jsp') diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsLayoutViewResolverPostProcessor.groovy b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsLayoutViewResolverPostProcessor.groovy index c69b9b11066..f29cec667c1 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsLayoutViewResolverPostProcessor.groovy +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsLayoutViewResolverPostProcessor.groovy @@ -19,10 +19,11 @@ package org.apache.grails.web.layout +import org.grails.plugins.web.GroovyPagesPostProcessor +import org.grails.web.servlet.view.GroovyPageViewResolver import org.springframework.beans.BeansException import org.springframework.beans.MutablePropertyValues import org.springframework.beans.factory.config.BeanDefinition -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory import org.springframework.beans.factory.config.RuntimeBeanReference import org.springframework.beans.factory.support.BeanDefinitionRegistry import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor @@ -46,25 +47,30 @@ class GrailsLayoutViewResolverPostProcessor implements BeanDefinitionRegistryPos private static final String GRAILS_VIEW_RESOLVER_BEAN_NAME = 'jspViewResolver' private static final String GROOVY_PAGE_LAYOUT_FINDER_BEAN_NAME = 'groovyPageLayoutFinder' - int order = 0 + int order = GroovyPagesPostProcessor.ORDER - 1 Class layoutViewResolverClass = GrailsLayoutViewResolver String layoutViewResolverBeanParentName = null boolean markBeanPrimary = true - boolean enabled = true - @Override - void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - } - @Override void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { - if (enabled && registry.containsBeanDefinition(GRAILS_VIEW_RESOLVER_BEAN_NAME)) { - BeanDefinition previousViewResolver = registry.getBeanDefinition(GRAILS_VIEW_RESOLVER_BEAN_NAME) - registry.removeBeanDefinition(GRAILS_VIEW_RESOLVER_BEAN_NAME) + if (enabled) { + BeanDefinition innerViewDefinition + if (registry.containsBeanDefinition(GRAILS_VIEW_RESOLVER_BEAN_NAME)) { + innerViewDefinition = registry.getBeanDefinition(GRAILS_VIEW_RESOLVER_BEAN_NAME) + registry.removeBeanDefinition(GRAILS_VIEW_RESOLVER_BEAN_NAME) + } else { + // default to what GroovyPagesPostProcessor would + innerViewDefinition = new GenericBeanDefinition() + innerViewDefinition.beanClass = GroovyPageViewResolver + innerViewDefinition.parentName = 'abstractViewResolver' + innerViewDefinition.lazyInit = true + } GenericBeanDefinition beanDefinition = new GenericBeanDefinition() beanDefinition.beanClass = layoutViewResolverClass + beanDefinition.lazyInit = true if (layoutViewResolverBeanParentName) { beanDefinition.parentName = layoutViewResolverBeanParentName } @@ -72,8 +78,8 @@ class GrailsLayoutViewResolverPostProcessor implements BeanDefinitionRegistryPos beanDefinition.primary = true } final MutablePropertyValues propertyValues = beanDefinition.getPropertyValues() - propertyValues.addPropertyValue('innerViewResolver', previousViewResolver) - propertyValues.addPropertyValue('groovyPageLayoutFinder', new RuntimeBeanReference((String) GROOVY_PAGE_LAYOUT_FINDER_BEAN_NAME, false)) + propertyValues.addPropertyValue('innerViewResolver', innerViewDefinition) + propertyValues.addPropertyValue('groovyPageLayoutFinder', new RuntimeBeanReference(GROOVY_PAGE_LAYOUT_FINDER_BEAN_NAME, false)) registry.registerBeanDefinition(GRAILS_VIEW_RESOLVER_BEAN_NAME, beanDefinition) } } diff --git a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy index 3e37889dbfd..3d1b0ae61b6 100644 --- a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy +++ b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy @@ -247,11 +247,8 @@ class GroovyPagesGrailsPlugin extends Plugin { cacheTimeout = gspCacheTimeout } } - // Configure a Spring MVC view resolver - jspViewResolver(GroovyPageViewResolver) { bean -> - bean.lazyInit = true - bean.parent = 'abstractViewResolver' - } + // Configure a Spring MVC view resolver if none is defined + groovyPagesPostProcessor(GroovyPagesPostProcessor) // Now go through tag libraries and configure them in Spring too. With AOP proxies and so on for (taglib in application.tagLibClasses) { diff --git a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesPostProcessor.groovy b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesPostProcessor.groovy new file mode 100644 index 00000000000..eb47f15bdbb --- /dev/null +++ b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesPostProcessor.groovy @@ -0,0 +1,49 @@ +/* + * 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 org.grails.plugins.web + +import org.grails.web.servlet.view.GroovyPageViewResolver +import org.springframework.beans.BeansException +import org.springframework.beans.factory.support.BeanDefinitionRegistry +import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor +import org.springframework.beans.factory.support.GenericBeanDefinition +import org.springframework.core.Ordered + +/** + * Registers a jspViewResolver bean definition if one does not already exist. + */ +class GroovyPagesPostProcessor implements BeanDefinitionRegistryPostProcessor, Ordered { + + private static final String JSP_VIEW_RESOLVER_BEAN_NAME = 'jspViewResolver' + public static final int ORDER = 0 + + int order = ORDER + + @Override + void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + if (!registry.containsBeanDefinition(JSP_VIEW_RESOLVER_BEAN_NAME)) { + GenericBeanDefinition beanDefinition = new GenericBeanDefinition() + beanDefinition.beanClass = GroovyPageViewResolver + beanDefinition.parentName = 'abstractViewResolver' + beanDefinition.lazyInit = true + registry.registerBeanDefinition(JSP_VIEW_RESOLVER_BEAN_NAME, beanDefinition) + } + } +} diff --git a/grails-test-examples/gsp-sitemesh3/src/integration-test/groovy/EndToEndSpec.groovy b/grails-test-examples/gsp-sitemesh3/src/integration-test/groovy/EndToEndSpec.groovy index 76810804398..df9dba72322 100644 --- a/grails-test-examples/gsp-sitemesh3/src/integration-test/groovy/EndToEndSpec.groovy +++ b/grails-test-examples/gsp-sitemesh3/src/integration-test/groovy/EndToEndSpec.groovy @@ -24,7 +24,6 @@ import spock.lang.PendingFeature @Integration class EndToEndSpec extends ContainerGebSpec { - @PendingFeature def 'simple layout'() { when: go('endToEnd/simpleLayout') @@ -35,7 +34,6 @@ class EndToEndSpec extends ContainerGebSpec { """ } - @PendingFeature def 'title in subtemplate'() { when: go('endToEnd/titleInSubtemplate') @@ -58,7 +56,6 @@ class EndToEndSpec extends ContainerGebSpec { """ } - @PendingFeature def 'parameters'() { when: go('endToEnd/parameters') @@ -67,7 +64,6 @@ class EndToEndSpec extends ContainerGebSpec { pageSource == """

pageProperty: here!

""" } - @PendingFeature def 'parameters with logic'() { when: go('endToEnd/parametersWithLogic') @@ -76,7 +72,6 @@ class EndToEndSpec extends ContainerGebSpec { pageSource == "good" } - @PendingFeature def 'multiline title'() { when: go('endToEnd/multilineTitle') From 0197fe076ee4553113e581c5a5d56cf1456d0252 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sun, 31 Aug 2025 23:11:26 -0400 Subject: [PATCH 11/22] 14017 - refactor - do not set the application context on beans that are already context aware --- .../layout/EmbeddedGrailsLayoutViewResolver.java | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/EmbeddedGrailsLayoutViewResolver.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/EmbeddedGrailsLayoutViewResolver.java index 6fa167216e4..c8b2761952b 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/EmbeddedGrailsLayoutViewResolver.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/EmbeddedGrailsLayoutViewResolver.java @@ -25,9 +25,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; import org.springframework.core.Ordered; import org.springframework.web.context.ServletContextAware; import org.springframework.web.servlet.SmartView; @@ -36,7 +33,7 @@ import org.grails.web.servlet.view.LayoutViewResolver; -public class EmbeddedGrailsLayoutViewResolver implements LayoutViewResolver, Ordered, ServletContextAware, ApplicationContextAware { +public class EmbeddedGrailsLayoutViewResolver implements LayoutViewResolver, Ordered, ServletContextAware { private static final Logger LOG = LoggerFactory.getLogger(EmbeddedGrailsLayoutViewResolver.class); @@ -91,16 +88,6 @@ public void setOrder(int order) { @Override public void setServletContext(ServletContext servletContext) { this.servletContext = servletContext; - if (innerViewResolver instanceof ServletContextAware) { - ((ServletContextAware) innerViewResolver).setServletContext(servletContext); - } - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - if (innerViewResolver instanceof ApplicationContextAware) { - ((ApplicationContextAware) innerViewResolver).setApplicationContext(applicationContext); - } } public void setInnerViewResolver(ViewResolver innerViewResolver) { From 56b597463348c70d8c6c21f9882e9aa1d278f686 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sun, 31 Aug 2025 23:29:32 -0400 Subject: [PATCH 12/22] #14017 - fix - bean syntax --- .../groovy/grails/plugin/formfields/FieldsGrailsPlugin.groovy | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/grails-fields/src/main/groovy/grails/plugin/formfields/FieldsGrailsPlugin.groovy b/grails-fields/src/main/groovy/grails/plugin/formfields/FieldsGrailsPlugin.groovy index ee241079428..398433c160d 100644 --- a/grails-fields/src/main/groovy/grails/plugin/formfields/FieldsGrailsPlugin.groovy +++ b/grails-fields/src/main/groovy/grails/plugin/formfields/FieldsGrailsPlugin.groovy @@ -42,8 +42,7 @@ class FieldsGrailsPlugin extends Plugin { formFieldsTemplateService(FormFieldsTemplateService) fieldsDomainPropertyFactory(DomainPropertyFactoryImpl) domainModelService(DomainModelServiceImpl) { - domainPropertyFactory: - ref(fieldsDomainPropertyFactory) + domainPropertyFactory = ref('fieldsDomainPropertyFactory') } } } From 1df83c47f332516438a7caa8a5475ac67a509f37 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Mon, 1 Sep 2025 00:56:31 -0400 Subject: [PATCH 13/22] 14017 - fix - switch to constructor based bean wiring --- ...faultConstraintEvaluatorFactoryBean.groovy | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/DefaultConstraintEvaluatorFactoryBean.groovy b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/DefaultConstraintEvaluatorFactoryBean.groovy index b1c161f6064..d954f5b6935 100644 --- a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/DefaultConstraintEvaluatorFactoryBean.groovy +++ b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/DefaultConstraintEvaluatorFactoryBean.groovy @@ -20,7 +20,6 @@ package org.grails.plugins.domain.support import org.springframework.beans.factory.FactoryBean -import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Qualifier import org.springframework.context.MessageSource @@ -36,23 +35,17 @@ import org.grails.validation.ConstraintEvalUtils class DefaultConstraintEvaluatorFactoryBean implements FactoryBean { MessageSource messageSource - - @Autowired - setMessageSource(List messageSources) { - setMessageSource(GrailsMessageSourceUtils.findPreferredMessageSource(messageSources)) - } - - void setMessageSource(MessageSource messageSource) { - this.messageSource = messageSource - } - - @Autowired - @Qualifier('grailsDomainClassMappingContext') MappingContext grailsDomainClassMappingContext - - @Autowired GrailsApplication grailsApplication + DefaultConstraintEvaluatorFactoryBean(List messageSources, + @Qualifier('grailsDomainClassMappingContext') MappingContext mappingContext, + GrailsApplication grailsApplication) { + this.messageSource = GrailsMessageSourceUtils.findPreferredMessageSource(messageSources) + this.grailsDomainClassMappingContext = mappingContext + this.grailsApplication = grailsApplication + } + @Override ConstraintsEvaluator getObject() throws Exception { ConstraintRegistry registry = new DefaultConstraintRegistry(messageSource) From f7c73ee159539b145f2ae4251a19d5b6a92846a2 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Mon, 1 Sep 2025 01:38:40 -0400 Subject: [PATCH 14/22] 14017 - cleanup - remove dependency that is no longer included --- grails-micronaut/build.gradle | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/grails-micronaut/build.gradle b/grails-micronaut/build.gradle index 9b322cc2574..8648a527710 100644 --- a/grails-micronaut/build.gradle +++ b/grails-micronaut/build.gradle @@ -33,10 +33,7 @@ dependencies { api platform("io.micronaut.platform:micronaut-platform:$micronautPlatformVersion") api 'io.micronaut.spring:micronaut-spring-boot-starter' - api 'io.micronaut.spring:micronaut-spring-context', { - // required to load the micronaut environment with plugin configuration - exclude group: 'org.slf4j', module: 'slf4j-simple' - } + api 'io.micronaut.spring:micronaut-spring-context' // For the grails plugin interface compileOnly platform(project(':grails-bom')) From f64899b40199fb737e04380ecc670b862f2feacd Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Mon, 1 Sep 2025 01:42:22 -0400 Subject: [PATCH 15/22] 14017 - styling - clean up styling from original 6.x code --- .../micronaut/GrailsMicronautGrailsPlugin.groovy | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy index 7aa6aeeb287..411c2b094f0 100644 --- a/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy +++ b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy @@ -47,23 +47,21 @@ class GrailsMicronautGrailsPlugin extends Plugin { } if (!applicationContext.containsBean('micronautApplicationContext')) { - throw new IllegalStateException("A Micronaut Application Context should exist prior to the loading of the Grails Micronaut plugin.") + throw new IllegalStateException('A Micronaut Application Context should exist prior to the loading of the Grails Micronaut plugin.') } ConfigurableApplicationContext micronautContext = applicationContext.getBean('micronautApplicationContext', ConfigurableApplicationContext) - Environment micronautEnv = micronautContext.getEnvironment() + Environment micronautEnv = micronautContext.environment - log.debug("Loading configurations from the plugins to the parent Micronaut context") - final GrailsPlugin[] plugins = pluginManager.allPlugins - final GrailsPlugin[] pluginsFromContext = pluginManagerFromContext ? pluginManagerFromContext.allPlugins : new GrailsPlugin[]{} - Integer priority = AbstractPropertySourceLoader.DEFAULT_POSITION + log.debug('Loading configurations from the plugins to the parent Micronaut context') + GrailsPlugin[] plugins = pluginManager.allPlugins + GrailsPlugin[] pluginsFromContext = pluginManagerFromContext ? pluginManagerFromContext.allPlugins : new GrailsPlugin[]{} + int priority = AbstractPropertySourceLoader.DEFAULT_POSITION [plugins, pluginsFromContext].each { GrailsPlugin[] pluginsToProcess -> Arrays.stream(pluginsToProcess) .filter({ GrailsPlugin plugin -> plugin.propertySource != null }) .forEach({ GrailsPlugin plugin -> - if (log.isDebugEnabled()) { - log.debug("Loading configurations from {} plugin to the parent Micronaut context", plugin.name) - } + log.debug('Loading configurations from {} plugin to the parent Micronaut context', plugin.name) // If invoking the source as `.source`, the NavigableMapPropertySource will return null, while invoking the getter, it will return the correct value micronautEnv.addPropertySource(PropertySource.of("grails.plugins.$plugin.name", (Map) plugin.propertySource.getSource(), --priority)) }) From 51db4077049b48f6d4ddeedf7890b8dc3267ce61 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Mon, 1 Sep 2025 10:18:38 -0400 Subject: [PATCH 16/22] 14017 - fix - move domain class to auto configuration to fix dependency load orders --- .../ControllersAutoConfiguration.java | 6 +- grails-domain-class/build.gradle | 3 + .../domain/DomainClassGrailsPlugin.groovy | 24 ----- .../GrailsDomainClassAutoConfiguration.groovy | 87 +++++++++++++++++++ .../DefaultMappingContextFactoryBean.groovy | 5 +- ...ot.autoconfigure.AutoConfiguration.imports | 20 +++++ 6 files changed, 118 insertions(+), 27 deletions(-) create mode 100644 grails-domain-class/src/main/groovy/org/grails/plugins/domain/GrailsDomainClassAutoConfiguration.groovy create mode 100644 grails-domain-class/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllersAutoConfiguration.java b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllersAutoConfiguration.java index d1804887b06..2d9817d73ab 100644 --- a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllersAutoConfiguration.java +++ b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllersAutoConfiguration.java @@ -44,12 +44,16 @@ import grails.config.Settings; import grails.core.GrailsApplication; +import org.grails.plugins.domain.GrailsDomainClassAutoConfiguration; import org.grails.web.config.http.GrailsFilters; import org.grails.web.filters.HiddenHttpMethodFilter; import org.grails.web.servlet.mvc.GrailsDispatcherServlet; import org.grails.web.servlet.mvc.GrailsWebRequestFilter; -@AutoConfiguration(before = { HttpEncodingAutoConfiguration.class, WebMvcAutoConfiguration.class }) +@AutoConfiguration( + before = {HttpEncodingAutoConfiguration.class, WebMvcAutoConfiguration.class}, + after = {GrailsDomainClassAutoConfiguration.class} +) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) public class ControllersAutoConfiguration { diff --git a/grails-domain-class/build.gradle b/grails-domain-class/build.gradle index a329240c962..bae1bbd4a53 100644 --- a/grails-domain-class/build.gradle +++ b/grails-domain-class/build.gradle @@ -35,6 +35,9 @@ dependencies { api project(':grails-validation') api 'org.apache.groovy:groovy' + compileOnly project(':grails-i18n') + runtimeOnly project(':grails-i18n') + // Datastore APIs api project(':grails-datamapping-validation') api(project(':grails-datamapping-core')) { diff --git a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/DomainClassGrailsPlugin.groovy b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/DomainClassGrailsPlugin.groovy index 3557aa4c72b..460a06afaea 100644 --- a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/DomainClassGrailsPlugin.groovy +++ b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/DomainClassGrailsPlugin.groovy @@ -18,14 +18,8 @@ */ package org.grails.plugins.domain -import grails.core.GrailsApplication import grails.plugins.Plugin import grails.util.GrailsUtil -import grails.validation.ConstraintsEvaluator -import org.grails.plugins.domain.support.ConstraintEvaluatorAdapter -import org.grails.plugins.domain.support.DefaultConstraintEvaluatorFactoryBean -import org.grails.plugins.domain.support.DefaultMappingContextFactoryBean -import org.grails.plugins.domain.support.ValidatorRegistryFactoryBean /** * Configures the domain classes in the spring context. @@ -41,22 +35,4 @@ class DomainClassGrailsPlugin extends Plugin { def version = GrailsUtil.getGrailsVersion() def dependsOn = [i18n: version] def loadAfter = ['controllers', 'dataSource'] - - Closure doWithSpring() { - { -> - GrailsApplication application = grailsApplication - validateableConstraintsEvaluator(DefaultConstraintEvaluatorFactoryBean) { bean -> - bean.lazyInit = true - } - "${ConstraintsEvaluator.BEAN_NAME}"(ConstraintEvaluatorAdapter, ref('validateableConstraintsEvaluator')) { bean -> - bean.lazyInit = true - } - grailsDomainClassMappingContext(DefaultMappingContextFactoryBean, application, applicationContext) { bean -> - bean.lazyInit = true - } - gormValidatorRegistry(ValidatorRegistryFactoryBean) { bean -> - bean.lazyInit = true - } - } - } } diff --git a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/GrailsDomainClassAutoConfiguration.groovy b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/GrailsDomainClassAutoConfiguration.groovy new file mode 100644 index 00000000000..b72c7acb290 --- /dev/null +++ b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/GrailsDomainClassAutoConfiguration.groovy @@ -0,0 +1,87 @@ +/* + * 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 org.grails.plugins.domain + +import grails.core.GrailsApplication +import grails.validation.ConstraintsEvaluator +import groovy.transform.CompileStatic +import org.grails.datastore.gorm.validation.constraints.factory.ConstraintFactory +import org.grails.datastore.mapping.model.MappingContext +import org.grails.plugins.domain.support.ConstraintEvaluatorAdapter +import org.grails.plugins.domain.support.DefaultConstraintEvaluatorFactoryBean +import org.grails.plugins.domain.support.DefaultMappingContextFactoryBean +import org.grails.plugins.domain.support.ValidatorRegistryFactoryBean +import org.grails.plugins.i18n.I18nAutoConfiguration +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.boot.autoconfigure.AutoConfiguration +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication +import org.springframework.context.ApplicationContext +import org.springframework.context.MessageSource +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Lazy + +@CompileStatic +// TODO: datasource plugin is supposed to always load after this (currently will because this is a configuration) +@AutoConfiguration(after = [I18nAutoConfiguration]) +@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) +class GrailsDomainClassAutoConfiguration { + + @Autowired + GrailsApplication grailsApplication + + @Autowired + ApplicationContext applicationContext + + @Autowired + List messageSources + + @Lazy + @Bean('grailsDomainClassMappingContext') + DefaultMappingContextFactoryBean grailsDomainClassMappingContext( + List constraintFactories + ) { + def bean = new DefaultMappingContextFactoryBean(grailsApplication, messageSources) + bean.constraintFactories = constraintFactories ?: [] + bean + } + + @Lazy + @Bean + DefaultConstraintEvaluatorFactoryBean validateableConstraintsEvaluator(@Qualifier('grailsDomainClassMappingContext') MappingContext grailsDomainClassMappingContext) { + + new DefaultConstraintEvaluatorFactoryBean(messageSources, grailsDomainClassMappingContext, grailsApplication) + } + + @Lazy + @Bean(name = ConstraintsEvaluator.BEAN_NAME) + ConstraintEvaluatorAdapter constraintsEvaluator(DefaultConstraintEvaluatorFactoryBean validateableConstraintsEvaluator) { + def bean = new ConstraintEvaluatorAdapter(validateableConstraintsEvaluator.getObject()) + bean + } + + @Lazy + @Bean + ValidatorRegistryFactoryBean gormValidatorRegistry(@Qualifier('grailsDomainClassMappingContext') MappingContext grailsDomainClassMappingContext) { + def bean = new ValidatorRegistryFactoryBean() + bean.mappingContext = grailsDomainClassMappingContext + bean + } +} diff --git a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/DefaultMappingContextFactoryBean.groovy b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/DefaultMappingContextFactoryBean.groovy index 652ac6c4c3f..959fbf1b35a 100644 --- a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/DefaultMappingContextFactoryBean.groovy +++ b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/DefaultMappingContextFactoryBean.groovy @@ -30,6 +30,7 @@ import org.springframework.core.env.PropertyResolver import grails.core.GrailsApplication import grails.core.GrailsClass +import grails.util.GrailsMessageSourceUtils import org.grails.core.artefact.DomainClassArtefactHandler import org.grails.datastore.gorm.validation.constraints.factory.ConstraintFactory import org.grails.datastore.gorm.validation.constraints.registry.DefaultValidatorRegistry @@ -53,9 +54,9 @@ class DefaultMappingContextFactoryBean implements FactoryBean, I protected final ApplicationContext applicationContext private MappingContext mappingContext - DefaultMappingContextFactoryBean(GrailsApplication grailsApplication, MessageSource messageSource) { + DefaultMappingContextFactoryBean(GrailsApplication grailsApplication, List messageSources) { this.configuration = grailsApplication.config - this.messageSource = messageSource + this.messageSource = GrailsMessageSourceUtils.findPreferredMessageSource(messageSources) this.grailsApplication = grailsApplication if (messageSource instanceof ApplicationContext) { this.applicationContext = (ApplicationContext) messageSource diff --git a/grails-domain-class/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/grails-domain-class/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..380d493973e --- /dev/null +++ b/grails-domain-class/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,20 @@ +# +# 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. +# + +org.grails.plugins.domain.GrailsDomainClassAutoConfiguration \ No newline at end of file From e2e0a85da9903d86ab5fb879ae8697ad7b86bf4b Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Mon, 1 Sep 2025 10:44:08 -0400 Subject: [PATCH 17/22] 14017 - cleanup - move i18n to be included by default and no longer require it as an exported dependency --- RENAME.md | 2 +- etc/bin/rename_gradle_artifacts.sh | 4 ++-- grails-dependencies/starter-web/build.gradle | 1 - .../en/guide/commandLine/gradleBuild/gradleDependencies.adoc | 1 - .../forge/feature/grails/GrailsDefaultPluginsSpec.groovy | 1 - grails-i18n/build.gradle | 2 +- grails-profiles/base/profile.yml | 2 -- .../autoconfigure/GrailsCompilerAutoConfiguration.java | 2 +- grails-test-examples/cache/build.gradle | 1 - grails-test-examples/demo33/build.gradle | 1 - grails-test-examples/external-configuration/build.gradle | 1 - grails-test-examples/geb-gebconfig/build.gradle | 1 - grails-test-examples/geb/build.gradle | 1 - grails-test-examples/gsp-layout/build.gradle | 1 - grails-test-examples/gsp-sitemesh3/build.gradle | 1 - .../hibernate5/grails-data-service/build.gradle | 1 - .../hibernate5/grails-database-per-tenant/build.gradle | 1 - grails-test-examples/hibernate5/grails-hibernate/build.gradle | 1 - .../hibernate5/grails-partitioned-multi-tenancy/build.gradle | 1 - .../hibernate5/grails-schema-per-tenant/build.gradle | 1 - grails-test-examples/hibernate5/issue450/build.gradle | 1 - grails-test-examples/issue-11102/build.gradle | 1 - grails-test-examples/mongodb/base/build.gradle | 1 - grails-test-examples/mongodb/database-per-tenant/build.gradle | 1 - grails-test-examples/mongodb/hibernate5/build.gradle | 1 - grails-test-examples/mongodb/test-data-service/build.gradle | 1 - grails-test-examples/views-functional-tests/build.gradle | 1 - grails-test-suite-persistence/build.gradle | 1 - grails-test-suite-uber/build.gradle | 1 - grails-web-boot/build.gradle | 1 - 30 files changed, 5 insertions(+), 32 deletions(-) diff --git a/RENAME.md b/RENAME.md index c00d1650284..d6531aa0b90 100644 --- a/RENAME.md +++ b/RENAME.md @@ -112,7 +112,7 @@ Below is a reference of all migrated artifacts - both their old and new name. | org.grails.plugins | gsp | org.apache.grails | grails-gsp | | | grails-views | | org.grails | grails-gsp | org.apache.grails.views | grails-gsp-core | | | grails-views | | org.grails | grails-logging | org.apache.grails | grails-logging | | | grails-core | -| org.grails | grails-plugin-i18n | org.apache.grails | grails-i18n | | | grails-core | +| org.grails | grails-plugin-i18n | org.apache.grails.i18n | grails-i18n | | | grails-core | | org.grails | grails-plugin-interceptors | org.apache.grails | grails-interceptors | | | grails-core | | org.grails | grails-plugin-mimetypes | org.apache.grails | grails-mimetypes | | | grails-core | | org.grails.plugins | quartz | org.apache.grails | grails-quartz | | | grails-quartz | diff --git a/etc/bin/rename_gradle_artifacts.sh b/etc/bin/rename_gradle_artifacts.sh index cdfeaefd882..e923b402af3 100755 --- a/etc/bin/rename_gradle_artifacts.sh +++ b/etc/bin/rename_gradle_artifacts.sh @@ -67,7 +67,7 @@ declare -a core_mappings=( "org[.]grails:grails-plugin-rest|org.apache.grails:grails-rest-transforms" "org[.]grails:grails-plugin-mimetypes|org.apache.grails:grails-mimetypes" "org[.]grails:grails-plugin-interceptors|org.apache.grails:grails-interceptors" -"org[.]grails:grails-plugin-i18n|org.apache.grails:grails-i18n" +"org[.]grails:grails-plugin-i18n|REMOVE_ME" # i18n is now included by default and should not be included explicitly "org[.]grails:grails-plugin-domain-class|org.apache.grails:grails-domain-class" "org[.]grails:grails-plugin-datasource|org.apache.grails:grails-datasource" "org[.]grails:grails-plugin-databinding|org.apache.grails:grails-databinding" @@ -109,7 +109,7 @@ declare -a excluded_core_mappings=( "exclude[[:space:]]+module[[:space:]]*:[[:space:]]*['\"]grails-plugin-rest['\"]|exclude module:'grails-rest-transforms'" "exclude[[:space:]]+module[[:space:]]*:[[:space:]]*['\"]grails-plugin-mimetypes['\"]|exclude module:'grails-mimetypes'" "exclude[[:space:]]+module[[:space:]]*:[[:space:]]*['\"]grails-plugin-interceptors['\"]|exclude module:'grails-interceptors'" -"exclude[[:space:]]+module[[:space:]]*:[[:space:]]*['\"]grails-plugin-i18n['\"]|exclude module:'grails-i18n'" +"exclude[[:space:]]+module[[:space:]]*:[[:space:]]*['\"]grails-plugin-i18n['\"]|exclude module:'REMOVE_THIS_EXCLUDE'" "exclude[[:space:]]+module[[:space:]]*:[[:space:]]*['\"]grails-plugin-domain-class['\"]|exclude module:'grails-domain-class'" "exclude[[:space:]]+module[[:space:]]*:[[:space:]]*['\"]grails-plugin-datasource['\"]|exclude module:'grails-datasource'" "exclude[[:space:]]+module[[:space:]]*:[[:space:]]*['\"]grails-plugin-databinding['\"]|exclude module:'grails-databinding'" diff --git a/grails-dependencies/starter-web/build.gradle b/grails-dependencies/starter-web/build.gradle index e12252310f7..45cb6206fde 100644 --- a/grails-dependencies/starter-web/build.gradle +++ b/grails-dependencies/starter-web/build.gradle @@ -45,7 +45,6 @@ def configurations = [ ':grails-encoder', ':grails-events', ':grails-gsp', - ':grails-i18n', ':grails-interceptors', System.getenv('SITEMESH3_TESTING_ENABLED') == 'true' ? ':grails-sitemesh3' : ':grails-layout', ':grails-logging', diff --git a/grails-doc/src/en/guide/commandLine/gradleBuild/gradleDependencies.adoc b/grails-doc/src/en/guide/commandLine/gradleBuild/gradleDependencies.adoc index f1303733fe0..eb526f4ab2a 100644 --- a/grails-doc/src/en/guide/commandLine/gradleBuild/gradleDependencies.adoc +++ b/grails-doc/src/en/guide/commandLine/gradleBuild/gradleDependencies.adoc @@ -32,7 +32,6 @@ dependencies { implementation "org.apache.grails:grails-core" implementation "org.apache.grails:grails-logging" implementation "org.apache.grails:grails-databinding" - implementation "org.apache.grails:grails-i18n" implementation "org.apache.grails:grails-interceptors" implementation "org.apache.grails:grails-rest-transforms" implementation "org.apache.grails:grails-services" diff --git a/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/grails/GrailsDefaultPluginsSpec.groovy b/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/grails/GrailsDefaultPluginsSpec.groovy index 9597ca77962..7a660340462 100644 --- a/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/grails/GrailsDefaultPluginsSpec.groovy +++ b/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/grails/GrailsDefaultPluginsSpec.groovy @@ -36,7 +36,6 @@ class GrailsDefaultPluginsSpec extends ApplicationContextSpec implements Command expect: buildGradle.contains("implementation \"org.apache.grails:grails-rest-transforms\"") buildGradle.contains("implementation \"org.apache.grails:grails-databinding\"") - buildGradle.contains("implementation \"org.apache.grails:grails-i18n\"") buildGradle.contains("implementation \"org.apache.grails:grails-services\"") buildGradle.contains("implementation \"org.apache.grails:grails-interceptors\"") } diff --git a/grails-i18n/build.gradle b/grails-i18n/build.gradle index fae78864ec1..5575f1bcc6e 100644 --- a/grails-i18n/build.gradle +++ b/grails-i18n/build.gradle @@ -24,7 +24,7 @@ plugins { } version = projectVersion -group = 'org.apache.grails' +group = 'org.apache.grails.i18n' dependencies { diff --git a/grails-profiles/base/profile.yml b/grails-profiles/base/profile.yml index f150003a5f7..1927e789a2f 100644 --- a/grails-profiles/base/profile.yml +++ b/grails-profiles/base/profile.yml @@ -45,8 +45,6 @@ dependencies: coords: "org.springframework.boot:spring-boot-starter" - scope: implementation coords: "org.apache.grails:grails-core" - - scope: implementation - coords: "org.apache.grails:grails-i18n" - scope: testImplementation coords: "org.apache.grails:grails-testing-support-datamapping" - scope: console diff --git a/grails-shell-cli/src/main/groovy/org/grails/cli/compiler/autoconfigure/GrailsCompilerAutoConfiguration.java b/grails-shell-cli/src/main/groovy/org/grails/cli/compiler/autoconfigure/GrailsCompilerAutoConfiguration.java index 49f05237d1e..3fdba6a8962 100644 --- a/grails-shell-cli/src/main/groovy/org/grails/cli/compiler/autoconfigure/GrailsCompilerAutoConfiguration.java +++ b/grails-shell-cli/src/main/groovy/org/grails/cli/compiler/autoconfigure/GrailsCompilerAutoConfiguration.java @@ -38,7 +38,7 @@ public void applyDependencies(DependencyCustomizer dependencies) { dependencies.ifAnyMissingClasses("grails.boot.config.GrailsAutoConfiguration").add("grails-boot"); dependencies.ifAnyMissingClasses("grails.core.DefaultGrailsApplication").add("grails-core"); dependencies.add("grails-web"); - dependencies.add("grails-i18n", "grails-codecs", "grails-controllers", + dependencies.add("grails-codecs", "grails-controllers", "grails-converters", "grails-databinding", "grails-interceptors", "grails-mimetypes", "grails-rest-transforms", "grails-url-mappings"); dependencies.add("gsp", "plain", "jar", true); diff --git a/grails-test-examples/cache/build.gradle b/grails-test-examples/cache/build.gradle index 9a9e9cf61f5..01ab8775c9c 100644 --- a/grails-test-examples/cache/build.gradle +++ b/grails-test-examples/cache/build.gradle @@ -37,7 +37,6 @@ dependencies { implementation 'org.apache.grails:grails-core' implementation 'org.apache.grails:grails-logging' implementation 'org.apache.grails:grails-databinding' - implementation 'org.apache.grails:grails-i18n' implementation 'org.apache.grails:grails-interceptors' implementation 'org.apache.grails:grails-rest-transforms' implementation 'org.apache.grails:grails-services' diff --git a/grails-test-examples/demo33/build.gradle b/grails-test-examples/demo33/build.gradle index c2711f4b17a..0d95401e403 100644 --- a/grails-test-examples/demo33/build.gradle +++ b/grails-test-examples/demo33/build.gradle @@ -35,7 +35,6 @@ dependencies { implementation 'org.apache.grails:grails-core' implementation 'org.apache.grails:grails-rest-transforms' implementation 'org.apache.grails:grails-databinding' - implementation 'org.apache.grails:grails-i18n' implementation 'org.apache.grails:grails-services' implementation 'org.apache.grails:grails-url-mappings' implementation 'org.apache.grails:grails-interceptors' diff --git a/grails-test-examples/external-configuration/build.gradle b/grails-test-examples/external-configuration/build.gradle index 8514f97902c..f977cb0beae 100644 --- a/grails-test-examples/external-configuration/build.gradle +++ b/grails-test-examples/external-configuration/build.gradle @@ -29,7 +29,6 @@ dependencies { implementation 'org.apache.grails:grails-core' implementation 'org.apache.grails:grails-logging' implementation 'org.apache.grails:grails-databinding' - implementation 'org.apache.grails:grails-i18n' implementation 'org.apache.grails:grails-interceptors' implementation 'org.apache.grails:grails-rest-transforms' implementation 'org.apache.grails:grails-services' diff --git a/grails-test-examples/geb-gebconfig/build.gradle b/grails-test-examples/geb-gebconfig/build.gradle index d6b4ffaf06f..19782d3db23 100644 --- a/grails-test-examples/geb-gebconfig/build.gradle +++ b/grails-test-examples/geb-gebconfig/build.gradle @@ -32,7 +32,6 @@ dependencies { implementation 'org.apache.grails:grails-core' implementation 'org.apache.grails:grails-logging' implementation 'org.apache.grails:grails-databinding' - implementation 'org.apache.grails:grails-i18n' implementation 'org.apache.grails:grails-interceptors' implementation 'org.apache.grails:grails-rest-transforms' implementation 'org.apache.grails:grails-services' diff --git a/grails-test-examples/geb/build.gradle b/grails-test-examples/geb/build.gradle index c5b403de709..3f690769c8b 100644 --- a/grails-test-examples/geb/build.gradle +++ b/grails-test-examples/geb/build.gradle @@ -32,7 +32,6 @@ dependencies { implementation 'org.apache.grails:grails-core' implementation 'org.apache.grails:grails-logging' implementation 'org.apache.grails:grails-databinding' - implementation 'org.apache.grails:grails-i18n' implementation 'org.apache.grails:grails-interceptors' implementation 'org.apache.grails:grails-rest-transforms' implementation 'org.apache.grails:grails-services' diff --git a/grails-test-examples/gsp-layout/build.gradle b/grails-test-examples/gsp-layout/build.gradle index f10622222f5..d7a20e94e8a 100644 --- a/grails-test-examples/gsp-layout/build.gradle +++ b/grails-test-examples/gsp-layout/build.gradle @@ -45,7 +45,6 @@ dependencies { runtimeOnly 'cloud.wondrify:asset-pipeline-grails' runtimeOnly 'org.fusesource.jansi:jansi' runtimeOnly 'org.apache.grails:grails-url-mappings' - runtimeOnly 'org.apache.grails:grails-i18n' runtimeOnly 'org.springframework.boot:spring-boot-autoconfigure' runtimeOnly 'org.springframework.boot:spring-boot-starter-logging' runtimeOnly 'org.springframework.boot:spring-boot-starter-tomcat' diff --git a/grails-test-examples/gsp-sitemesh3/build.gradle b/grails-test-examples/gsp-sitemesh3/build.gradle index eb15a775e5e..73e0e7cef2c 100644 --- a/grails-test-examples/gsp-sitemesh3/build.gradle +++ b/grails-test-examples/gsp-sitemesh3/build.gradle @@ -45,7 +45,6 @@ dependencies { runtimeOnly 'cloud.wondrify:asset-pipeline-grails' runtimeOnly 'org.fusesource.jansi:jansi' runtimeOnly 'org.apache.grails:grails-url-mappings' - runtimeOnly 'org.apache.grails:grails-i18n' runtimeOnly 'org.springframework.boot:spring-boot-autoconfigure' runtimeOnly 'org.springframework.boot:spring-boot-starter-logging' runtimeOnly 'org.springframework.boot:spring-boot-starter-tomcat' diff --git a/grails-test-examples/hibernate5/grails-data-service/build.gradle b/grails-test-examples/hibernate5/grails-data-service/build.gradle index 33d500af700..ff91350b7fb 100644 --- a/grails-test-examples/hibernate5/grails-data-service/build.gradle +++ b/grails-test-examples/hibernate5/grails-data-service/build.gradle @@ -37,7 +37,6 @@ dependencies { runtimeOnly 'com.h2database:h2' runtimeOnly 'com.zaxxer:HikariCP' runtimeOnly 'org.apache.grails:grails-databinding' - runtimeOnly 'org.apache.grails:grails-i18n' runtimeOnly 'org.apache.grails:grails-services' runtimeOnly 'org.apache.grails:grails-url-mappings' runtimeOnly 'org.springframework.boot:spring-boot-autoconfigure' diff --git a/grails-test-examples/hibernate5/grails-database-per-tenant/build.gradle b/grails-test-examples/hibernate5/grails-database-per-tenant/build.gradle index 04bca76239c..b7d149a2b11 100644 --- a/grails-test-examples/hibernate5/grails-database-per-tenant/build.gradle +++ b/grails-test-examples/hibernate5/grails-database-per-tenant/build.gradle @@ -47,7 +47,6 @@ dependencies { runtimeOnly 'com.h2database:h2' runtimeOnly 'com.zaxxer:HikariCP' runtimeOnly 'org.apache.grails:grails-databinding' - runtimeOnly 'org.apache.grails:grails-i18n' runtimeOnly 'org.apache.grails:grails-services' runtimeOnly 'org.apache.grails:grails-url-mappings' runtimeOnly 'org.apache.grails:grails-fields' diff --git a/grails-test-examples/hibernate5/grails-hibernate/build.gradle b/grails-test-examples/hibernate5/grails-hibernate/build.gradle index c65f8fb8172..cb8ed234763 100644 --- a/grails-test-examples/hibernate5/grails-hibernate/build.gradle +++ b/grails-test-examples/hibernate5/grails-hibernate/build.gradle @@ -49,7 +49,6 @@ dependencies { runtimeOnly 'com.h2database:h2' runtimeOnly 'com.zaxxer:HikariCP' runtimeOnly 'org.apache.grails:grails-databinding' - runtimeOnly 'org.apache.grails:grails-i18n' runtimeOnly 'org.apache.grails:grails-services' runtimeOnly 'org.apache.grails:grails-url-mappings' runtimeOnly 'org.apache.grails:grails-fields' diff --git a/grails-test-examples/hibernate5/grails-partitioned-multi-tenancy/build.gradle b/grails-test-examples/hibernate5/grails-partitioned-multi-tenancy/build.gradle index 05331c8dc04..2d0f12d7a02 100644 --- a/grails-test-examples/hibernate5/grails-partitioned-multi-tenancy/build.gradle +++ b/grails-test-examples/hibernate5/grails-partitioned-multi-tenancy/build.gradle @@ -47,7 +47,6 @@ dependencies { runtimeOnly 'com.h2database:h2' runtimeOnly 'com.zaxxer:HikariCP' runtimeOnly 'org.apache.grails:grails-databinding' - runtimeOnly 'org.apache.grails:grails-i18n' runtimeOnly 'org.apache.grails:grails-services' runtimeOnly 'org.apache.grails:grails-url-mappings' runtimeOnly 'org.apache.grails:grails-fields' diff --git a/grails-test-examples/hibernate5/grails-schema-per-tenant/build.gradle b/grails-test-examples/hibernate5/grails-schema-per-tenant/build.gradle index b9da357949c..cf033f116a7 100644 --- a/grails-test-examples/hibernate5/grails-schema-per-tenant/build.gradle +++ b/grails-test-examples/hibernate5/grails-schema-per-tenant/build.gradle @@ -47,7 +47,6 @@ dependencies { runtimeOnly 'com.h2database:h2' runtimeOnly 'com.zaxxer:HikariCP' runtimeOnly 'org.apache.grails:grails-databinding' - runtimeOnly 'org.apache.grails:grails-i18n' runtimeOnly 'org.apache.grails:grails-services' runtimeOnly 'org.apache.grails:grails-url-mappings' runtimeOnly 'org.apache.grails:grails-fields' diff --git a/grails-test-examples/hibernate5/issue450/build.gradle b/grails-test-examples/hibernate5/issue450/build.gradle index 3ff6b9847d2..fe533af8fdb 100644 --- a/grails-test-examples/hibernate5/issue450/build.gradle +++ b/grails-test-examples/hibernate5/issue450/build.gradle @@ -48,7 +48,6 @@ dependencies { runtimeOnly 'com.h2database:h2' runtimeOnly 'com.zaxxer:HikariCP' runtimeOnly 'org.apache.grails:grails-databinding' - runtimeOnly 'org.apache.grails:grails-i18n' runtimeOnly 'org.apache.grails:grails-services' runtimeOnly 'org.apache.grails:grails-url-mappings' runtimeOnly 'org.apache.grails:grails-fields' diff --git a/grails-test-examples/issue-11102/build.gradle b/grails-test-examples/issue-11102/build.gradle index ec92fe30b30..58b5b236016 100644 --- a/grails-test-examples/issue-11102/build.gradle +++ b/grails-test-examples/issue-11102/build.gradle @@ -46,7 +46,6 @@ dependencies { implementation 'org.apache.grails:grails-logging' implementation 'org.apache.grails:grails-rest-transforms' implementation 'org.apache.grails:grails-databinding' - implementation 'org.apache.grails:grails-i18n' implementation 'org.apache.grails:grails-services' implementation 'org.apache.grails:grails-url-mappings' implementation 'org.apache.grails:grails-interceptors' diff --git a/grails-test-examples/mongodb/base/build.gradle b/grails-test-examples/mongodb/base/build.gradle index f5e186241d5..d62ce74c201 100644 --- a/grails-test-examples/mongodb/base/build.gradle +++ b/grails-test-examples/mongodb/base/build.gradle @@ -45,7 +45,6 @@ dependencies { runtimeOnly 'cloud.wondrify:asset-pipeline-grails' runtimeOnly 'org.fusesource.jansi:jansi' - runtimeOnly 'org.apache.grails:grails-i18n' runtimeOnly 'org.apache.grails:grails-url-mappings' runtimeOnly 'org.apache.grails:grails-scaffolding' runtimeOnly 'org.springframework.boot:spring-boot-autoconfigure' diff --git a/grails-test-examples/mongodb/database-per-tenant/build.gradle b/grails-test-examples/mongodb/database-per-tenant/build.gradle index 74bc0b21de6..33b04f897b9 100644 --- a/grails-test-examples/mongodb/database-per-tenant/build.gradle +++ b/grails-test-examples/mongodb/database-per-tenant/build.gradle @@ -45,7 +45,6 @@ dependencies { runtimeOnly 'cloud.wondrify:asset-pipeline-grails' runtimeOnly 'org.fusesource.jansi:jansi' - runtimeOnly 'org.apache.grails:grails-i18n' runtimeOnly 'org.apache.grails:grails-url-mappings' runtimeOnly 'org.springframework.boot:spring-boot-autoconfigure' runtimeOnly 'org.springframework.boot:spring-boot-starter-logging' diff --git a/grails-test-examples/mongodb/hibernate5/build.gradle b/grails-test-examples/mongodb/hibernate5/build.gradle index ad703b02035..9f47b349768 100644 --- a/grails-test-examples/mongodb/hibernate5/build.gradle +++ b/grails-test-examples/mongodb/hibernate5/build.gradle @@ -49,7 +49,6 @@ dependencies { runtimeOnly 'com.zaxxer:HikariCP' runtimeOnly 'org.fusesource.jansi:jansi' runtimeOnly 'org.apache.grails:grails-scaffolding' - runtimeOnly 'org.apache.grails:grails-i18n' runtimeOnly 'org.apache.grails:grails-url-mappings' runtimeOnly "org.hibernate:hibernate-ehcache:$hibernate5Version", { // exclude javax variant of hibernate-core diff --git a/grails-test-examples/mongodb/test-data-service/build.gradle b/grails-test-examples/mongodb/test-data-service/build.gradle index 047dd7c41c0..55142af02c8 100644 --- a/grails-test-examples/mongodb/test-data-service/build.gradle +++ b/grails-test-examples/mongodb/test-data-service/build.gradle @@ -37,7 +37,6 @@ dependencies { implementation "org.apache.grails:grails-spring-security-rest:$grailsSpringSecurityVersion" implementation 'org.apache.grails:grails-views-gson' - runtimeOnly 'org.apache.grails:grails-i18n' runtimeOnly 'org.apache.grails:grails-url-mappings' runtimeOnly 'org.apache.grails:grails-events' runtimeOnly 'org.springframework.boot:spring-boot-autoconfigure' diff --git a/grails-test-examples/views-functional-tests/build.gradle b/grails-test-examples/views-functional-tests/build.gradle index a2d5d87077d..5416996a717 100644 --- a/grails-test-examples/views-functional-tests/build.gradle +++ b/grails-test-examples/views-functional-tests/build.gradle @@ -46,7 +46,6 @@ dependencies { } implementation 'org.apache.grails:grails-databinding' - implementation 'org.apache.grails:grails-i18n' implementation 'org.apache.grails:grails-interceptors' implementation 'org.apache.grails:grails-rest-transforms' implementation 'org.apache.grails:grails-services' diff --git a/grails-test-suite-persistence/build.gradle b/grails-test-suite-persistence/build.gradle index d00fd7ea9f1..37d61c34cc3 100644 --- a/grails-test-suite-persistence/build.gradle +++ b/grails-test-suite-persistence/build.gradle @@ -34,7 +34,6 @@ dependencies { testImplementation project(':grails-test-suite-base') testImplementation project(':grails-domain-class') testImplementation project(':grails-datasource') - testImplementation project(':grails-i18n') testImplementation project(':grails-url-mappings') testImplementation project(':grails-databinding') testImplementation project(':grails-services') diff --git a/grails-test-suite-uber/build.gradle b/grails-test-suite-uber/build.gradle index 0aadc990efd..a1ea256b245 100644 --- a/grails-test-suite-uber/build.gradle +++ b/grails-test-suite-uber/build.gradle @@ -34,7 +34,6 @@ dependencies { testImplementation project(':grails-databinding') testImplementation project(':grails-datasource') testImplementation project(':grails-domain-class') - testImplementation project(':grails-i18n') testImplementation project(':grails-interceptors') testImplementation project(':grails-rest-transforms') testImplementation project(':grails-services') diff --git a/grails-web-boot/build.gradle b/grails-web-boot/build.gradle index adaa00d995c..f1e2455cd56 100644 --- a/grails-web-boot/build.gradle +++ b/grails-web-boot/build.gradle @@ -36,7 +36,6 @@ dependencies { testImplementation project(':grails-controllers') testImplementation 'org.apache.tomcat.embed:tomcat-embed-core' - testRuntimeOnly project(':grails-i18n') testRuntimeOnly project(':grails-url-mappings') compileOnly 'jakarta.servlet:jakarta.servlet-api' From 490ff683e3bc1e83a2dbfe25bb469fde213b4f2a Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Mon, 1 Sep 2025 15:32:28 -0400 Subject: [PATCH 18/22] 14017 - cleanup - remove commented code --- .../gradle/plugin/views/gsp/GroovyPageForkCompileTask.groovy | 1 - 1 file changed, 1 deletion(-) diff --git a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/views/gsp/GroovyPageForkCompileTask.groovy b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/views/gsp/GroovyPageForkCompileTask.groovy index 65dec308d0c..c9f181895d2 100644 --- a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/views/gsp/GroovyPageForkCompileTask.groovy +++ b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/views/gsp/GroovyPageForkCompileTask.groovy @@ -145,7 +145,6 @@ abstract class GroovyPageForkCompileTask extends AbstractCompile { void execute(JavaExecSpec javaExecSpec) { javaExecSpec.mainClass.set(getCompilerName()) javaExecSpec.setClasspath(getClasspath()) - //javaExecSpec.setJvmArgs(['-Xmx2g', '-Xdebug', '-Xnoagent','-Djava.compiler=NONE', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005']) def jvmArgs = compileOptions.forkOptions.jvmArgs if (jvmArgs) { From 73410db845148349cea9d0ee6f82691704bcd176 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Tue, 2 Sep 2025 10:35:31 -0400 Subject: [PATCH 19/22] 14017 - license - fix group for project licensing configuration --- gradle/dependency-licenses.gradle | 2 +- grails-forge/gradle/dependency-licenses.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/dependency-licenses.gradle b/gradle/dependency-licenses.gradle index ae0a50e9635..24c7f836969 100644 --- a/gradle/dependency-licenses.gradle +++ b/gradle/dependency-licenses.gradle @@ -20,7 +20,7 @@ apply plugin: 'com.github.hierynomus.license-report' List licenseExclusions = rootProject.subprojects.collect { - "org.apache.grails:${it.findProperty('pomArtifactId') ?: it.name}:${rootProject.projectVersion}" as String + "${it.group}:${it.findProperty('pomArtifactId') ?: it.name}:${rootProject.projectVersion}" as String } downloadLicenses { diff --git a/grails-forge/gradle/dependency-licenses.gradle b/grails-forge/gradle/dependency-licenses.gradle index ae0a50e9635..24c7f836969 100644 --- a/grails-forge/gradle/dependency-licenses.gradle +++ b/grails-forge/gradle/dependency-licenses.gradle @@ -20,7 +20,7 @@ apply plugin: 'com.github.hierynomus.license-report' List licenseExclusions = rootProject.subprojects.collect { - "org.apache.grails:${it.findProperty('pomArtifactId') ?: it.name}:${rootProject.projectVersion}" as String + "${it.group}:${it.findProperty('pomArtifactId') ?: it.name}:${rootProject.projectVersion}" as String } downloadLicenses { From 6507fc8fbbc7d64dcbf669c215f5bf6204b24a95 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Tue, 2 Sep 2025 10:35:51 -0400 Subject: [PATCH 20/22] 14017 - styling - feedback --- .../GrailsDomainClassAutoConfiguration.groovy | 48 +++++++++---------- .../web/GroovyPagesPostProcessor.groovy | 12 +++-- .../GrailsMicronautGrailsPlugin.groovy | 31 ++++++------ 3 files changed, 46 insertions(+), 45 deletions(-) diff --git a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/GrailsDomainClassAutoConfiguration.groovy b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/GrailsDomainClassAutoConfiguration.groovy index b72c7acb290..b1f0e864b3a 100644 --- a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/GrailsDomainClassAutoConfiguration.groovy +++ b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/GrailsDomainClassAutoConfiguration.groovy @@ -19,16 +19,8 @@ package org.grails.plugins.domain -import grails.core.GrailsApplication -import grails.validation.ConstraintsEvaluator import groovy.transform.CompileStatic -import org.grails.datastore.gorm.validation.constraints.factory.ConstraintFactory -import org.grails.datastore.mapping.model.MappingContext -import org.grails.plugins.domain.support.ConstraintEvaluatorAdapter -import org.grails.plugins.domain.support.DefaultConstraintEvaluatorFactoryBean -import org.grails.plugins.domain.support.DefaultMappingContextFactoryBean -import org.grails.plugins.domain.support.ValidatorRegistryFactoryBean -import org.grails.plugins.i18n.I18nAutoConfiguration + import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Qualifier import org.springframework.boot.autoconfigure.AutoConfiguration @@ -38,6 +30,16 @@ import org.springframework.context.MessageSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Lazy +import grails.core.GrailsApplication +import grails.validation.ConstraintsEvaluator +import org.grails.datastore.gorm.validation.constraints.factory.ConstraintFactory +import org.grails.datastore.mapping.model.MappingContext +import org.grails.plugins.domain.support.ConstraintEvaluatorAdapter +import org.grails.plugins.domain.support.DefaultConstraintEvaluatorFactoryBean +import org.grails.plugins.domain.support.DefaultMappingContextFactoryBean +import org.grails.plugins.domain.support.ValidatorRegistryFactoryBean +import org.grails.plugins.i18n.I18nAutoConfiguration + @CompileStatic // TODO: datasource plugin is supposed to always load after this (currently will because this is a configuration) @AutoConfiguration(after = [I18nAutoConfiguration]) @@ -54,34 +56,30 @@ class GrailsDomainClassAutoConfiguration { List messageSources @Lazy - @Bean('grailsDomainClassMappingContext') - DefaultMappingContextFactoryBean grailsDomainClassMappingContext( - List constraintFactories - ) { - def bean = new DefaultMappingContextFactoryBean(grailsApplication, messageSources) - bean.constraintFactories = constraintFactories ?: [] - bean + @Bean(name = 'grailsDomainClassMappingContext') + DefaultMappingContextFactoryBean grailsDomainClassMappingContext(List factories) { + new DefaultMappingContextFactoryBean(grailsApplication, messageSources).tap { + constraintFactories = factories ?: [] + } } @Lazy @Bean - DefaultConstraintEvaluatorFactoryBean validateableConstraintsEvaluator(@Qualifier('grailsDomainClassMappingContext') MappingContext grailsDomainClassMappingContext) { - - new DefaultConstraintEvaluatorFactoryBean(messageSources, grailsDomainClassMappingContext, grailsApplication) + DefaultConstraintEvaluatorFactoryBean validateableConstraintsEvaluator(@Qualifier('grailsDomainClassMappingContext') MappingContext mappingContext) { + new DefaultConstraintEvaluatorFactoryBean(messageSources, mappingContext, grailsApplication) } @Lazy @Bean(name = ConstraintsEvaluator.BEAN_NAME) ConstraintEvaluatorAdapter constraintsEvaluator(DefaultConstraintEvaluatorFactoryBean validateableConstraintsEvaluator) { - def bean = new ConstraintEvaluatorAdapter(validateableConstraintsEvaluator.getObject()) - bean + new ConstraintEvaluatorAdapter(validateableConstraintsEvaluator.object) } @Lazy @Bean - ValidatorRegistryFactoryBean gormValidatorRegistry(@Qualifier('grailsDomainClassMappingContext') MappingContext grailsDomainClassMappingContext) { - def bean = new ValidatorRegistryFactoryBean() - bean.mappingContext = grailsDomainClassMappingContext - bean + ValidatorRegistryFactoryBean gormValidatorRegistry(@Qualifier('grailsDomainClassMappingContext') MappingContext mappingContext) { + new ValidatorRegistryFactoryBean().tap { + it.mappingContext = mappingContext + } } } diff --git a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesPostProcessor.groovy b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesPostProcessor.groovy index eb47f15bdbb..6555c47f1e0 100644 --- a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesPostProcessor.groovy +++ b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesPostProcessor.groovy @@ -19,13 +19,14 @@ package org.grails.plugins.web -import org.grails.web.servlet.view.GroovyPageViewResolver import org.springframework.beans.BeansException import org.springframework.beans.factory.support.BeanDefinitionRegistry import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor import org.springframework.beans.factory.support.GenericBeanDefinition import org.springframework.core.Ordered +import org.grails.web.servlet.view.GroovyPageViewResolver + /** * Registers a jspViewResolver bean definition if one does not already exist. */ @@ -39,10 +40,11 @@ class GroovyPagesPostProcessor implements BeanDefinitionRegistryPostProcessor, O @Override void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { if (!registry.containsBeanDefinition(JSP_VIEW_RESOLVER_BEAN_NAME)) { - GenericBeanDefinition beanDefinition = new GenericBeanDefinition() - beanDefinition.beanClass = GroovyPageViewResolver - beanDefinition.parentName = 'abstractViewResolver' - beanDefinition.lazyInit = true + GenericBeanDefinition beanDefinition = new GenericBeanDefinition().tap { + beanClass = GroovyPageViewResolver + parentName = 'abstractViewResolver' + lazyInit = true + } registry.registerBeanDefinition(JSP_VIEW_RESOLVER_BEAN_NAME, beanDefinition) } } diff --git a/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy index 411c2b094f0..4ec46a8435a 100644 --- a/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy +++ b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy @@ -19,16 +19,17 @@ package org.apache.grails.micronaut -import grails.plugins.GrailsPlugin -import grails.plugins.GrailsPluginManager -import grails.plugins.Plugin +import groovy.transform.CompileStatic import groovy.util.logging.Slf4j import io.micronaut.context.ConfigurableApplicationContext import io.micronaut.context.env.AbstractPropertySourceLoader -import io.micronaut.context.env.Environment import io.micronaut.context.env.PropertySource +import grails.plugins.GrailsPlugin +import grails.plugins.GrailsPluginManager +import grails.plugins.Plugin @Slf4j +@CompileStatic class GrailsMicronautGrailsPlugin extends Plugin { def grailsVersion = '7.0.0-SNAPSHOT > *' @@ -36,8 +37,8 @@ class GrailsMicronautGrailsPlugin extends Plugin { @Override void doWithApplicationContext() { - String[] beanNames = applicationContext.getBeanNamesForType(GrailsPluginManager) - GrailsPluginManager pluginManagerFromContext = beanNames.length ? + def beanNames = applicationContext.getBeanNamesForType(GrailsPluginManager) + def pluginManagerFromContext = beanNames.length ? applicationContext.getBean(GrailsPluginManager) : null @@ -50,23 +51,23 @@ class GrailsMicronautGrailsPlugin extends Plugin { throw new IllegalStateException('A Micronaut Application Context should exist prior to the loading of the Grails Micronaut plugin.') } - ConfigurableApplicationContext micronautContext = applicationContext.getBean('micronautApplicationContext', ConfigurableApplicationContext) - Environment micronautEnv = micronautContext.environment + def micronautContext = applicationContext.getBean('micronautApplicationContext', ConfigurableApplicationContext) + def micronautEnv = micronautContext.environment log.debug('Loading configurations from the plugins to the parent Micronaut context') - GrailsPlugin[] plugins = pluginManager.allPlugins - GrailsPlugin[] pluginsFromContext = pluginManagerFromContext ? pluginManagerFromContext.allPlugins : new GrailsPlugin[]{} + + def plugins = pluginManager.allPlugins + def pluginsFromContext = pluginManagerFromContext ? pluginManagerFromContext.allPlugins : new GrailsPlugin[0] int priority = AbstractPropertySourceLoader.DEFAULT_POSITION - [plugins, pluginsFromContext].each { GrailsPlugin[] pluginsToProcess -> + [plugins, pluginsFromContext].each { pluginsToProcess -> Arrays.stream(pluginsToProcess) - .filter({ GrailsPlugin plugin -> plugin.propertySource != null }) - .forEach({ GrailsPlugin plugin -> + .filter { plugin -> plugin.propertySource != null } + .forEach { plugin -> log.debug('Loading configurations from {} plugin to the parent Micronaut context', plugin.name) // If invoking the source as `.source`, the NavigableMapPropertySource will return null, while invoking the getter, it will return the correct value micronautEnv.addPropertySource(PropertySource.of("grails.plugins.$plugin.name", (Map) plugin.propertySource.getSource(), --priority)) - }) + } } micronautEnv.refresh() -// applicationContext.setParent(parentApplicationContext) } } From 08826bf7d7057a314eaef9002d45925b98d42d89 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Tue, 2 Sep 2025 11:20:31 -0400 Subject: [PATCH 21/22] 14017 - doc - add documentation for why parameters must always be enabled --- gradle/java-config.gradle | 2 +- grails-forge/gradle/java-config.gradle | 1 + grails-gradle/gradle/java-config.gradle | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gradle/java-config.gradle b/gradle/java-config.gradle index 43fb10fe6b9..46cb1956add 100644 --- a/gradle/java-config.gradle +++ b/gradle/java-config.gradle @@ -34,7 +34,7 @@ tasks.withType(Javadoc).configureEach { Javadoc it -> tasks.withType(GroovyCompile).configureEach { groovyOptions.encoding = 'UTF-8' // encoding needs to be the same since it's different across platforms - // Preserve method parameter names in Groovy classes for IDE parameter hints. + // Preserve method parameter names in Groovy/Java classes for IDE parameter hints & bean reflection metadata. groovyOptions.parameters = true options.encoding = 'UTF-8' // encoding needs to be the same since it's different across platforms options.fork = true diff --git a/grails-forge/gradle/java-config.gradle b/grails-forge/gradle/java-config.gradle index e7dc9438ce4..dab7db9cba3 100644 --- a/grails-forge/gradle/java-config.gradle +++ b/grails-forge/gradle/java-config.gradle @@ -27,6 +27,7 @@ extensions.configure(JavaPluginExtension) { tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' + // Preserve method parameter names in Java classes for IDE parameter hints & bean reflection metadata. options.compilerArgs.add('-parameters') } diff --git a/grails-gradle/gradle/java-config.gradle b/grails-gradle/gradle/java-config.gradle index 5990fbaabde..c5d538865a9 100644 --- a/grails-gradle/gradle/java-config.gradle +++ b/grails-gradle/gradle/java-config.gradle @@ -48,7 +48,7 @@ tasks.named('sourcesJar', Jar).configure { Jar jar -> tasks.withType(GroovyCompile).configureEach { groovyOptions.encoding = 'UTF-8' // encoding needs to be the same since it's different across platforms - // Preserve method parameter names in Groovy classes for IDE parameter hints. + // Preserve method parameter names in Groovy/Java classes for IDE parameter hints & bean reflection metadata. groovyOptions.parameters = true options.encoding = 'UTF-8' // encoding needs to be the same since it's different across platforms options.fork = true From a6c358187f870c1cc8446e484ba293c6bc459ee5 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Tue, 2 Sep 2025 11:28:14 -0400 Subject: [PATCH 22/22] 14017 - feedback - styling --- .../org/grails/plugins/web/GroovyPagesPostProcessor.groovy | 2 +- .../apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesPostProcessor.groovy b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesPostProcessor.groovy index 6555c47f1e0..c9606ee8f74 100644 --- a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesPostProcessor.groovy +++ b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesPostProcessor.groovy @@ -40,7 +40,7 @@ class GroovyPagesPostProcessor implements BeanDefinitionRegistryPostProcessor, O @Override void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { if (!registry.containsBeanDefinition(JSP_VIEW_RESOLVER_BEAN_NAME)) { - GenericBeanDefinition beanDefinition = new GenericBeanDefinition().tap { + def beanDefinition = new GenericBeanDefinition().tap { beanClass = GroovyPageViewResolver parentName = 'abstractViewResolver' lazyInit = true diff --git a/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy index 4ec46a8435a..08810ab0a63 100644 --- a/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy +++ b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy @@ -21,9 +21,11 @@ package org.apache.grails.micronaut import groovy.transform.CompileStatic import groovy.util.logging.Slf4j + import io.micronaut.context.ConfigurableApplicationContext import io.micronaut.context.env.AbstractPropertySourceLoader import io.micronaut.context.env.PropertySource + import grails.plugins.GrailsPlugin import grails.plugins.GrailsPluginManager import grails.plugins.Plugin