Getting the Spock out of a Gradle War

Posted by: Ken Sipe on 04/05/2012
I recent ran into a interesting situation, for which I thought it would be worth sharing. I have a new project with the following build needs: Java, Spring MVC and Spock Testing. The problem is simple... The WAR build in gradle was building a WAR file that included the Groovy libraries. This project has no need for groovy at runtime. Groovy is needed because I'm using Spock for my testing.

Gradle and providedCompile

In older versions of Gradle it was commonly necessary to manage the jars in the lib directory. In the maven world, there is a dependency scope of "provided". This scope basically means that the dependency will be provided on the server classpath, however for the purposes of compiling the code in the project it is necessary. From a WAR perspective it means use this dependency for compile, but do not include it in the lib directory of the WAR. Gradle within the last year has added the same feature as providedCompile or providedRuntime. In my project I have this very need with the servlet-api, shown below.
dependencies {
compile "org.springframework:spring-webmvc:$springVersion"
compile 'javax.servlet:jstl:1.2'
providedCompile 'javax.servlet:servlet-api:2.5'
}

Spock dependencies and Gradle

As Spock is a groovy testing tool, it is no surprise that Spock requires groovy. This requires a couple of well documented configurations in your gradle file. First, you'll have to add the groovy plugin. Second you have to set as a dependency the groovy version. But wait!!! The dependency for groovy doesn't have a scoping ability. This is area where the "model" of gradle breaks down a little bit IMO. Ideally you would be interested in expressing in the model that there are "testing" needs... and those testing needs require groovy and spock dependencies.
apply plugin: 'groovy'

def spockVersion = '0.5-groovy-1.8'
def springVersion = '3.1.0.RELEASE'

dependencies {
groovy 'org.codehaus.groovy:groovy-all:1.8.3'
testCompile 'junit:junit:4.8.1'
testCompile "org.spockframework:spock-core:$spockVersion"
testCompile "org.spockframework:spock-spring:$spockVersion"
}
With this groovy dependency any build of WAR will result in a the groovy-all-?.?.?.jar file being added to the the WEB-INF/lib directory. The problem is I have no current interest in having groovy in production for this project. What to do? What to do?

Gradle Doc to the Rescue

I find that a large number of people (usually new to gradle) struggle with discovering how to resolve such a problem. The best starting point for getting to know gradle is the gradle user guide documentation, but the best starting point to use as a reference is the gradle dsl documentation (http://gradle.org/docs/current/dsl). Hopefully it is obvious that what we want to change is the build of the WAR. So lets look at the War task. Here we see all of it's properties... which includes the classpath property. The documentation for this property clearly states that this property affects the WEB-INF/classes and the WEB-INF/lib. Diving deeper into that property we see the default behavior which is:
project.configurations.runtime - project.configurations.providedRuntime
So our logical solution would be to include a war task configuration for the building of the classpath like this:
war {
classpath = classpath - project.configurations.groovy
}


Happy Coding! and may your builds never fail!

About Ken Sipe

Ken Sipe

Ken has been a practitioner and instructor of RUP since the late 1990s, and an extreme programmer and coach since the middle 2000s. Ken has worked with Fortune 500 companies to small startups in the roles of developer, designer, application architect and enterprise architect. Ken's current focus is on enterprise system automation and continuous delivery systems.

Ken is an international speaker on the subject of software engineering speaking at conferences such as JavaOne, JavaZone, Jax-India, and The Strange Loop. He is a regular speaker with NFJS where he is best known for his architecture and security hacking talks. In 2009, Ken was honored by being awarded the JavaOne Rockstar Award at JavaOne in SF, California and the JavaZone Rockstar Award at JavaZone in Oslo, Norway as the top ranked speaker.

More About Ken »

Northern Virginia Software Symposium

November 1 - 3, 2013

Reston, VA

Current Topics on the NFJS Tour

  • Core Java, JEE
  • Dynamic Languages: Groovy, JRuby, Scala, Clojure
  • RESTful Web Apps
  • Frameworks: Hibernate, Grails, Spring, JSF, GWT, more
  • Agility
  • Test Driven Design
  • Security
  • Ajax, Flex, RIA
View Event Details »

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 7
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 3
  • Automation Tools: Git, Hudson, Sonar
  • HTML5, Ajax, jQuery, Usability
  • Mobile Applications - iPhone and Android
  • More...
Learn More »

NFJS, the Magazine

May Issue Now Available
  • On the road to learning

    by Raju Gandhi
  • Refactoring to Modularity

    by Kirk Knoernschild
  • RESTful Groovy

    by Kenneth Kousen
  • Getting Started with D3.js

    by Brian Sletten
Learn More »