Skip to content

Fix Spring MVC RequestPath lookup across Tomcat classloaders - #20914

Open
trask wants to merge 2 commits into
mainfrom
trask-spring-war-compatibility
Open

trask wants to merge 2 commits into
mainfrom
trask-spring-war-compatibility

Conversation

@trask

@trask trask commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Fix Spring MVC agent initialization when different Spring versions are loaded by a WAR and Tomcat's common classloader.

Fixes #13249.

Resolve ServletRequestPathUtils.parseAndCache from its declaring class instead of independently resolving its RequestPath return type. This avoids creating a conflicting loader constraint that can prevent a later application's ContextLoaderListener from initializing otelAutoDispatcherFilter.

Replace the standalone investigation with a native Tomcat smoke regression and no-agent control. The regression deploys a Spring 5.2 WAR before a second WAR using common-loader Spring 5.3, then requires both HTTP endpoints and the agent's server spans to work. It exercises the repository-built agent, including the current indy implementation.

The WAR fixture is built and deployed automatically by the regression test. Run both agent and no-agent cases on Windows with Java 25 and Docker's Linux containers:

$env:USE_LINUX_CONTAINERS = "1"
.\gradlew.bat :smoke-tests:test -PtestJavaVersion=11 --tests "*TomcatSpringWar*SmokeTest"

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Pull request dashboard status

Waiting on reviewers · refreshed 2026-10-23 23:11 UTC

Review the latest changes.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The changes are confined to the standalone reproducer, with no unresolved review findings or production instrumentation changes.

No open issues 🎉

What changed in this PR

Adds an isolated Docker-based Spring MVC WAR reproducer for the RequestPath loader-constraint failure during agent bean initialization. It compares released agents and deployment layouts without changing production instrumentation.

Changes:

  • Adds a Java 8 WAR application and pinned Docker environment with configurable Spring dependency placement.
  • Adds a Python runner that captures diagnostics, classifies failures, and compares agent and no-agent controls.
  • Documents reproduction steps, recorded results, and investigation limitations.
File Description
examples/​spring-war-compatibility/​test_run.py Tests failure classification and Docker launcher behavior.
examples/​spring-war-compatibility/​src/​main/​webapp/​WEB-INF/​web.xml Registers listeners and the MVC servlet.
examples/​spring-war-compatibility/​src/​main/​webapp/​WEB-INF/​servlet.xml Defines the empty servlet application context.
examples/​spring-war-compatibility/​src/​main/​webapp/​WEB-INF/​root.xml Configures MVC and the probe controller.
examples/​spring-war-compatibility/​src/​main/​webapp/​WEB-INF/​path-patterns.xml Enables path-pattern matching for the second WAR.
examples/​spring-war-compatibility/​src/​main/​java/​io/​opentelemetry/​examples/​springwar/​ProbeController.java Exposes health and class-origin diagnostics.
examples/​spring-war-compatibility/​src/​main/​java/​io/​opentelemetry/​examples/​springwar/​LoaderListener.java Logs runtime and classloader identities.
examples/​spring-war-compatibility/​run.py Runs comparisons and saves classified evidence.
examples/​spring-war-compatibility/​RESULTS.md Records observations, controls, and limitations.
examples/​spring-war-compatibility/​README.md Explains setup, deployment, and classification.
examples/​spring-war-compatibility/​pom.xml Defines the standalone Java 8 WAR build.
examples/​spring-war-compatibility/​Dockerfile Builds dependency layouts and packages released agents.
examples/​spring-war-compatibility/​.gitignore Excludes generated results and build artifacts.
examples/​spring-war-compatibility/​.dockerignore Limits Docker build inputs.

Review effort: Balanced

Comment thread examples/spring-war-compatibility/Dockerfile Outdated
Co-authored-by: trask <218610+trask@users.noreply.github.com>
@trask
trask requested a balanced review from Copilot October 23, 2026 22:33
@trask trask changed the title Add Docker reproducer for Spring WAR RequestPath loader constraints Fix Spring MVC RequestPath lookup across Tomcat classloaders Oct 23, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The class-loader-sensitive production change warrants maintainer review before approval.

1 open issue

Review effort: Balanced

Comment thread settings.gradle.kts
include(":smoke-tests:images:servlet")
include(":smoke-tests:images:servlet:servlet-3.0")
include(":smoke-tests:images:servlet:servlet-5.0")
include(":smoke-tests:images:servlet:spring-war")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@laurit I could go either way on keeping the test 🤷‍♂️

@trask
trask marked this pull request as ready for review October 23, 2026 22:51
@trask
trask requested a review from a team as a code owner October 23, 2026 22:51

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

URLClassLoader previously initiated loading for a different type with name "org/springframework/http/server/RequestPath"

3 participants