Document Grails 8 API compatibility breaks#15823
Conversation
Correct the enum marshaller migration note and add a Grails 8 extension API compatibility section for confirmed binary breaks. Assisted-by: Hephaestus:openai/gpt-5.5
There was a problem hiding this comment.
Pull request overview
Updates the Grails 8 upgrade guide to more accurately describe confirmed Grails 8 binary/API compatibility breaks and to correct guidance around enum marshalling changes.
Changes:
- Clarifies that the legacy enum marshaller classes were removed in Grails 8 and that there is no config switch to restore the verbose enum-object shape.
- Adds a new “Extension API Compatibility Notes” section summarizing confirmed binary breaks across multiple Grails modules and providing migration pointers.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
The suggestion to avoid wildcard imports is appropriate. You can update the migration note to reference the package explicitly or list the specific classes to improve clarity and follow best practices. Here is the updated text for that row in the table: | `grails-core`
| `grails.plugins.PluginFilter`, `IncludingPluginFilter`, `ExcludingPluginFilter`, `NoOpPluginFilter`, and related filter types
| Import the replacements from the `org.apache.grails.core.plugins.filters` package.grails-doc/src/en/guide/upgrading/upgrading80x.adoc |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## 8.0.x #15823 +/- ##
==================================================
- Coverage 49.5810% 49.5713% -0.0097%
+ Complexity 16695 16689 -6
==================================================
Files 1947 1947
Lines 92598 92598
Branches 16179 16179
==================================================
- Hits 45911 45902 -9
- Misses 39589 39596 +7
- Partials 7098 7100 +2 🚀 New features to boost your workflow:
|
Clarify plugin filter replacement imports and complete the japicmp checklist coverage for core constructor wiring and fields taglib helpers. Assisted-by: Hephaestus:openai/gpt-5.5
Assisted-by: Hephaestus:openai/gpt-5.5
Assisted-by: Hephaestus:openai/gpt-5.5
Assisted-by: Hephaestus:openai/gpt-5.5
Assisted-by: Hephaestus:openai/gpt-5.5
Assisted-by: Hephaestus:openai/gpt-5.5
🚨 TestLens detected 5 failed tests 🚨Here is what you can do:
Test SummaryCI - Groovy Joint Validation Build / build_grails > :grails-test-examples-gorm:integrationTest
CI / Build Grails-Core (windows-latest, 25) > :grails-shell-cli:test
CI / Functional Tests (Java 21, indy=false) > :grails-test-examples-gorm:integrationTest
CI / Functional Tests (Java 21, indy=true) > :grails-test-examples-gorm:integrationTest
CI / Functional Tests (Java 25, indy=false) > :grails-test-examples-gorm:integrationTest
🏷️ Commit: 2f58a24 Test FailuresRunningApplicationProcessSpec > stop terminates a running process and removes the PID file (:grails-shell-cli:test in CI / Build Grails-Core (windows-latest, 25))DirtyCheckBindingSpec > an explicit bindable:true id constraint declared on a @DirtyCheck base is inherited and binds over HTTP (:grails-test-examples-gorm:integrationTest in CI / Functional Tests (Java 21, indy=false))DirtyCheckBindingSpec > an explicit bindable:true id constraint declared on a @DirtyCheck base is inherited and binds over HTTP (:grails-test-examples-gorm:integrationTest in CI / Functional Tests (Java 21, indy=true))DirtyCheckBindingSpec > an explicit bindable:true id constraint declared on a @DirtyCheck base is inherited and binds over HTTP (:grails-test-examples-gorm:integrationTest in CI / Functional Tests (Java 25, indy=false))DirtyCheckBindingSpec > an explicit bindable:true id constraint declared on a @DirtyCheck base is inherited and binds over HTTP (:grails-test-examples-gorm:integrationTest in CI - Groovy Joint Validation Build / build_grails)Muted TestsSelect tests to mute in this pull request:
Reuse successful test results:
Click the checkbox to trigger a rerun:
Learn more about TestLens at testlens.app. |
Summary
This PR updates the Grails 8 upgrade guide to document the API and binary compatibility findings from the 8.0.x versus 7.1.2 japicmp follow-up review.
The japicmp pass compared 47 published Grails 7.1.2 module jars with locally built
8.0.0-SNAPSHOTjars. 33 modules had no binary-incompatible changes. The remaining findings were cross-checked against the existing Grails 8 upgrade guide so this PR could fill only the real documentation gaps and correct one inaccurate existing note.This PR does two things:
31. Extension API Compatibility Notes, for confirmed extension-level compatibility changes that were not already documented elsewhere in the guide.Why this is needed
The existing Grails 8 upgrade guide already covered many broad migration areas, including Spring Boot 4, Jackson 3, TagLib test cleanup, method-based TagLib handlers, JSON view converter migration, SiteMesh compatibility, GORM nullability defaults, MIME defaults, and Accept-header behavior.
The japicmp review found two remaining documentation problems:
Row-by-row japicmp coverage
grails-codecsCodecsGrailsPlugin.doWithSpring()removeddoWithSpring()implementation.grails-controllersControllersAutoConfiguration.dispatcherServletRegistration(...)return type changed because of the Spring Boot 4 package moveorg.springframework.boot.webmvc.autoconfigure.DispatcherServletRegistrationBean.grails-convertersgrails.web.JSONBuilderremovedgroovy.json.JsonBuilderorgroovy.json.StreamingJsonBuilder.grails-convertersorg.grails.web.converters.marshaller.json.EnumMarshallerandorg.grails.web.converters.marshaller.xml.EnumMarshallerremovedSimpleEnumMarshalleris the default, and that there is no Grails 8 configuration switch to restore the verbose enum-object shape.grails-coreGrailsApplicationPostProcessor(...),ProfilingGrailsApplicationPostProcessor(...), andDefaultGrailsPluginManager(...)constructor and plugin-discovery wiring changedGrailsApplicationPostProcessorandDefaultGrailsPluginManagerconstruction requires the plugin-discovery dependency, whileProfilingGrailsApplicationPostProcessorkeeps its existing constructor shape but requires agrailsPluginDiscoverybean in the application context.grails-coregrails.plugins.PluginFilterfamily removed or movedorg.apache.grails.core.plugins.filterspackage and names explicit replacement types without recommending wildcard imports.grails-coregrails.util.Mixin,MixinTargetAware, andMixinTransformationremovedgrails-coregrails.validation.ConstraintsEvaluatorremovedorg.grails.datastore.gorm.validation.constraints.eval.ConstraintsEvaluator.grails-coreBinaryGrailsPluginDescriptor,CorePluginFinder, andBinaryGrailsPlugin.getBinaryDescriptor()removedBinaryGrailsPlugin.getPluginDescriptor().grails-domain-classConstraintEvaluatorAdapterandGrailsDomainClassAutoConfiguration.constraintsEvaluator(...)removedvalidateableConstraintsEvaluator(...)bean path and datastore constraint evaluator APIs.grails-fieldsBeanPropertyAccessor.getBeanClass()and setter,PropertyPathAccessor.getBeanClass(),FormFieldsTagLib.input(...), and directrender*helpers changed or removedbeanTypeand to the documentedf:field,f:widget, andf:displayWidgettags/templates instead of direct helper calls.grails-gradle-pluginsApplicationContextCommandTask,ApplicationContextScriptTask,ProfileCompilerTask, andGrailsRunTaskare abstract;GrailsGradlePlugin.createBuildPropertiesTask(...)return type changed;IntegrationTestGradlePlugin.get*constants removedgrails-gspApplicationTagLib,CountryTagLib,FormatTagLib, andFormTagLib; helper methods made privateMethod-based TagLib Handlers. This PR does not duplicate that section.grails-shell-cliAetherGrapeEngineandAetherGrapeEngineFactoryremovedMavenResolverGrapeEngineandMavenResolverGrapeEngineFactory.grails-shell-clicomplete(...)signatures moved to JLine 3org.jline.reader.Completercontract.grails-sitemesh3GrailsLayoutHandlerMapping,RenderSitemeshTagLibmembers, andSitemesh3GrailsPluginlifecycle changesKnown Plugin Incompatibilities, which tells applications usinggrails-sitemesh3to stay on thegrails-layoutplugin until compatibility is available. This PR does not duplicate that warning.grails-springGrailsApplicationContext.getTheme(String)andonRefresh()removedonRefresh()to the new section and directs custom context subclasses to supported Spring lifecycle extension points.grails-testing-support-webGrailsWebUnitTest.getPurgeTagLibMetaClass()andTagLibUnitTest.getPurgeTagLibMetaClass()removedTag Library Test Cleanup Changes. This PR does not duplicate that section.grails-views-gsongrails.plugin.json.builder.*removed and helper APIs moved togroovy.json.*Custom JSON View Converters. This PR does not duplicate that section.What changed in the guide
Section 8: enum serialization
The guide previously said:
That was incorrect for Grails 8. The guide now says the legacy JSON/XML
EnumMarshallerclasses were removed in Grails 8, and that projects needing the old verbose enum-object contract must register a custom object marshaller explicitly.Section 31: extension API compatibility notes
The new section is scoped to applications, plugins, or build logic that directly import public Grails extension classes or override public extension points. It explicitly says unsupported internal implementation details are not covered.
The section is intentionally compact so the upgrade guide remains usable as a migration checklist rather than a full japicmp report.
Review feedback addressed
Copilot noted that the first version of the plugin-filter migration note used
org.apache.grails.core.plugins.filters.*, which could be read as a wildcard-import recommendation. That feedback was valid.The note now points to the
org.apache.grails.core.plugins.filterspackage and lists explicit replacement types instead of using.*.Verification
Completed:
npx --yes asciidoctor -o C:\Users\james\AppData\Local\Temp\opencode\upgrading80x.html grails-doc\src\en\guide\upgrading\upgrading80x.adoc.*reference.git diff --checksuccessfully.a419ca79bbb6441febaabaf2d1b2457ed2831e2f.a2cf68206237041a8f04553ddfd571b49475903f.Attempted but blocked by an unrelated current-tree issue:
./gradlew.bat :grails-doc:publishGuide -x aggregateGroovydoc:grails-validation:compileGroovyfails in the current tree withunable to resolve class groovy.transform.Virtualingrails-validation/src/main/groovy/grails/validation/Validateable.groovy.No further Gradle commands were run after being asked to run Gradle tasks one at a time, with a max of two tasks per invocation.