Emulating Maven’s “provided” scope in Gradle

I’m not a fan of Maven. I don’t make any secret of it. But one thing they’ve got right is the “provided” scope – that is, a scope whose dependencies are used at compile time, but not required at runtime because they’re expected to already be present. The canonical example of the use of this scope is the Servlet or JSP API – it needs to be present at compile time to compile against, but the container provides it at runtime, so it doesn’t need to be explicitly pulled in as a runtime dependency.

I am however, a big fan of Gradle. Gradle’s Java plugin provides a number of default “configurations” (revealing Gradle’s close relationship to Ivy) which bear a close resemblance to Maven’s scopes. However, the Java plugin doesn’t provide anything like Maven’s “provided” scope. (Note: the War plugin does provide both “providedCompile” and “providedRuntime” configurations.)

Why would you want a “provided” configuration in a Java project? Well, my particular use case was that I was writing a custom Ant task (I’m aware of the irony of using Gradle to build this!) and I needed to compile against the Ant API – but, of course, at run time the Ant JAR is already present.

Having pieced together a number of posts on the internet, I came up with the following:

configurations {
    provided
}

sourceSets {
    main.compileClasspath += configurations.provided
    test.compileClasspath += configurations.provided
    test.runtimeClasspath += configurations.provided
}

dependencies {
    provided 'org.apache.ant:ant:1.8.4'
}

This works, but it feels a bit dirty.

If you’re an Eclipse user (of course you are!) it also has one major flaw. If you’re using the Eclipse STS Gradle plugin to create a managed classpath in your Eclipse project (rather than using Gradle’s Eclipse plugin to generate your .classpath and .project files), you’ll find that Eclipse doesn’t know anything about your “provided” dependencies and you have a bunch of compile errors.

Here’s how to sort that out:

apply plugin: 'eclipse'

eclipse.classpath.plusConfigurations += configurations.provided

So, you have to add Gradle’s Eclipse plugin – even if you wouldn’t otherwise be using it – and add your “provided” dependencies to the Eclipse classpath configuration. Even if you don’t use the Gradle Eclipse plugin, the Eclipse STS Gradle plugin uses the same model and will now pick up your “provided” dependencies.

There is an outstanding Gradle bug report/enhancement request for this feature, but for some reason it’s struggling to get traction. If you feel this is important enough to be a built-in part of the Gradle Java plugin, please vote for this issue.

Share this:
Facebook Twitter Digg Email

This entry was posted in Build. Bookmark the permalink.

10 Responses to Emulating Maven’s “provided” scope in Gradle

  1. Tim Biegeleisen says:

    The above code does not work used as-is. Gradle complains that it doesn’t know about sourceSets.

  2. Many thanks. After reading dozens of pages purporting to solve this problem, trying them out and failing (but learning a lot about Gradle on the way), I finally came across your post. It’s short, sweet, and worked first time.

    Truly appreciated.

  3. Danny says:

    If you take a look at the linked bug report (http://issues.gradle.org/browse/GRADLE-784), you’ll find a comment on 18 July about the Spring guys having this functionality in one of their plugins. I’ve taken a look at the source code and it looks pretty straightforward, so hopefully the Gradle guys will bring that into the core platform soon.

  4. Christian Essl says:

    Many thanks for that. I can only repeat what Philip has said. Finnally a solution which works great, and also a right comment regarding the missing ‘provided’ scope in gradle

  5. Raphael says:

    How do I install that spring guys plugin?

  6. Jack says:

    For more recent version of Gradle

    eclipse.classpath.plusConfigurations += configurations.provided

    should be

    eclipse.classpath.plusConfigurations += [ configurations.provided ]

  7. Dmitry says:

    With Gradle 2.12 you now can use ‘compileOnly’ scope.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>