jamesfredley opened a new pull request, #15411:
URL: https://github.com/apache/grails-core/pull/15411
## Summary
Fixes two Micronaut integration bugs by automating configuration that
previously required manual `build.gradle` setup:
- **#15207** - `java -jar` broken for grails-micronaut apps due to Spring
Boot 3.2+ default loader incompatibility
- **#15211** - Java `@Singleton` beans not registered when using Groovy
incremental compilation (missing annotation processor)
## Problem
### Issue #15207 - `java -jar` fails with `NoClassDefFoundError`
Spring Boot 3.2+ changed the default `LoaderImplementation` from `CLASSIC`
to a new implementation. The new loader is incompatible with Micronaut-Spring's
classpath scanning mechanism (`MicronautImportRegistrar`), causing
`NoClassDefFoundError` at runtime when running a packaged JAR/WAR via `java
-jar`.
### Issue #15211 - Java `@Singleton` beans silently ignored
Groovy sources use `micronaut-inject-groovy` AST transforms to generate
`BeanDefinitionReference` classes. However, Java sources in a Grails project
require the `micronaut-inject-java` annotation processor on the
`annotationProcessor` configuration. Without it, Java beans annotated with
`@Singleton`, `@Factory`, etc. are silently ignored - no compile error, just
missing beans at runtime.
## Solution
### GrailsGradlePlugin (`configureMicronaut()`)
1. **Annotation processor** - Automatically adds `micronaut-inject-java` +
`jakarta.annotation-api` to the `annotationProcessor` configuration, scoped to
the Micronaut platform BOM. This only affects `compileJava` tasks (Groovy
sources continue using AST transforms via `compileOnlyApi`).
2. **CLASSIC loader** - Configures `bootJar` and `bootWar` tasks with
`LoaderImplementation.CLASSIC` as a convention default (overridable by users).
This ensures `java -jar` works correctly with Micronaut-Spring's classpath
scanning.
### Forge Template
Adds the missing `bootWar` CLASSIC loader configuration to match the
existing `bootJar` configuration in Forge-generated `build.gradle` files.
### Housekeeping
- Adds Apache license header to `GrailsMicronautValidator.java`
- Replaces `// TODO:` with `// See:` to satisfy Forge checkstyle
`TodoComment` rule
## Commits
| Commit | Description |
|--------|-------------|
| `fix: configure Micronaut annotation processor and CLASSIC loader in
GrailsGradlePlugin` | Core fix - adds annotation processor for Java sources +
CLASSIC loader convention for bootJar/bootWar |
| `fix: add bootWar CLASSIC loader to Forge-generated build.gradle` | Forge
template parity - bootWar was missing CLASSIC loader config |
| `chore: add Apache license header to GrailsMicronautValidator` | License
header + checkstyle compliance |
| `test: add integration tests for Micronaut bean type registration` | New
`MicronautBeanTypesSpec` covering Java @Singleton, Groovy @Factory/@Bean, and
@ConfigurationProperties bean registration |
| `docs: document Micronaut annotation processor and CLASSIC loader in
upgrade guide` | Upgrade guide notes warning against manual annotation
processor setup |
## Test Coverage
**21 integration tests passing** in `grails-test-examples-micronaut`:
- `BeanInjectionServiceSpec` (3 tests) - existing Micronaut bean injection
tests
- `MicronautBeanTypesSpec` (5 tests) - **NEW** - Java @Singleton,
@Factory/@Bean, @ConfigurationProperties, singleton identity checks
- `MicronautContextSpec` (6 tests) - existing context bridge tests
- `MicronautQualifierSpec` (7 tests) - existing qualifier/named bean tests
### New test bean types added:
| Bean | Type | Registration Path |
|------|------|-------------------|
| `JavaSingletonService` | Java class | `@Singleton` via annotation
processor |
| `FactoryCreatedService` | Groovy POJO | `@Factory`/`@Bean` via AST
transform |
| `ServiceFactory` | Groovy factory | `@Factory` with `@Singleton` method |
| `AppConfig` | Groovy config | `@ConfigurationProperties('app')` bound from
`application.yml` |
## Build Verification
| Project | Status |
|---------|--------|
| `grails-gradle` (plugins) | :white_check_mark: BUILD SUCCESSFUL |
| `grails-forge` (checkstyle) | :white_check_mark: BUILD SUCCESSFUL |
| `grails-doc` (guide) | :white_check_mark: BUILD SUCCESSFUL |
| `codeStyle` (main project) | :white_check_mark: BUILD SUCCESSFUL |
| `grails-test-examples-micronaut:integrationTest` | :white_check_mark:
21/21 PASSED |
## Remaining Gaps (Out of Scope)
These are known limitations of the current Micronaut integration, not
addressed by this PR:
- `spring-boot-devtools` incompatibility
([micronaut-spring#769](https://github.com/micronaut-projects/micronaut-spring/issues/769))
- Groovy incremental compilation may re-trigger AST transforms on unchanged
files (Groovy compiler limitation)
- No `bootRun` CLASSIC loader needed (only affects packaged archives)
Fixes #15207
Fixes #15211
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]