jetty / jetty.project

Eclipse Jetty® - Web Container & Clients - supports HTTP/2, HTTP/1.1, HTTP/1.0, websocket, servlets, and more
https://eclipse.dev/jetty
Other
3.82k stars 1.91k forks source link

Duplicate Resource / web-fragment registration #11789

Open jackeri opened 3 months ago

jackeri commented 3 months ago

Jetty version(s) 12.0.9

Jetty Environment ee10

Java version/vendor (use: java -version) openjdk 21 2023-09-19 LTS OpenJDK Runtime Environment Temurin-21+35 (build 21+35-LTS) OpenJDK 64-Bit Server VM Temurin-21+35 (build 21+35-LTS, mixed mode)

OS type/version macOS Sonoma 14

Description

When using Jetty as an embedded application server and appending classpath / jar patterns to the runtime context, the final resources list in Metadata.java line 488 https://github.com/jetty/jetty.project/blob/a9b2da533f64b923cf06306b5f5faf2c5132f7ce/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/MetaData.java#L488 can end up with duplicates. Depending on which IDE or environment the process in being run in. When run in Intellij Idea with multiple Gradle modules which are web-fragments of which one is the primary, it gets pushed twice to the resources list, and during runtime the duplicate path registration breaks runtime filters in odd ways.

Simply adding a breakpoint on the line 488, stepping over it and with debug tools remove the duplicate (distinct the list) and the issue gets resolved.

How to reproduce? Multi module project with one main web app and multiple fragments of which one has

<ordering>
  <before>
    <others/>
  </before>
</ordering>
janbartel commented 3 months ago

@jackeri do you have a reproduction ? I can't reproduce it with the information in the PR and our standard jetty-ee10-demo-spec webapp.

jackeri commented 3 months ago

I sadly cannot provide the actual issue project as a sample as it is proprietary software, but essentially having jetty startup from a library module (when I say module I mean a Gradle submodule), and said project having a multiple web-fragments of which one has the ordering set. The dependencies also include spring security, which has a fragment of its own. These all modules are then included with the Gradle "includeBuild" mechanism to the actual Web-application project.

The embedded jetty sets up the required class folders and dependencies with the following patterns for direct disk read:

List<String> jarPatterns = new LinkedList<>();
jarPatterns.add(".*org\\.webjar.*\\.jar$");
jarPatterns.add(".*spring-.*\\.jar$");
// Eclipse specific output path
jarPatterns.add(".*/main/$");

// IntelliJ specific output paths (cls and resources are separated)
jarPatterns.add(".*/production/classes/$");
jarPatterns.add(".*/production/resources/$");

WebAppContext context = new WebAppContext();
context.setAttribute(MetaInfConfiguration.CONTAINER_JAR_PATTERN, String.join("|", jarPatterns));

If the issue really needs an example project, then I can try to provide you with an example setup, but it might take a couple of days for me to get to it. This also only happens with IntelliJ, haven't seen the same issue with Eclipse. The simple fix is to just distinct the resources when loading, as I did in the pull request https://github.com/jetty/jetty.project/pull/11790.

janbartel commented 3 months ago

@jackeri I'm reluctant to change something that doesn't look broken according to our tests, so it would be really great if you can supply a small repro test case that can be loaded into IntelliJ.

janbartel commented 1 month ago

@jackeri as I said before, I can't reproduce a problem. It could just be that your patterns match the same jar multiple times, or you really do have the same jar on the classpath multiple times. That might be visible on the logging output of jetty - at least it will be if there are classes that are being scanned from multiple locations. I'm not keen to change jetty unless I can get a reproduction test case.