You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by bo...@apache.org on 2026/08/06 15:56:57 UTC
(grails-core) 17/17: Merge remote-tracking branch 'origin/8.0.x' into feat/gorm-registry-consolidated
This is an automated email from the ASF dual-hosted git repository.
borinquenkid pushed a commit to branch feat/gorm-registry-consolidated
in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit bd16af77381f5bcb00119b762a55837d2796abbc
Merge: 5f45fb144b 93fd522fb6
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Thu Aug 6 10:24:49 2026 -0500
Merge remote-tracking branch 'origin/8.0.x' into feat/gorm-registry-consolidated
# Conflicts:
# grails-doc/src/en/guide/upgrading/upgrading80x.adoc
.agents/skills/gradle-developer/SKILL.md | 701 +++++
.agents/skills/grails-developer/SKILL.md | 2 +-
.agents/skills/groovy-developer/SKILL.md | 2 +-
.github/dependabot.yml | 4 +
.github/workflows/coverage.yml | 2 +-
.github/workflows/end-to-end.yml | 7 +-
.github/workflows/gradle.yml | 5 +
.github/workflows/release-notes.yml | 2 +-
.github/workflows/validate-actions.yml | 59 +
AGENTS.md | 12 +-
build-logic/plugins/build.gradle | 15 +
.../buildsrc/AutoConfigurationImportsPlugin.groovy | 66 +
.../GenerateAutoConfigurationImportsTask.groovy | 181 ++
.../GrailsDependencyValidatorPlugin.groovy | 145 +-
.../buildsrc/GrailsValidateActionsPlugin.groovy | 62 +
.../org/apache/grails/buildsrc/SbomPlugin.groovy | 25 +-
.../grails/buildsrc/ValidateActionsTask.groovy | 236 ++
.../buildsrc/ValidateDependencyVersionsTask.groovy | 100 +
.../ValidateProductionClasspathTask.groovy | 102 +
.../grails/buildsrc/VulnerabilityScanPlugin.groovy | 5 -
...GenerateAutoConfigurationImportsTaskSpec.groovy | 195 ++
build-logic/settings.gradle | 8 +
build.gradle | 1 +
dependencies.gradle | 32 +-
end-to-end/README.md | 16 +
end-to-end/gradle/test-config.gradle | 35 +
end-to-end/legacy-commands/build.gradle | 5 +-
end-to-end/settings.gradle | 17 +
.../spring-dependency-management/build.gradle | 38 +-
.../grails-app/conf/application.yml | 0
.../grails-app/controllers/UrlMappings.groovy | 0
.../controllers/springdm/HelloController.groovy | 0
.../grails-app/init/springdm/Application.groovy | 0
.../grails-app/views/error.gsp | 0
.../grails-app/views/index.gsp | 0
.../grails-app/views/notFound.gsp | 0
.../groovy/springdm/HelloControllerSpec.groovy | 0
etc/bin/extract-build-artifact.sh | 6 +-
etc/bin/verify-reproducible.sh | 7 +-
gradle/docs-dependencies.gradle | 1 -
gradle/functional-test-config.gradle | 84 +-
gradle/publish-root-config.gradle | 1 +
.../build.gradle | 45 +-
.../java/grails/compiler/beans/GrailsBeans.java | 136 +
.../beans/GrailsBeansASTTransformation.java | 1384 +++++++++
.../beans/GrailsBeansASTTransformationSpec.groovy | 3151 ++++++++++++++++++++
grails-bom/base/build.gradle | 6 +
grails-bom/hibernate5-micronaut/build.gradle | 3 +
grails-bom/hibernate5/build.gradle | 3 +
grails-bom/hibernate7-micronaut/build.gradle | 3 +
grails-bom/hibernate7/build.gradle | 3 +
grails-bom/micronaut/build.gradle | 3 +
grails-bootstrap/build.gradle | 50 +-
.../groovy/grails/build/logging/ConsoleLogger.java | 0
.../groovy/grails/build/logging/GrailsConsole.java | 154 +-
.../grails/build/logging/GrailsEclipseConsole.java | 0
.../CandidateListCompletionHandler.java | 0
.../org/grails/build/logging/ConsoleAnsi.java | 146 +
.../build/logging/GrailsConsoleAntBuilder.java | 0
.../build/logging/GrailsConsoleBuildListener.java | 0
.../logging/GrailsConsoleErrorPrintStream.java | 0
.../build/logging/GrailsConsolePrintStream.java | 0
.../org/grails/io/watch/DirectoryWatcher.java | 74 +-
.../logging/GrailsConsoleCompleterSpec.groovy | 0
.../grails/build/logging/GrailsConsoleSpec.groovy | 298 ++
.../CandidateListCompletionHandlerSpec.groovy | 0
.../grails/build/logging/GrailsConsoleSpec.groovy | 109 -
.../grails/io/watch/DirectoryWatcherSpec.groovy | 253 ++
.../grails/plugin/cache/CacheGrailsPlugin.groovy | 97 +-
.../cache/GrailsCacheAutoConfiguration.groovy | 69 -
...rk.boot.autoconfigure.AutoConfiguration.imports | 2 +-
...ec.groovy => CacheAutoConfigurationSpec.groovy} | 87 +-
.../plugin/cache/CacheGrailsPluginSpec.groovy | 73 -
grails-console/build.gradle | 1 -
grails-controllers/build.gradle | 1 -
.../controllers/ControllersAutoConfiguration.java | 4 +-
grails-core/build.gradle | 20 +
.../injection/ArtefactTypeAstTransformation.java | 25 +-
.../GlobalGrailsClassInjectorTransformation.groovy | 96 +
.../org/grails/plugins/CoreGrailsPlugin.groovy | 175 +-
.../grails/plugins/core/CoreAutoConfiguration.java | 69 -
.../AbstractResourceLocatorPostProcessor.java | 82 +
...sIgnoringComponentScanBeanDefinitionParser.java | 170 +-
.../GrailsComponentScanPostProcessor.java | 95 +
.../support/GrailsPlaceholderConfigurer.java | 14 +-
...rk.boot.autoconfigure.AutoConfiguration.imports | 2 +-
.../core/cli/ApplicationCommandProviderSpec.groovy | 0
.../grails/core/cli/ConfigReportCommandSpec.groovy | 0
.../CommandFactoriesTransformationSpec.groovy | 0
.../resources/META-INF/grails-cli.factories | 0
...aceHolderConfigurerCorePluginRuntimeSpec.groovy | 73 -
...balGrailsClassInjectorTransformationSpec.groovy | 91 +
.../plugins/CoreAutoConfigurationSpec.groovy | 178 ++
.../plugins/CoreGrailsPluginRegistrarSpec.groovy | 229 ++
.../grails/plugins/SpringBeanPackagesSpec.groovy | 86 +
.../grails/plugins/scan/ScannedComponent.groovy | 22 +-
grails-data-hibernate5/dbmigration/build.gradle | 4 +
.../databasemigration/DbUpdateCommandSpec.groovy | 0
...ationContextDatabaseMigrationCommandSpec.groovy | 0
.../cli/DatabaseMigrationCommandConfigSpec.groovy | 0
.../cli/DatabaseMigrationCommandSpec.groovy | 0
.../cli/DbmChangelogSyncCommandSpec.groovy | 0
.../cli/DbmChangelogSyncCommandSqlSpec.groovy | 0
.../cli/DbmClearChecksumsCommandSpec.groovy | 0
.../dbmigration/cli/DbmDiffCommandSpec.groovy | 0
.../dbmigration/cli/DbmDropAllCommandSpec.groovy | 0
.../DbmFutureRollbackCountSqlCommandSpec.groovy | 0
.../cli/DbmFutureRollbackSqlCommandSpec.groovy | 0
.../cli/DbmGenerateChangelogCommandSpec.groovy | 0
.../cli/DbmGenerateGormChangelogCommandSpec.groovy | 0
.../dbmigration/cli/DbmGormDiffCommandSpec.groovy | 0
.../dbmigration/cli/DbmListLocksCommandSpec.groovy | 0
.../cli/DbmMarkNextChangesetRanCommandSpec.groovy | 0
.../DbmMarkNextChangesetRanSqlCommandSpec.groovy | 0
.../cli/DbmPreviousChangesetSqlCommandSpec.groovy | 0
.../cli/DbmReleaseLocksCommandSpec.groovy | 0
.../dbmigration/cli/DbmRollbackCommandSpec.groovy | 0
.../cli/DbmRollbackCountCommandSpec.groovy | 0
.../cli/DbmRollbackCountSqlCommandSpec.groovy | 0
.../cli/DbmRollbackSqlCommandSpec.groovy | 0
.../cli/DbmRollbackToDateCommandSpec.groovy | 0
.../cli/DbmRollbackToDateSqlCommandSpec.groovy | 0
.../dbmigration/cli/DbmStatusCommandSpec.groovy | 0
.../dbmigration/cli/DbmUpdateCommandSpec.groovy | 0
.../cli/DbmUpdateCountCommandSpec.groovy | 0
.../cli/DbmUpdateCountSqlCommandSpec.groovy | 0
.../dbmigration/cli/DbmUpdateSqlCommandSpec.groovy | 0
.../dbmigration/cli/DbmValidateCommandSpec.groovy | 0
.../cli/ScriptDatabaseMigrationCommandSpec.groovy | 0
.../liquibase/GroovyChangeLogSpec.groovy | 0
.../liquibase/GroovyPreconditionSpec.groovy | 0
.../src/test-cli/resources/logging.properties | 2 +-
grails-data-hibernate5/docs/build.gradle | 1 -
grails-data-hibernate7/dbmigration/build.gradle | 5 +
.../databasemigration/DbUpdateCommandSpec.groovy | 0
...ationContextDatabaseMigrationCommandSpec.groovy | 0
.../cli/DatabaseMigrationCommandConfigSpec.groovy | 0
.../cli/DatabaseMigrationCommandSpec.groovy | 0
.../cli/DbmChangelogSyncCommandSpec.groovy | 0
.../cli/DbmChangelogSyncCommandSqlSpec.groovy | 0
.../cli/DbmClearChecksumsCommandSpec.groovy | 0
.../dbmigration/cli/DbmDiffCommandSpec.groovy | 0
.../dbmigration/cli/DbmDropAllCommandSpec.groovy | 0
.../DbmFutureRollbackCountSqlCommandSpec.groovy | 0
.../cli/DbmFutureRollbackSqlCommandSpec.groovy | 0
.../cli/DbmGenerateChangelogCommandSpec.groovy | 0
.../cli/DbmGenerateGormChangelogCommandSpec.groovy | 0
.../dbmigration/cli/DbmGormDiffCommandSpec.groovy | 0
.../dbmigration/cli/DbmListLocksCommandSpec.groovy | 0
.../cli/DbmMarkNextChangesetRanCommandSpec.groovy | 0
.../DbmMarkNextChangesetRanSqlCommandSpec.groovy | 0
.../cli/DbmPreviousChangesetSqlCommandSpec.groovy | 0
.../cli/DbmReleaseLocksCommandSpec.groovy | 0
.../dbmigration/cli/DbmRollbackCommandSpec.groovy | 0
.../cli/DbmRollbackCountCommandSpec.groovy | 0
.../cli/DbmRollbackCountSqlCommandSpec.groovy | 0
.../cli/DbmRollbackSqlCommandSpec.groovy | 0
.../cli/DbmRollbackToDateCommandSpec.groovy | 0
.../cli/DbmRollbackToDateSqlCommandSpec.groovy | 0
.../dbmigration/cli/DbmStatusCommandSpec.groovy | 0
.../dbmigration/cli/DbmUpdateCommandSpec.groovy | 0
.../cli/DbmUpdateCountCommandSpec.groovy | 0
.../cli/DbmUpdateCountSqlCommandSpec.groovy | 0
.../dbmigration/cli/DbmUpdateSqlCommandSpec.groovy | 0
.../dbmigration/cli/DbmValidateCommandSpec.groovy | 0
.../cli/ScriptDatabaseMigrationCommandSpec.groovy | 0
.../liquibase/GroovyChangeLogSpec.groovy | 0
.../liquibase/GroovyPreconditionSpec.groovy | 0
.../src/test-cli/resources/logging.properties | 2 +-
grails-data-hibernate7/docs/build.gradle | 1 -
grails-data-mongodb/docs/build.gradle | 1 -
grails-data-neo4j/docs/build.gradle | 1 -
grails-data-neo4j/gradle.properties | 1 -
grails-databinding/build.gradle | 1 +
.../databinding/DataBindingConfiguration.java | 132 -
.../databinding/DataBindingGrailsPlugin.groovy | 87 +
...rk.boot.autoconfigure.AutoConfiguration.imports | 1 -
grails-dependencies/starter-web/build.gradle | 12 +-
.../guide/commandLine/creatingCustomCommands.adoc | 9 +-
.../gradleBuild/gradleDependencies.adoc | 1 -
.../applicationClass/applicationLifeCycle.adoc | 2 +
.../plugins/hookingIntoRuntimeConfiguration.adoc | 142 +
.../en/guide/plugins/providingBasicArtefacts.adoc | 9 +
.../src/en/guide/spring/springdslAdditional.adoc | 38 +
.../src/en/guide/upgrading/upgrading70x.adoc | 6 +-
.../src/en/guide/upgrading/upgrading80x.adoc | 337 ++-
.../DomainClassEnvironmentPostProcessor.groovy | 70 +
.../plugins/domain/DomainClassGrailsPlugin.groovy | 45 +-
.../GrailsDomainClassAutoConfiguration.groovy | 78 -
.../src/main/resources/META-INF/spring.factories | 5 +-
...rk.boot.autoconfigure.AutoConfiguration.imports | 2 +-
.../domain/AutoTimestampCacheDefaultSpec.groovy | 97 +
.../domain/DomainClassGrailsPluginSpec.groovy | 65 -
grails-forge/gradle.properties | 4 +-
grails-forge/grails-forge-cli/build.gradle | 7 +-
.../org/grails/forge/cli/InteractiveShell.java | 32 +-
.../org/grails/forge/feature/view/Scaffolding.java | 5 -
.../forge/feature/view/ScaffoldingSpec.groovy | 4 +-
grails-forge/settings.gradle | 10 +-
grails-gradle/bom/build.gradle | 3 +
grails-gradle/gradle/docs-config.gradle | 1 -
grails-gradle/model/build.gradle | 1 -
.../plugin/bom/BomPropertyOverridesPlugin.groovy | 8 +
.../commands/GrailsCliArtifactGradlePlugin.groovy | 97 +-
.../gradle/plugin/core/GrailsGradlePlugin.groovy | 88 +-
.../plugin/core/GrailsPluginGradlePlugin.groovy | 116 +-
.../plugin/core/TestPhasesGradlePlugin.groovy | 2 +-
.../plugin/views/gsp/GroovyPagePlugin.groovy | 4 -
.../bom/BomPropertyOverridesPluginSpec.groovy | 20 +
.../PluginScriptCommandPackagingSpec.groovy | 129 +
.../plugin/core/TestPhasesGradlePluginSpec.groovy | 108 +
.../gsp/GroovyPagePluginFunctionalSpec.groovy | 65 +
.../gsp-compile-classpath/build.gradle | 37 +
.../compile-classpath-marker/marker.txt | 1 +
.../provided-compile-marker/marker.txt | 1 +
.../gsp-compile-classpath/settings.gradle | 1 +
.../plugin-script-commands/gradle.properties | 2 +
.../plugin-with-cli/build.gradle | 89 +
.../grails-app/views/sample/show.gsp | 1 +
.../resources/META-INF/commands/hand-authored.yml | 1 +
.../src/main/scripts/example-multi-step.yml | 3 +
.../src/main/scripts/example-script.groovy | 5 +
.../plugin-with-cli/src/main/templates/example.gsp | 1 +
.../plugin-with-cli/src/main/templates/example.txt | 1 +
.../plugin-without-cli/build.gradle | 38 +
.../src/main/scripts/legacy-only-script.groovy | 5 +
.../src/main/templates/legacy-only.gsp | 1 +
.../src/main/templates/legacy-only.txt | 1 +
.../plugin-script-commands/settings.gradle | 3 +
grails-gradle/settings.gradle | 8 +
.../sitemesh3/Sitemesh3AutoConfiguration.groovy | 131 -
.../Sitemesh3EnvironmentPostProcessor.groovy | 38 +-
.../plugins/sitemesh3/Sitemesh3GrailsPlugin.groovy | 119 +-
.../src/main/resources/META-INF/spring.factories | 2 +-
grails-gsp/grails-web-gsp/build.gradle | 1 +
.../web/taglib/AbstractGrailsTagTests.groovy | 24 +-
grails-i18n/build.gradle | 1 +
.../GrailsLocaleResolverAutoConfiguration.java | 22 +-
.../grails/plugins/i18n/I18nAutoConfiguration.java | 159 -
.../grails/plugins/i18n/I18nGrailsPlugin.groovy | 104 +-
...railsLocaleResolverAutoConfigurationSpec.groovy | 24 +
.../plugins/i18n/I18nAutoConfigurationSpec.groovy | 31 +
grails-mail/build.gradle | 3 +
.../plugins/mail/MailAutoConfiguration.groovy | 118 -
.../grails/plugins/mail/MailGrailsPlugin.groovy | 79 +-
.../plugins/mail/MailAutoConfigurationSpec.groovy | 150 +
grails-profiles/base/profile.yml | 2 -
grails-scaffolding/build.gradle | 4 -
grails-shell-cli/build.gradle | 13 +-
...SpringApplicationWebApplicationInitializer.java | 15 +-
...ApplicationWebApplicationInitializerSpec.groovy | 97 +
.../profile/commands/CreateAppCommandSpec.groovy | 2 +-
.../cas/plugin/grails-app/conf/logback.xml | 1 -
.../ldap/plugin/grails-app/conf/logback.xml | 1 -
grails-spring-security/oauth2/plugin/build.gradle | 2 -
grails-spring-security/plugin/build.gradle | 2 -
grails-spring-security/ui/plugin/build.gradle | 12 +-
grails-test-core/build.gradle | 5 +-
.../grails/test/io/SystemOutAndErrSwapper.groovy | 24 +-
.../async-events-pubsub-demo/build.gradle | 1 -
.../grails-app/conf/logback.xml | 1 -
.../integration-test/resources/logback-test.xml | 1 -
.../beans-dsl-plugin}/build.gradle | 47 +-
.../groovy/beandsl/example/plugin/Farewell.groovy} | 14 +-
.../example/plugin/FarewellGrailsPlugin.groovy | 47 +
.../groovy/beandsl/example/plugin/Greeting.groovy} | 14 +-
.../example/plugin/GreetingGrailsPlugin.groovy | 52 +
.../FarewellGrailsPluginAutoDiscoverySpec.groovy | 74 +
.../GreetingGrailsPluginAutoDiscoverySpec.groovy | 82 +
.../beans-dsl}/build.gradle | 44 +-
.../groovy/beandsl/example/ExampleBeans.groovy} | 30 +-
.../groovy/beandsl/example/FancyGreeter.groovy} | 20 +-
.../main/groovy/beandsl/example/Greeter.groovy} | 14 +-
.../main/groovy/beandsl/example/LoudGreeter.groovy | 26 +-
.../ExampleBeansAutoConfigurationSpec.groovy | 74 +
.../example/ExampleBeansAutoDiscoverySpec.groovy | 62 +
grails-test-examples/cache/build.gradle | 1 -
.../external-configuration/build.gradle | 1 -
.../grails-app/conf/logback-spring.xml | 1 -
grails-test-examples/geb-context-path/build.gradle | 1 -
grails-test-examples/geb-gebconfig/build.gradle | 1 -
.../grails-app/conf/logback-spring.xml | 1 -
grails-test-examples/geb/build.gradle | 1 -
.../geb/grails-app/conf/logback-spring.xml | 1 -
grails-test-examples/gsp-layout/build.gradle | 1 -
.../gsp-layout/grails-app/conf/logback-spring.xml | 1 -
.../views/gsp/layout/AbstractGrailsTagTests.groovy | 24 +-
grails-test-examples/gsp-sitemesh3/build.gradle | 1 -
.../grails-app/conf/logback-spring.xml | 1 -
.../async-events-pubsub-demo/build.gradle | 1 -
.../grails-app/conf/logback.xml | 1 -
.../integration-test/resources/logback-test.xml | 1 -
.../issue-10279/grails-app/conf/logback.xml | 1 -
.../issue-11767/grails-app/conf/logback.xml | 1 -
.../issue-15228/grails-app/conf/logback.xml | 1 -
grails-test-examples/jetty/build.gradle | 1 -
.../jetty/grails-app/conf/logback-spring.xml | 1 -
grails-test-examples/mail/build.gradle | 1 -
.../mail/grails-app/conf/logback-spring.xml | 1 -
grails-test-examples/mongodb/base/build.gradle | 1 -
.../mongodb/database-per-tenant/build.gradle | 1 -
.../mongodb/hibernate5/build.gradle | 1 -
grails-test-examples/redis/build.gradle | 1 -
grails-test-examples/scaffolding/build.gradle | 1 -
.../acl/functional-test-app/build.gradle | 1 -
.../grails-app/conf/logback.xml | 1 -
.../grails-app/conf/logback.xml | 1 -
.../spring-security/cas/test1/build.gradle | 1 -
.../cas/test1/grails-app/conf/logback.xml | 1 -
.../build.gradle | 1 -
.../grails-app/conf/logback-spring.xml | 1 -
.../ldap/functional-test-app/build.gradle | 1 -
.../grails-app/conf/logback-spring.xml | 1 -
.../ldap/retrieve-db-roles/build.gradle | 1 -
.../grails-app/conf/logback-spring.xml | 1 -
.../ldap/retrieve-group-roles/build.gradle | 1 -
.../grails-app/conf/logback-spring.xml | 1 -
.../spring-security/ui/extended/build.gradle | 1 -
.../ui/extended/grails-app/conf/logback.xml | 1 -
.../spring-security/ui/simple/build.gradle | 1 -
.../ui/simple/grails-app/conf/logback.xml | 1 -
grails-test-examples/undertow/build.gradle | 1 -
.../undertow/grails-app/conf/logback-spring.xml | 1 -
grails-test-report/build.gradle | 9 +-
.../grails/plugins/CoreGrailsPluginTests.groovy | 68 +-
grails-url-mappings/build.gradle | 1 +
.../web/mapping/UrlMappingsAutoConfiguration.java | 102 -
.../web/mapping/UrlMappingsGrailsPlugin.groovy | 63 +-
.../UrlMappingsAutoConfigurationSpec.groovy | 84 +
grails-web-url-mappings/build.gradle | 8 +-
.../AnsiConsoleUrlMappingsRenderer.groovy | 28 +-
.../AnsiConsoleUrlMappingsRendererSpec.groovy | 0
.../mapping/UrlMappingsWithHttpMethodSpec.groovy | 1 -
settings.gradle | 21 +-
334 files changed, 11960 insertions(+), 2105 deletions(-)
diff --cc grails-doc/src/en/guide/upgrading/upgrading80x.adoc
index 655edf3df1,2d777e80cc..0c354b2945
--- a/grails-doc/src/en/guide/upgrading/upgrading80x.adoc
+++ b/grails-doc/src/en/guide/upgrading/upgrading80x.adoc
@@@ -1941,74 -1987,271 +1987,343 @@@ tests — keeps the previous fallback b
configuration applied. The filterer is JVM-global rather than per-context, so in a JVM hosting more than one
application context the last one booted supplies the filterer for all of them.
- ==== 39. GORM API Resolution Moves to a Registry
+ ==== 41. Jansi Removed and Developer Tooling Off the Application Classpath
+
+ Grails no longer depends on a separate ANSI library. The console renders its escape sequences directly,
+ and the FuseSource Jansi artifact - unmaintained, and the subject of an unfixed CVE - is gone from the
+ dependency graph along with the `org.jline:jansi` fork that briefly replaced it.
+
+ At the same time, developer-only tooling no longer ships with an application. These artifacts could reach
+ an application's production runtime classpath, by a different route for each:
+
+ * `org.apache.grails:grails-console` - the Swing console, the Groovy shell, and the script and command
+ runners - and the `org.apache.groovy:groovy-console`, `groovy-groovysh` and `groovy-swing` libraries it
+ brings with it, through the `console` configuration the application generator declared
+ * the JLine family, including `org.jline:jansi`, and the FuseSource Jansi artifact, declared directly by
+ the generated build
+
+ None of these are on an application's runtime classpath now. They are provisioned onto the `grailsCli`
+ configuration instead, which the Grails Gradle plugin puts on the compile and test classpaths but never on
+ `runtimeClasspath` - so `bootRun`, `bootJar` and `bootWar` no longer carry them. The `console` and `shell`
+ tasks are unaffected and continue to work exactly as before.
+
+ ===== What you need to change
+
+ Applications generated by earlier versions of Grails declare Jansi explicitly:
+
+ [source,groovy]
+ .build.gradle
+ ----
+ runtimeOnly "org.fusesource.jansi:jansi"
+ ----
+
+ Delete that line. New projects are generated without it.
+
+ If your own code imports Jansi directly, it must move off it - there is no Grails-managed replacement
+ coordinate. Application code that needs coloured output should use Spring Boot's
+ `org.springframework.boot.ansi.AnsiOutput`, or JLine's `org.jline.utils.AttributedStringBuilder` if the
+ project already depends on JLine.
+
+ If your code, or a `runtimeOnly` dependency of it, genuinely needs the Groovy shell, Swing console or JLine
+ at application runtime, declare that dependency explicitly rather than relying on the starter:
+
+ [source,groovy]
+ .build.gradle
+ ----
+ runtimeOnly "org.apache.groovy:groovy-groovysh"
+ ----
+
+ ===== Controlling ANSI output
+
+ Jansi's global switch went away with the library. Console colour is now driven by Spring Boot's own
+ property, so it is configured in one place alongside the rest of the application's output settings:
+
+ [source,yaml]
+ .application.yml
+ ----
+ spring:
+ output:
+ ansi:
+ enabled: never # always | detect | never
+ ----
+
+ `detect` is the default and keeps the previous behaviour - colour only when the attached terminal
+ supports it. `never` suppresses it entirely, and `always` forces it on even when the terminal is not
+ detected as capable, which is useful for CI logs that render ANSI.
+
+ The same property works as a system property, which is how the CLI reads it since it has no Spring
+ `Environment` to bind from:
+
+ [source,bash]
+ ----
+ grails -Dspring.output.ansi.enabled=never run-app
+ ----
+
+ Note that passing `-D` to `gradlew` sets the property on the Gradle daemon, not on the JVM that
+ `bootRun` forks for your application, so it has no effect there. To disable colour for `bootRun`, use
+ the `application.yml` form above or set it on the task itself:
+
+ [source,groovy]
+ ----
+ tasks.named('bootRun') {
+ systemProperty 'spring.output.ansi.enabled', 'never'
+ }
+ ----
+
+ If you previously disabled colour through Jansi's own switch, replace it - the property no longer has any
+ effect now that the library is gone:
+
+ [cols="1,1"]
+ |===
+ |Before |Now
+
+ |`-Dorg.fusesource.jansi.Ansi.disable=true`
+ |`-Dspring.output.ansi.enabled=never`
+ |===
+
+ ===== Remove `withJansi` from your Logback configuration
+
+ Logback's `ConsoleAppender` has a `withJansi` option that loads `org.fusesource.jansi.AnsiConsole` by
+ name to wrap the output stream. With Jansi gone from the dependency graph, an application that still
+ enables it logs a warning on every startup and falls back to the plain stream:
+
+ [source]
+ ----
+ -WARN in ch.qos.logback.core.ConsoleAppender[STDOUT] - Failed to create AnsiPrintStream. Falling back
+ on the default stream. java.lang.ClassNotFoundException: org.fusesource.jansi.AnsiConsole
+ ----
+
+ Delete the element from `grails-app/conf/logback.xml` or `logback-spring.xml`:
+
+ [source,xml]
+ ----
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <withJansi>true</withJansi> <!--1-->
+ <encoder>
+ ...
+ </encoder>
+ </appender>
+ ----
+ <1> remove this line
+
+ Nothing is lost. Coloured log output comes from Spring Boot's `ColorConverter` - the `%clr(...)` tokens
+ in the encoder pattern - which is independent of Jansi and honours `spring.output.ansi.enabled`. The
+ `withJansi` option only wrapped the stream for legacy Windows consoles.
+
+ Applications generated by recent versions of Grails already omit it: Jansi's global `System.out`
+ replacement breaks console logging after a Spring Boot DevTools restart
+ (https://github.com/apache/grails-core/issues/15663[issue #15663]), so it was removed from the
+ generated configuration before Jansi itself was dropped. Only applications carrying older
+ configuration forward need this change.
+
+ ===== `GrailsConsole` moved to a companion artifact
+
+ The console classes are developer tooling, so they now ship as `grails-bootstrap`'s CLI companion
+ rather than in the artifact applications depend on. These types moved out of
+ `org.apache.grails.bootstrap:grails-bootstrap` and into
+ `org.apache.grails.bootstrap:grails-bootstrap-cli`:
+
+ * `grails.build.logging.GrailsConsole`
+ * `grails.build.logging.ConsoleLogger`
+ * `grails.build.logging.GrailsEclipseConsole`
+ * `org.grails.build.logging.GrailsConsolePrintStream`
+ * `org.grails.build.logging.GrailsConsoleErrorPrintStream`
+ * `org.grails.build.logging.GrailsConsoleAntBuilder`
+ * `org.grails.build.logging.GrailsConsoleBuildListener`
+ * `org.grails.build.interactive.CandidateListCompletionHandler`
+
+ The URL mappings report renderer moved the same way, out of `org.apache.grails:grails-url-mappings`
+ and into `org.apache.grails:grails-url-mappings-cli`:
+
+ * `org.grails.web.mapping.reporting.AnsiConsoleUrlMappingsRenderer`
+
+ Their package names are unchanged - only the artifact that carries them is different.
+
+ Command code needs no change: the CLI tier is auto-provisioned onto `grailsCli`, so commands in
+ `grails-app/commands` and in a plugin's `src/cli` continue to see `GrailsConsole` as before.
+
+ If application code (not command code) references any of these types, it was relying on developer
+ tooling being present at runtime. Prefer a logger, or Spring Boot's
+ `org.springframework.boot.ansi.AnsiOutput` for coloured output. If the dependency is genuinely
+ required, declare the companion explicitly:
+
+ [source,groovy]
+ .build.gradle
+ ----
+ implementation "org.apache.grails.bootstrap:grails-bootstrap-cli"
+ ----
+
+ Test code that extended `GrailsConsolePrintStream` to capture output does not need it: that class
+ routes output through the CLI console, which a test almost never wants. Extend `java.io.PrintStream`
+ directly instead.
+
+ ==== 42. Plugin Authors: Separate Source Sets for the CLI Tier
+
+ This affects plugins that apply `org.apache.grails.gradle.grails-plugin-cli` and therefore publish a
+ companion `-cli` artifact.
+
+ Previously the `cli` source set's output and its dependencies were added to the plugin's `test`
+ classpath, so unit tests saw CLI classes and CLI-only libraries that an application never receives. A test
+ could pass against something that was not actually there in production.
+
+ The `cli` tier now has its own test source sets:
+
+ [cols="1,2"]
+ |===
+ |Source set |Purpose
+
+ |`src/test-cli`
+ |Tests for CLI classes. Runs as the `testCli` task, wired into `check`.
+
+ |`src/integration-test-cli`
+ |CLI tests that need a booted application - a command starts one the same way the shell does. Runs as the
+ `integrationTestCli` task.
+ |===
+
+ Both are created by `org.apache.grails.gradle.grails-plugin-cli`, so there is nothing to declare: create the
+ folder, add a spec, and the task picks it up.
+
+ `src/test` no longer sees the CLI tier at all. Move any existing spec that exercises a command or another
+ CLI class into `src/test-cli`, or into `src/integration-test-cli` if it boots an application.
+
+ Both CLI test source sets can read the module's `main` and `test` output, so shared fixtures stay where they
+ are. `src/integration-test-cli` additionally reuses `src/integration-test/resources` when that folder exists,
+ since both integration phases boot the same application and its configuration should not be duplicated.
+
+ The relationship between the source sets is deliberately one-way: CLI tests may use test fixtures, but
+ ordinary tests never see CLI classes, which is what keeps the `test` classpath a faithful stand-in for
+ production.
+
+ ==== 43. `gspCompile` Configuration Removed
+
+ The `org.apache.grails.gradle.grails-gsp` plugin no longer registers a `gspCompile` configuration.
+
+ It dated back to the original Ant-based GSP compiler, where it carried the classpath that compiler ran
+ against. Once GSP compilation moved to a forked compile task the configuration's only remaining content was
+ a hardcoded servlet API dependency, and that dependency has itself been removed — the servlet API already
+ reaches GSP compilation through the regular compile classpath, at the version the BOM manages.
+
+ GSPs continue to compile against the project's `compileClasspath`, its compiled classes, and — for a WAR
+ build — `providedCompile`. No application that leaves the configuration alone is affected.
+
+ A build that declares dependencies on `gspCompile` fails with `Could not find method gspCompile()`. Move
+ those declarations to `compileOnly`, which places them on the compile classpath that GSP compilation uses:
+
+ [source,groovy]
+ .build.gradle
+ ----
+ dependencies {
+ // Grails 7
+ // gspCompile 'com.example:some-library:1.0'
+
+ // Grails 8
+ compileOnly 'com.example:some-library:1.0'
+ }
+ ----
+
+ ==== 44. `grails.spring.bean.packages` Scanning Fixed Outside the Project Directory
+
+ The component scan driven by `grails.spring.bean.packages` resolved its search root from a probe of the
+ *working directory* — it looked for a `grails-app` directory or an `Application.groovy` beside it — and
+ returned nothing when neither was there. An application started from anywhere other than its project root
+ therefore registered none of the `@Component` classes in the configured packages, silently.
+
+ That covers most production shapes: a systemd unit with its own `WorkingDirectory`, a container with a
+ `WORKDIR`, an application server. `java -jar build/libs/app.jar` run from the project root was unaffected,
+ which is why the gap survived. The scan now uses Spring's own resource resolution, so the packages are
+ scanned wherever the process is started from.
+
+ [source, yaml]
+ .grails-app/conf/application.yml
+ ----
+ grails:
+ spring:
+ bean:
+ packages:
+ - com.example.components
+ ----
+
+ **Applications deployed this way will start getting beans they previously did not.** The scan registers
+ every `@Component`, `@Service`, `@Repository` and `@Controller` in the listed packages. Two things to check
+ before upgrading:
+
+ * A class in one of those packages that was never actually reaching the context — because it duplicates a
+ bean the application defines elsewhere, or because it was left behind — now registers. A duplicate under the
+ same bean name will fail startup rather than pass silently.
+ * Beans that were previously absent may now participate in autowiring by type, so an injection point that
+ resolved unambiguously before can become ambiguous.
+
+ Removing the packages from `grails.spring.bean.packages`, or the stray classes from those packages, restores
+ the previous set of beans.
++
++==== 45. GORM API Resolution Moves to a Registry
+
+GORM no longer allocates an API object for every (entity, connection) pair up front. Per-entity, per-qualifier
+state now lives in a registry (`org.grails.datastore.gorm.GormRegistry`), and APIs are built on first use by a
+pluggable factory. For applications this is invisible — `Book.list()`, dynamic finders, and
+`Book.withNewSession { }` behave as before. It does change some extension points that out-of-tree GORM
+implementations subclass.
+
+===== GormEnhancer
+
+`org.grails.datastore.gorm.GormEnhancer`'s public constructors, `enhance()`/`enhance(PersistentEntity)`,
+`dynamicEnhance`, and the `transactionManager` field are all unchanged in behaviour and signature (the
+`transactionManager` field is now `@Deprecated` and immutable after construction — read it, don't assign it).
+
+The following members were removed:
+
+[cols="1,2", options="header"]
+|===
+| Removed
+| Migration note
+
+| `finders` field / `getFinders()`
+| Use `createDynamicFinders(Datastore)`, or read the finders from the API object you are working with.
+
+| `removeConstraints()`
+| Moved to `GormRegistry.removeConstraints()`, called automatically from `GormRegistry.removeDatastore(Datastore)`
+as part of tearing a datastore down. There is nothing to call directly - it runs when the enhancer's `close()`
+removes the datastore from the registry, same as before.
+
+| `addStaticMethods(PersistentEntity, boolean)` / `addInstanceMethods(PersistentEntity, boolean)`
+| The `onlyExtendedMethods` parameter is gone; both methods now take only the entity. Installation mechanism
+also changed from per-method reflective registration to a single `methodMissing`/`propertyMissing` handler pair.
+
+| `findTenantId`, `apiQualifiers`, `findDatastoreByType`, `findSingleDatastore`,
+`findSingleTransactionManager`, `findTransactionManager(Class, String)`, `appliesToDatastore`,
+`getInstanceMethodApiProviders`, `registerStaticMethod`, `registerInstanceMethod`, `doesRealMethodExist`,
+`isRealMethod`
+| Internal helpers of the old per-method reflective registration mechanism, replaced wholesale by the registry
+and its `methodMissing`/`propertyMissing` handlers. If you overrode one of these to customise dispatch, override
+`registerApiFactories()` (below) or a `GormApiFactory` instead.
+|===
+
+A new `registerApiFactories()` hook is called once, before any entity is registered. Adapters that build
+specialised API objects should override it:
+
+[source,groovy]
+----
+class MyGormEnhancer extends GormEnhancer {
+
+ @Override
+ protected void registerApiFactories() {
+ GormRegistry.instance.registerApiFactory(MyDatastore, new MyGormApiFactory())
+ }
+}
+----
+
+WARNING: Earlier snapshots of this work registered API factories from `registerConstraints(Datastore)`.
+Move that code to `registerApiFactories()`; factory registration must not depend on the constraints lifecycle step.
+
+===== CurrentTenantHolder.get()
+
+`grails.gorm.multitenancy.CurrentTenantHolder.get()` — the no-argument form — now throws `TenantException` when
+different datastores hold different tenants on the calling thread, rather than returning an arbitrary one of
+them. Pass the datastore you are operating on:
+
+[source,groovy]
+----
+CurrentTenantHolder.get(datastore)
+----
+
+See <<multiTenancy,Multi-Tenancy>> for the full multi-tenancy API.