jamesfredley opened a new pull request, #16041:
URL: https://github.com/apache/grails-core/pull/16041

   ## Summary
   
   Backport to `7.0.x` of #15815. Fixes the `Cannot invoke 
"String.split(String)" because "sources" is null` NPE that crashes a classic 
servlet-container (Tomcat) WAR deployment of a Grails 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.
   
   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]

Reply via email to