Skip to content

Support provided-scope libraries when extracting an executable war - #51372

Open
skdas20 wants to merge 1 commit into
spring-projects:mainfrom
skdas20:fix-51367-war-provided-libs
Open

Support provided-scope libraries when extracting an executable war#51372
skdas20 wants to merge 1 commit into
spring-projects:mainfrom
skdas20:fix-51367-war-provided-libs

Conversation

@skdas20

@skdas20 skdas20 commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

See gh-51367.

Problem

IndexedJarStructure.toStructureDependency flattens every classpath index entry relative to the single Spring-Boot-Lib location:

Assert.state(libEntryName.startsWith(this.libLocation), () -> "Invalid library location " + libEntryName);
return libEntryName.substring(this.libLocation.length());

For an executable war Spring-Boot-Lib is WEB-INF/lib/, but provided-scope dependencies (the embedded container among them) are packaged under WEB-INF/lib-provided/ by Layouts.War and are listed in WEB-INF/classpath.idx alongside the rest. The first such entry trips the assertion, so -Djarmode=tools extract fails with Invalid library location WEB-INF/lib-provided/... on any war built from a web starter.

Only Spring-Boot-Lib is recorded in the manifest, so the second location can't be read from there. WarLauncher has the same need and hardcodes both:

return name.startsWith("WEB-INF/lib/") || name.startsWith("WEB-INF/lib-provided/");

Change

Accept entries from either location when flattening, mirroring WarLauncher, and keep the failure for anything genuinely outside a library root (now an explicit IllegalStateException, since the two-location check no longer fits Assert.state).

Tests

Added to IndexedJarStructureTests, using a war-shaped manifest and an index containing both a WEB-INF/lib/ and a WEB-INF/lib-provided/ entry:

  • shouldResolveLibraryEntryFromWarProvidedLocation — the provided entry resolves as a LIBRARY flattened to its bare jar name
  • shouldCreateLauncherManifestForWarWithProvidedLibraries — both jars appear in the generated Class-Path

Both fail on main:

IndexedJarStructureTests > shouldCreateLauncherManifestForWarWithProvidedLibraries() FAILED
IndexedJarStructureTests > shouldResolveLibraryEntryFromWarProvidedLocation() FAILED

With the change the module's tests and checkFormatMain/checkFormatTest all pass.

One thing worth your call: I hardcoded the location as a constant to match WarLauncher. If you'd rather it be derived (or carried in the manifest as a new attribute so the tools jarmode doesn't need to know war layout at all), happy to redo it that way.

IndexedJarStructure flattened every classpath index entry relative to the
single Spring-Boot-Lib location. An executable war also places its
provided-scope dependencies under WEB-INF/lib-provided/ and lists them in
the index, so the first such entry failed the assertion and aborted the
tools jarmode extract command.

Accept entries from that location too, mirroring WarLauncher, which
already treats WEB-INF/lib/ and WEB-INF/lib-provided/ as library roots.

See spring-projectsgh-51367

Signed-off-by: skdas20 <skdas5405@gmail.com>
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 12, 2026
@skdas20

skdas20 commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Note on the red build: the failure is :platform:spring-boot-dependencies:bomrCheck, not this change.

> Task :platform:spring-boot-dependencies:bomrCheck FAILED

MongoDB
    - Version 5.9.1 is misaligned. It should be 5.9.2.

MongoDB 5.9.2 has been published since #51339 bumped the BOM to 5.9.1, so the check flags the drift on any build until that's bumped again. This PR only touches IndexedJarStructure and its test in spring-boot-jarmode-tools, nothing under platform/ — I've left the BOM alone since dependency upgrades look like they're handled through your own tracked issues.

Happy to rebase once that lands if you'd like a green run before reviewing.

@mhalbritter

Copy link
Copy Markdown
Contributor

@philwebb What do you think about adding a new manifest attribite for the lib-provided dependencies, which the jartools can then read? Instead of hardcoding WEB-INF/lib-provided?

@skdas20

skdas20 commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

@mhalbritter that reads better to me than the constant, and I'm happy to redo it that way — it would let the jarmode stop knowing war layout at all, which is really the underlying smell here.

One fact that may make the decision easier: the tools jarmode is packaged into the archive it operates on — JarModeLibrary.TOOLS writes it to META-INF/jarmode/spring-boot-jarmode-tools.jar, so the reader and the manifest are always produced by the same Boot version. That means a new attribute wouldn't need a fallback for archives built by older versions the way a normally-consumed API would; there's no mixed-version case to support.

Shape I'd propose unless you'd rather something else:

  • Packager writes the location when the layout declares one — the war layout already knows it from Layouts.War.SCOPE_LOCATION for PROVIDED, so it isn't a new piece of knowledge, just newly recorded.
  • IndexedJarStructure reads it as optional and adds it to the set of library roots it will flatten against; jars simply won't have it.
  • Naming: Spring-Boot-Lib-Provided alongside the existing Spring-Boot-Lib, and added to MANIFEST_DENY_LIST so it's stripped from the generated launcher manifest like its siblings.

That's a wider change than this PR, touching loader-tools and both build plugins' expected-manifest tests. Say the word and I'll push it here, or if you'd rather keep this one as the narrow fix and track the attribute separately, that works too — I don't mind which, and I'd rather not guess and hand you the wrong scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: waiting-for-triage An issue we've not yet triaged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants