Search code examples
javamavenguavajsr305

Why do I need adding artifact JSR305 to use Guava 14+?


While looking for informations on stackoverflow, I have seen a question similar to mine, but with no real answer here.

I need migrating my maven project from guava 11.0.2 to guava 14 or higher (I need RangeSet). I updated my maven pom with the dependency:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>14.0</version>
</dependency>

I then run the maven build, and got this error:

[ERROR] xxx.java: cannot find symbol
[ERROR] symbol  : class Nonnull
[ERROR] location: package javax.annotation

I took a look closer, and this annotations is provided with JSR305, on which depends guava 11.0.2, as mvn repository reports it.

What I find strange is that guava 14 also depends on JSR305 as mvn repository reports.

If I add the JSR dependency to my pom, then the compilation just runs fine:

<dependency>
    <groupId>com.google.code.findbugs</groupId>
    <artifactId>jsr305</artifactId>
    <version>1.3.9</version>
    <scope>provided</scope>
</dependency>

But why would I have to add this dependency to my pom if guava already depends on it ? This looks more to a workaround than to a solution, and I would prefer to understand and make things clean.

Thanks for participating.


Solution

  • The reason that you need to add it as a dependency is because Guava 14 defines the dependency in their pom as follows:

    <dependency>
        <groupId>com.google.code.findbugs</groupId>
        <artifactId>jsr305</artifactId>
        <version>1.3.9</version>
        <scope>provided</scope>
    </dependency>
    

    The important part for your problem is the <scope>provided</scope> line.

    From the maven website they state the following with regards to provided dependencies:

    provided: This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.

    So basically because Guava have set this as a provided dependency they expect whoever is consuming Guava to provide this dependency which is exactly what you have had to do.

    In Guava 11.0.2 it was a normal compile dependency, hence you didn't have to provide it in your own project.

    The change was made in Guava 13. From the release notes:

    Made findbugs a provided dependency to avert dep conflicts when using findbugs 2.0. The side-effect of this change is that projects which relied upon Guava to grant access to the JSR-305 annotations "for free" will break unless they provide their own direct dependency on that jar (or an equivalent). Projects should always have been directly depending on JSR-305 (per maven best-practice), but this change makes that should into a must.