Merged
Conversation
…ration Plugin is present
…railsGradlePlugin Add Java annotation processor (micronaut-inject-java) for projects using grails-micronaut so that Java @singleton beans generate proper BeanDefinitionReference classes at compile time. Groovy sources continue to use the existing micronaut-inject-groovy AST transforms. Configure bootJar and bootWar tasks to use LoaderImplementation.CLASSIC as a convention default when Micronaut support is detected. The new Spring Boot 3.2+ default loader is incompatible with Micronaut-Spring's classpath scanning, causing NoClassDefFoundError at runtime when running via java -jar. Fixes #15207 Fixes #15211 Assisted-by: Claude Code <Claude@Claude.ai>
The Forge template already configured bootJar with CLASSIC loader but was missing the equivalent bootWar configuration. WAR-packaged apps deployed via java -jar would fail with the same Micronaut-Spring classpath scanning issue as JAR-packaged apps. Related to #15207 Assisted-by: Claude Code <Claude@Claude.ai>
Add the required ASF license header and replace TODO comment with a See reference to satisfy the Forge project checkstyle TodoComment rule. Assisted-by: Claude Code <Claude@Claude.ai>
Add MicronautBeanTypesSpec verifying that Java @singleton beans (via annotation processor), Groovy @Factory/@bean beans (via AST transform), and @ConfigurationProperties beans are all correctly bridged into the Spring application context. New test bean types: - JavaSingletonService: Java class with @singleton (annotation processor path) - FactoryCreatedService + ServiceFactory: Groovy @Factory/@bean pattern - AppConfig: @ConfigurationProperties bound from application.yml Also adds MicronautTestController and URL mapping for manual smoke testing of bean injection across all registration mechanisms. Assisted-by: Claude Code <Claude@Claude.ai>
…pgrade guide Add notes to the 6.0.x upgrade guide warning users not to manually add Micronaut annotation processors (now handled automatically by the Grails Gradle Plugin) and explaining the automatic CLASSIC loader configuration for bootJar/bootWar tasks. References #15207, #15211 Assisted-by: Claude Code <Claude@Claude.ai>
SpringBootDevTools.shouldApply() now returns false when GrailsMicronaut is selected, preventing the DefaultFeature from being auto-applied and triggering GrailsMicronautValidator's incompatibility check. Fixes Build Grails Forge CI failures on CreateAppSpec. Assisted-by: Claude Code <Claude@Claude.ai>
…naut Verifies no bean duplication occurs when micronaut-spring bridges Micronaut beans into Spring context. Confirms bridged beans share the same singleton instance across both contexts. Assisted-by: Claude Code <Claude@Claude.ai>
- Use render([...] as JSON) instead of render(text: Map) for valid JSON output - Fix singleton tests to use applicationContext.getBean() for proper scope verification - Make JavaMessageProvider public and add interface-type injection test - Correct capitalization of Spring Boot DevTools and Micronaut integration in docs Assisted-by: Claude Code <Claude@Claude.ai>
Java requires public interfaces to be declared in a file matching the interface name. Moves JavaMessageProvider out of JavaSingletonService.java into its own JavaMessageProvider.java file. Assisted-by: Claude Code <Claude@Claude.ai>
Replace the runtime AutoConfigurationImportFilter approach with a compile-time AST transformation in ApplicationClassInjector. When DatabaseMigrationGrailsPlugin is on the classpath, the exclusion is added to @EnableAutoConfiguration(excludeName=...) during compilation - the same mechanism already used for DataSourceAutoConfiguration, ReactorAutoConfiguration, and HibernateJpaAutoConfiguration. Opt-out via system property in gradle.properties: systemProp.grails.dbmigration.excludeLiquibaseAutoConfiguration=false Assisted-by: Claude Code <Claude@Claude.ai>
test Remove auto-configured Micronaut annotation processors from GrailsGradlePlugin per review feedback - they are incompatible with Groovy incremental compilation and were never previously configured. Projects with Java sources using Micronaut annotations must add the annotationProcessor dependencies manually. Add declarative @client interface and integration test to verify Micronaut HTTP client beans are properly registered in the Grails context. Add micronaut-http-client and micronaut-serde-jackson dependencies to the micronaut test example, along with the required annotationProcessor configuration for its Java sources. All 33 micronaut integration tests pass. Assisted-by: Claude Code <Claude@Claude.ai>
…atz mock Add integration test that exercises the Micronaut @client(id='grails-self') through the full service discovery and load balancing path using an ersatz mock HTTP server as the backend endpoint. Assisted-by: Claude Code <Claude@Claude.ai>
…lePlugin The annotation processor (micronaut-inject-java) is required for Java sources that use Micronaut annotations like @ConfigurationProperties and @singleton. Removing it broke the issue-11767 plugin's PluginJavaMicronautBean, which depends on compile-time code generation. Assisted-by: Claude Code <Claude@Claude.ai>
…a sources Micronaut annotation processors are incompatible with Groovy incremental compilation, so they should not be auto-configured in GrailsGradlePlugin. Instead, add them manually only to test apps that have Java sources using Micronaut annotations (issue-11767 plugin has PluginJavaMicronautBean.java, micronaut test app already had them configured). Assisted-by: Claude Code <Claude@Claude.ai>
…3 to 3.20.0 Add version-conditional JVM arguments in GrailsGradlePlugin to suppress warnings on modern JDKs: - --sun-misc-unsafe-memory-access=allow for Java 23+ (JEP 471/498, #15343) - --enable-native-access=ALL-UNNAMED for Java 24+ (JEP 472, #15216) Override commons-lang3 from 3.17.0 (Spring Boot managed) to 3.20.0 in the Grails BOM to fix LANG-1786 timezone warnings and CVE-2025-48924. Includes Gradle TestKit functional tests verifying the args are applied correctly based on toolchain version. Assisted-by: Claude Code <Claude@Claude.ai>
Tests were hardcoding expected values for JDK 17 but CI also runs on Java 25 where both compat flags are correctly applied. Compute expected values dynamically from CURRENT_JDK. Assisted-by: Claude Code <Claude@Claude.ai>
…connection) Data Service methods using @where annotations or DetachedCriteria-based queries (count, list, findBy*) were ignoring the class-level @transactional(connection) annotation, causing queries to execute against the default datasource instead of the specified connection. Root cause: Both AbstractWhereImplementer and AbstractDetachedCriteriaServiceImplementor called findConnectionId(newMethodNode) instead of findConnectionId(abstractMethodNode). The newMethodNode belongs to the generated $ServiceImplementation class which lacks the @transactional annotation, while abstractMethodNode belongs to the original interface/abstract class where the annotation is declared. Additionally, in AbstractWhereImplementer the build() call was placed after withConnection(), but DetachedCriteria.clone() (called internally by build) does not copy the connectionName field, causing the connection setting to be lost. Fixed by reordering build() before withConnection(). Fixes #15416 Assisted-by: Claude Code <Claude@Claude.ai>
AbstractHibernateGormStaticApi.exists() called criteriaQuery.from() twice, creating a second query root that produced a cartesian product. The generated SQL selected count(alias0) from Table alias1, Table alias0 where alias1.id=?, scanning the entire table for every matching row instead of a simple count. Reuse the existing queryRoot variable for the count select expression. Fixes #14334 Assisted-by: Claude Code <Claude@Claude.ai>
Co-authored-by: Mattias Reichel <matrei@apache.org>
Co-authored-by: Mattias Reichel <matrei@apache.org>
Fix exists() cross-join caused by duplicate CriteriaQuery root
Add unit and functional tests verifying that @Query-annotated Data Service methods (find-one, find-all, update) correctly route to non-default datasources when @transactional(connection) is specified. Tests cover both abstract class and interface service patterns using FindOneStringQueryImplementer, FindAllStringQueryImplementer, and UpdateStringQueryImplementer - previously untested code paths. Assisted-by: Claude Code <Claude@Claude.ai>
Add TCK test (WhereQueryConnectionRoutingSpec) that validates @where queries, count, list, and findBy operations route to the correct datasource when using @transactional(connection). This ensures the AbstractWhereImplementer fix is verified across all datastore implementations, not just Hibernate. - Add WhereRoutingItem domain and WhereRoutingItemService to TCK - Extend GrailsDataTckManager with optional multi-datasource support - Implement multi-datasource in Hibernate and MongoDB TCK managers - Fix WhereQueryMultiDataSourceSpec cleanup (setup -> cleanup method) - TCK test passes on Hibernate5, MongoDB, skipped on SimpleMap Assisted-by: Claude Code <Claude@Claude.ai>
…ility When Undertow is selected as the servlet container, undertow-core transitively pulls in jboss-threads 3.7.0 which calls the terminally deprecated sun.misc.Unsafe::objectFieldOffset in its static initializer, producing a warning on Java 25. Pin jboss-threads to 3.9.2 as a runtimeOnly dependency to resolve this. Assisted-by: Claude Code <Claude@Claude.ai>
…r review
Address review feedback from jdaugherty:
- Replace afterEvaluate anti-pattern with project.plugins.withId('java')
- Move version resolution into configureEach callbacks so toolchain
config is read lazily after build script evaluation
- Add project.logger.info for each JVM compatibility flag added
Assisted-by: Claude Code <Claude@Claude.ai>
…eton beans, and docs updates - Add comprehensive ersatz-based integration tests for Micronaut declarative HTTP client covering GET, POST, PUT, DELETE, path variables, 404/500 error handling, and Accept headers - Add full roundtrip integration tests (HTTP -> Grails controller -> service -> @client -> ersatz) for all CRUD operations, error propagation, sequential calls, custom headers, and large responses - Add micronaut-singleton plugin with Java @singleton bean to verify plugin-contributed Micronaut beans are properly bridged into the Spring application context - Add ExternalApiController and ExternalApiService demonstrating Grails service layer consuming external APIs via Micronaut declarative HTTP client - Remove CLASSIC loader from Forge buildGradle template (no longer needed with plugin handling it) - Update upgrading60x.adoc to clarify Micronaut plugin only adds Groovy support, annotation processors needed separately for Java, recommend split projects 63 integration tests pass (27 ersatz-based, 5 plugin bean, 31 existing) Assisted-by: Claude Code <Claude@Claude.ai>
Add comprehensive ersatz-mocked integration tests covering every way a Micronaut declarative HTTP client can be integrated into a Grails app: - All HTTP methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, ANY - Parameter binding: @QueryValue, @PathVariable, @Header, @CookieValue, @Body - Return types: String, HttpResponse, CompletableFuture<T>, void - Client config: @client(id), @client(id, path) for base path/API versioning - Class-level @Header for automatic header injection on all methods - @ClientFilter with @RequestFilter for auto-injecting auth tokens - @retryable with ersatz sequential responses (503, 503, 200) - Content types: JSON, plain text, XML - Error handling: 401, 403, 404, 429, 500, 502, 503 - Ersatz features: delayed responses, sequential responses, listeners, call count verification, query/header/cookie matching, response cookies - Full roundtrip tests: HTTP client -> Grails controller -> service -> Micronaut declarative client -> ersatz mock server New files: - MicronautAdvancedClient, MicronautHeaderClient (Phase 2) - MicronautReactiveClient, MicronautPathClient, MicronautFilteredClient - MicronautRetryableClient.java (Java for proper AOP annotation processing) - AuthTokenClientFilter.java (@ClientFilter with @RequestFilter) - MicronautErsatzAdvancedSpec (27 tests), MicronautErsatzPatternSpec (16 tests) Total: 105 integration tests across 10 specs, all passing. Assisted-by: Claude Code <Claude@Claude.ai>
Standardize the opt-out property name under the grails.autoconfigure.exclude namespace per review feedback from @matrei, replacing the previous grails.dbmigration.excludeLiquibaseAutoConfiguration name. Assisted-by: Claude Code <Claude@Claude.ai>
fix: copy missing fields in AbstractDetachedCriteria.clone()
fix: add jboss-threads 3.9.2 to Undertow feature for Java 25 compatibility
…ainForForkTasks
Use plugins.withId('java') with configureEach instead of
afterEvaluate, matching the pattern used by
configureJavaCompatibilityArgs. The configureEach closure defers
execution until task realization (after evaluation), so the
toolchain check works without afterEvaluate.
Assisted-by: Claude Code <Claude@Claude.ai>
Replace internal GormEnhancer.findStaticApi/findInstanceApi calls with the public domain class API (Item.secondary.withNewTransaction, item.secondary.save) matching existing test conventions in MultipleDataSourcesWithEventsSpec. Assisted-by: Claude Code <Claude@Claude.ai>
Upgrade to Spring Boot 3.5.11
Restore Javadoc comments on ProductService, ProductDataService, and DataServiceMultiDataSourceSpec that were inadvertently removed. Assisted-by: Claude Code <Claude@Claude.ai>
Assisted-by: Claude Code <Claude@Claude.ai>
Add micronaut-groovy-only test example that validates grails-micronaut works without explicit annotationProcessor dependencies or Java source files. The Grails Gradle plugin auto-applies the required annotation processors when grails-micronaut is on the classpath. Includes bean injection, context coexistence, and qualifier tests ported from the existing micronaut module with NamedService converted from Java interface to Groovy interface. Assisted-by: Claude Code <Claude@Claude.ai>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR merges changes from the 7.0.x maintenance branch into 7.1.x. The changes include:
Changes:
- New Micronaut integration test examples with Ersatz mock server testing
- Java 23+ and 24+ compatibility JVM arguments for Test and JavaExec tasks
- Grails Micronaut plugin improvements (annotation processor handling, Spring Boot DevTools incompatibility)
- GORM multi-datasource connection routing fixes for
@Wherequeries and@Querymethods - Hibernate exists() cross-join fix (issue #14334)
- Automatic LiquibaseAutoConfiguration exclusion when database-migration plugin is present
- Dependency updates (Spring Boot 3.5.10 → 3.5.11, grails-spring-security 7.0.1 → 7.0.2)
Reviewed changes
Copilot reviewed 97 out of 101 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| settings.gradle | Adds two new test example projects: micronaut-groovy-only and plugins/micronaut-singleton |
| grails-test-examples/micronaut/* | Comprehensive Micronaut integration tests with Ersatz mock server, declarative clients, bean injection |
| grails-test-examples/micronaut-groovy-only/* | Pure Groovy Micronaut beans test (validates AST transform without Java annotation processor) |
| grails-test-examples/plugins/micronaut-singleton/* | Plugin providing @Singleton bean to verify cross-context bridge |
| grails-gradle/.../GrailsGradlePlugin.groovy | Java 23/24 compatibility JVM args, toolchain handling, CLASSIC boot loader for Micronaut |
| grails-forge/.../SpringBootDevTools.java | Excludes spring-boot-devtools when grails-micronaut is selected |
| grails-forge/.../SpringBootUndertowFeature.java | Adds jboss-threads dependency for Java 25 compatibility |
| grails-forge/.../GrailsMicronautValidator.java | Validates incompatibility between grails-micronaut and spring-boot-devtools |
| grails-micronaut/.../GrailsMicronautGrailsPlugin.groovy | Code formatting improvements, removes micronaut-inject-java compileOnlyApi |
| grails-datamapping-core/.../AbstractWhereImplementer.groovy | Fixes connection routing by calling withConnection before build |
| grails-datamapping-core/.../AbstractDetachedCriteria.groovy | Clone preserves connectionName, lazyQuery, associationCriteriaMap |
| grails-data-hibernate5/.../AbstractHibernateGormStaticApi.groovy | Fixes exists() cross-join by using queryRoot instead of creating new from() |
| grails-core/.../ApplicationClassInjector.groovy | Automatic conditional exclusion of LiquibaseAutoConfiguration |
| grails-doc/.../upgrading60x.adoc | Documents Micronaut integration, annotation processor requirements, DevTools incompatibility |
| grails-doc/.../automaticDatabaseMigration.adoc | Documents automatic LiquibaseAutoConfiguration exclusion |
| dependencies.gradle | Spring Boot 3.5.10 → 3.5.11, adds commons-lang3 |
| gradle.properties | Adds ersatzVersion=4.0.1, updates grailsSpringSecurityVersion to 7.0.2-SNAPSHOT |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.