40

I want to reuse certain filter for many projects so I want to extract it and use a single jar to just add it to any Web App.

For building I am using Gradle 1.3 and the following build.gradle file:

apply plugin: 'java'

dependencies {

    compile group:'org.slf4j', name:'slf4j-api', version:'1.7.+'

    testCompile group:'junit', name:'junit', version:'4.+'

    compile group:'org.springframework', name:'spring-web', version:'3.+'   

    compile group:'org.slf4j', name:'slf4j-log4j12', version:'1.6.+'
    compile group:'log4j', name:'log4j', version:'1.2.+'

    providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version:'3.+'        

}

repositories {

    mavenCentral()

}

As you can see, I need the servlet api to compile this filter succesfully so I want to add it like a maven provided dependency.

Anyways, after running gradle build I get the following error:

Could not find method providedCompile() for arguments [{group=javax.servlet, name=javax.servlet-api, version=3.+}] on root project 'hibernate-conversation-context'.

Now, I know that I cannot use providedCompile without the WAR plugin but I need the project to be a simple JAR. Is there another way to do this?

ElderMael
  • 7,000
  • 5
  • 34
  • 53
  • Possible duplicate of [How do I define a compile-time \*only\* classpath in Gradle?](http://stackoverflow.com/questions/10405970/how-do-i-define-a-compile-time-only-classpath-in-gradle) – Nick Grealy Aug 23 '16 at 01:44

7 Answers7

54

There is no such configuration out of the box for the java plugin. However you can build it yourself as follows:

configurations { providedCompile }

dependencies {
    providedCompile "javax.servlet:javax.servlet-api:3.+"
}

sourceSets.main.compileClasspath += configurations.providedCompile
sourceSets.test.compileClasspath += configurations.providedCompile
sourceSets.test.runtimeClasspath += configurations.providedCompile

This adds the configuration, and puts all the dependencies in there on the compile classpaths of both your main classes and test classes. You also need to add it to the runtimeClasspath, as that doesn't include the compile classpath according to the gradle DSL documentation.

Hiery Nomus
  • 17,429
  • 2
  • 41
  • 37
  • 1
    Just a warning to people that this solution is not compatible with Eclipse. The answer by dty shows the method to get it working there. Basically just by adding: eclipse.classpath.plusConfigurations += configurations.providedCompile to the build file. – IcedDante Aug 28 '14 at 22:07
  • 3
    For a solution that works within both Eclipse and IntelliJ, see here: http://stackoverflow.com/a/25809968/2591231 – Doron Gold Sep 12 '14 at 14:44
  • Things get complicated when we want to add support for idea plugin. Gradle 2.x is built on top of Groovy 2.3, that does not support adding single element into the collection with +=. This may result in failure "Cannot change configuration ':provided' after it has been resolved". Usages of += in the answer are OK, but if you have this error you may need to wrap the right side after += with [ ]. See this discussion: https://discuss.gradle.org/t/custom-provided-configuration-not-working-with-gradle-2-0-rc2-in-multi-project-mode/2459 – virgo47 May 13 '15 at 10:56
  • I submitted a feature request, https://discuss.gradle.org/t/need-providecompile-for-java-plugin/10457 to add providedCompile for the java plugin – djb Jul 06 '15 at 17:15
  • This seems to break javadoc `{@link }` references – Gus Mar 22 '17 at 21:28
  • Unfortunately, if you later add a War task, with appropriate plugin, it will gripe "Cannot add a configuration with name 'providedCompile' as a configuration with that name already exists." – Meower68 Jul 14 '17 at 16:12
14

Take a look at the Gradle plugin propdeps from SpringSource. From the project description:

Provides additional optional and provided dependency configurations for Gradle along with Maven POM generation support.

Gerhard Schlager
  • 3,155
  • 1
  • 31
  • 53
  • Thanks for the pointer, the example from the SpringSource page resolved this issue for me. I think it's odd that Gradle doesn't have a notion for provided out of the box. – Spanky Quigman Sep 20 '13 at 16:18
  • This is a straightforward solution, but I find that it still results in the provided JARs getting packaged into my WAR, which I would not expect to happen. – Nick Spacek Jan 15 '16 at 18:21
13

As of Gradle 2.12 the issue of defining compile only dependencies is finally solved in a simple and natural manner by the new "copmpileOnly" configuration:

dependencies {
    compileOnly 'javax.servlet:servlet-api:2.5'
}
Doron Gold
  • 3,664
  • 4
  • 32
  • 44
  • In my opinion, compileOnly has slightly different semantics. providedCompile suggests that the Application Server will provide it, whereas compileOnly suggests that the package is only needed during compilation (e.g. Lombok annotations) and not at runtime. – Nick Spacek Mar 14 '18 at 18:24
6

I wrote a blog post recently which covers exactly this scenario. It also shows you how to get integration with Eclipse set up properly too.

http://blog.codeaholics.org/2012/emulating-mavens-provided-scope-in-gradle/

dty
  • 18,795
  • 6
  • 56
  • 82
6

When you find yourself using Gradle 2.12, change 'providedCompile' to 'compileOnly'.

ginzsa
  • 61
  • 1
  • 1
5

There is an easier way:

configurations {    
    provided
    provided.extendsFrom(compile)
}

and then you can:

dependencies {  
    provided group: 'javax.servlet', name: 'javax.servlet-api', version:'3.+' 
}

You will also want to have the provided libraries in the generated project files of Eclipse or Idea:

idea.module.scopes.PROVIDED.plus += configurations.provided
eclipse.classpath.plusConfigurations += configurations.provided
Dima Gutzeit
  • 221
  • 4
  • 3
  • I did not get this to work without the sourceSets-additions. What am I doing wrong? Thanks for the IDEA fix, though. – stolsvik Jul 17 '15 at 20:21
  • 1
    Also, the Eclipse and IntelliJ fixes now needs square brackets around them, like so: `eclipse.classpath.plusConfigurations += [ configurations.provided ]` – stolsvik Jul 17 '15 at 23:53
4

To make the javadoc work I had to add this:

javadoc.classpath=sourceSets.main.compileClasspath
Peter Borbas
  • 158
  • 6