Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jetty-maven-plugin - maven internal dependencies included on webapp classloader #7677

Closed
unb opened this issue Mar 1, 2022 · 13 comments
Closed
Assignees
Labels
Bug For general bugs on Jetty side

Comments

@unb
Copy link

unb commented Mar 1, 2022

Jetty version(s)
9.4.38.v20210224

Maven version
3.6.3

Description

When using maven to run a webapp using jetty:run some of the maven's internal dependencies are included on the classpath used to launch the jetty-maven-plugin.

This includes jsr305-3.0.2.jar (com.google.code.findbugs:jsr305), depended on by org.apache.maven:maven-core.
This jar includes a javax.annotation package, which is problematic for our embedded OSGi support as it conflicts with the javax.annotation package provided by Jetty.

It would be good if either:

  • these were not on the webapp classpath; or
  • there was a facility to exclude jars that aren't project dependencies

The workaround is to manually exclude jsr305 by manipulating the jetty-maven-plugins dependencies.
This is a little brittle as it needs to be updated each time jetty-maven-plugin is updated:

<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>9.4.38.v20210224</version>
    <configuration>
        <useTestScope>true</useTestScope>
        <useTestClasspath>true</useTestClasspath>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-core</artifactId>
            <version>3.6.0</version>
            <exclusions>
                <exclusion>
                    <groupId>com.google.code.findbugs</groupId>
                    <artifactId>jsr305</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
</plugin>

How to reproduce?

Easiest approach is to attach a debugger to a webapp launched using jetty:run and try load one of the classes included by jsr305. E.g.:

  • HttpServlet.class.getClassLoader().loadClass("javax.annotation.Nullable")
  • HttpServlet.class.getClassLoader().loadClass("javax.annotation.OverridingMethodsMustInvokeSuper")

When using the exclusion shown above, these classes are no longer available and the calls throw ClassNotFoundException

@unb unb added the Bug For general bugs on Jetty side label Mar 1, 2022
@olamy
Copy link
Member

olamy commented Mar 1, 2022

You should try with a more recent version of Maven Core (3.8.4 should not have this problem anymore if still I can have a look at fixing it).

By the way you should notice jsr 305 have been voted as dormant (so almost dead).
Not sure what tool you are using for those annotations but you should have a look at spotbugs which is the kind of standard tool and have his own similar annotations.
In your case this is coming because of transitive dependencies of old version of guava (now they have removed usage of it for more details have a look here google/guava#2960 )

@janbartel
Copy link
Contributor

@unb interesting. Could you share more about how you are starting and configuring your osgi container via the jetty-maven-plugin, and how the jsr305-3.0.2.jar is related to your webapp? For example, are you specifically deploying that jar from your webapp?

The jsr305-3.0.2.jar, whilst it contains the package javax.annotation has no overlap at all with the javax.annotation packages in javax.annotation-api-1.3.2.jar that is provided and used by jetty on it's server classpath. So there is no way the same class could be loaded by 2 different classloaders. Thus, I assume the problem you're referring to the fact that the javax.annotation package is split, which is a no-no for osgi, but I'd like to see the error you get from the osgi container. Do you get resolution problems? Or, is the problem that your webapp is re-deploying the jsr305-3.0.2.jar?

I tend to agree that machinery from the plugin shouldn't leak into the webapp, however, as this is a javax.annotation package it's a somewhat special case and requires careful resolution, so I would like to understand your situation as well as possible before jumping in to fixes.

@janbartel janbartel self-assigned this Mar 1, 2022
@unb
Copy link
Author

unb commented Mar 1, 2022

@janbartel We don't use jsr305-3.0.2.jar. It's being pulled in by Maven.

You can see it is a dependency of maven-core by running:

`mvn -f "$HOME/.m2/repository/org/apache/maven/maven-core/3.6.0/maven-core-3.6.0.pom" dependency:tree
[INFO] --- maven-dependency-plugin:3.1.1:tree (default-cli) @ maven-core ---
[INFO] org.apache.maven:maven-core:jar:3.6.0
....
[INFO] +- com.google.inject:guice:jar:no_aop:4.2.1:compile
[INFO] |  +- aopalliance:aopalliance:jar:1.0:compile
[INFO] |  \- com.google.guava:guava:jar:25.1-android:compile
[INFO] |     +- com.google.code.findbugs:jsr305:jar:3.0.2:compile

(replace $HOME/.m2/repository with wherever your maven repository is located)

The workaround shown in the original post adds the dependency on maven-core so it can exclude js305.

We embed the Atlassian Plugin Framework, which uses Apache Felix.
Part of the bootstrapping process involves going through the jars on the classpath and working out what packages and versions they expose, using org.twdata.pkgscanner.PackageScanner.
These all get passed to Felix via the org.osgi.framework.system.packages.extra property.

What seems to be happening is that PackageScanner will (sometimes, rarely) determine that javax.annotation is version 3.0.2 (from jsr305-3.0.2.jar) rather than the 1.3.x provided by Jetty.

@joakime
Copy link
Contributor

joakime commented Mar 1, 2022

@unb that jar (jsr305) is from maven yes, and from many different places in maven too (core, shared components, surefire, assembly plugin, etc), and its existence in your project and/or plugin is a bug in maven, supposedly fixed in maven 3.8.4. (newer plugin versions also upgraded the version of jsr305 dependency to at least version 3.0.3)

@unb
Copy link
Author

unb commented Mar 1, 2022

@joakime & @olamy I can still see it on the classpath when running jetty under Maven 3.8.4. I also updated jetty to 9.4.45.v20220203
You can see it is still a dependency of maven-core:

mvn -f "$HOME/.m2/repository/org/apache/maven/maven-core/3.8.4/maven-core-3.8.4.pom" dependency:tree
[INFO] --- maven-dependency-plugin:3.1.1:tree (default-cli) @ maven-core ---
[INFO] org.apache.maven:maven-core:jar:3.8.4
...
[INFO] +- com.google.inject:guice:jar:no_aop:4.2.2:compile
[INFO] |  +- aopalliance:aopalliance:jar:1.0:compile
[INFO] |  \- com.google.guava:guava:jar:25.1-android:compile
[INFO] |     +- com.google.code.findbugs:jsr305:jar:3.0.2:compile

@joakime
Copy link
Contributor

joakime commented Mar 2, 2022

Obviously maven-core itself will show that dependency.

What about your project?

@olamy
Copy link
Member

olamy commented Mar 2, 2022

I guess this change in jetty-10.0.x might help you #7626
any chance you could try with Jetty 10.0.9-SNAPSHOT?

@unb
Copy link
Author

unb commented Mar 2, 2022

@joakime It doesn't show up in a mvn dependency:tree listing
Running mvn -X -e jetty:run I can see maven creating a ClassRealm with it included.
Attaching to the running webapp with a debugger, there is no jsr305-3.0.2.jar in the ucp of org.eclipse.jetty.webapp.WebAppClassLoader. It is however in the parent org.codehaus.plexus.classworlds.realm.ClassRealm classloader ClassRealm[plugin>org.eclipse.jetty:jetty-maven-plugin:9.4.45.v20220203]

@olamy Thanks - I'll try it out later. In the meantime, I'll just exclude it from the classpath.

@olamy
Copy link
Member

olamy commented Mar 2, 2022

@unb do you have a simple project we could use to reproduce?

@unb
Copy link
Author

unb commented Mar 2, 2022

@olamy Not as yet. I will try and produce one in the next day or so.

@unb
Copy link
Author

unb commented Mar 2, 2022

The zip jetty-7677.zip demonstrates the issue.

It produces a listing of all of the jars available to the servlet when launched by mvn jetty:run

To use, download and:

  1. jar xvf jetty-7677.zip
  2. cd jetty-7677
  3. mvn jetty:run
  4. curl http://localhost:8080/test

If com.google.code.findbugs:jsr305 is present, it will be shown as jsr305-3.0.2.jar

@janbartel
Copy link
Contributor

@unb I've raised a pr to exclude jsr305 jar from the maven core dependency, see #7682. That seems to be the most straightforward way to solve this. Alternative solutions would require knowlege of how org.twdata.pkgscanner.PackageScanner scans the classloader hierarchy - ie how far up it traverses.

janbartel added a commit that referenced this issue Mar 28, 2022
* Issue #7677 Exclude findbugs jsr305 jar from plugin

Signed-off-by: Jan Bartel <janb@webtide.com>

* add IT test for those classes exclusions

Signed-off-by: Olivier Lamy <oliver.lamy@gmail.com>
@janbartel
Copy link
Contributor

Fixed via #7682

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug For general bugs on Jetty side
Projects
None yet
Development

No branches or pull requests

4 participants