jamesfredley opened a new pull request, #15815:
URL: https://github.com/apache/grails-core/pull/15815
## Summary
Fixes the `Cannot invoke "String.split(String)" because "sources" is null`
NPE that crashes a classic servlet-container (Tomcat) WAR deployment of a
Grails 8 application using the Database Migration plugin.
## Root cause
Both Database Migration plugins - `grails-data-hibernate5-dbmigration` and
`grails-data-hibernate7-dbmigration` - depend on `grails-shell-cli` at
`implementation` scope. That places
`org.grails.cli.boot.SpringApplicationWebApplicationInitializer` on the
classpath of a normal application WAR.
That class is a `SpringBootServletInitializer` (a
`WebApplicationInitializer`) intended **only** for CLI-packaged WARs produced
by the shell `war` command (`WarCommand`), which records the application source
classes in the WAR manifest via the `Spring-Application-Source-Classes` entry.
When a standard `bootWar` is deployed to an external servlet container such
as Tomcat, Spring's `SpringServletContainerInitializer` discovers the stray
initializer and invokes `onStartup`. A normal WAR manifest has no
`Spring-Application-Source-Classes` entry, so `sources` was `null` and
`sources.split(",")` threw an NPE, crashing context startup. The application's
own `SpringBootServletInitializer` never got a chance to bootstrap.
## Fix
Make the initializer **inert** when the manifest source-classes entry is
absent: `onStartup` now returns before `super.onStartup(...)` instead of
throwing, so a standard WAR is unaffected and the application's own initializer
bootstraps it normally. The CLI-packaged WAR path is unchanged because that
manifest entry is always present there.
This single fix in the shared `grails-shell-cli` module resolves the issue
for **both** dbmigration plugins, and - importantly - requires **no changes in
consuming applications** (avoiding the `developmentOnly` / feature-variant /
separate-artifact options that would each require app-side build changes).
## Changes
- `SpringApplicationWebApplicationInitializer.java`: early-return when there
are no source classes; `getManifest` returning `null` and a blank/absent entry
now yield `null` (inert) instead of throwing.
- `SpringApplicationWebApplicationInitializerSpec.groovy` (new): regression
test covering a missing manifest, a manifest without the entry, and a manifest
with an unrelated entry - all must not throw.
- `grails-shell-cli/build.gradle`: `testImplementation` for `spring-boot` +
`spring-web` (needed to load the class under test; they are `compileOnly` in
the main source set).
## Verification
- `./gradlew :grails-shell-cli:test --tests
"org.grails.cli.boot.SpringApplicationWebApplicationInitializerSpec"` - BUILD
SUCCESSFUL, all cases pass.
- `./gradlew clean aggregateViolations` - Checkstyle, CodeNarc, PMD, and
SpotBugs all report no violations.
Fixes #15377
--
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]