Loading...

Friday, March 18, 2016

Gradle Goodness: Source Sets As IntelliJ IDEA Modules

IntelliJ IDEA 2016.1 introduced better support for Gradle source sets. Each source set in our project becomes a module in the IntelliJ IDEA project. And each module has it's own dependencies, also between source sets. For example if we simply apply the java plugin in our project we already get two source sets: main and test. For compiling the test sources there is a dependency to the main source set. IntelliJ now knows how to handle this.

Let's create a sample Gradle build file with an extra custom source set and see what we get in IntelliJ IDEA. In the following example build file we add the source set api. This source set contains interfaces without implementations. The implementations for the interfaces are in the default main source set. Finally we have some tests in the test source set that depend on the classes generated by the api and main source sets.

apply plugin: 'groovy'
apply plugin: 'idea'

sourceSets {
    // Define new source set
    // with the name api. This 
    // source set contains interfaces,
    // implementation classes are in
    // the main source set.
    api
}

repositories {
    jcenter()
}

dependencies {

    // The default source set main
    // has a compile dependency on the 
    // output of the api source set.
    // Gradle will invoke the apiClasses
    // task automatically if we compile
    // the sources in the main source set.
    compile sourceSets.api.output
    
    testCompile 'org.spockframework:spock-core:1.0-groovy-2.4'
}

When we invoke the idea task to generate the IntelliJ IDEA project files or we import the build.gradle file into IDEA we can see in the Gradle tool window a new element: Source Sets. When we open the node we see all the source sets in our project with their dependencies:

When we right click on the project and select Open Module Settings we get a new dialog window. All source sets are separate modules grouped into a single module. In our example the module group is idea-sourcesets and it has three modules. If we click on the idea-sourcesets_test and select the Dependencies tab we see a list of dependencies for the source set:

Written with Gradle 2.12 and IntelliJ IDEA 2016.1.

Wednesday, March 16, 2016

Gradle Goodness: Enable Compiler Annotation Processing For IntelliJ IDEA

Suppose we have a project where we use Lombok annotations. To use it we must change the compiler configuration for our project and enable annotation processing. We can find this in the Preferences or Settings window under Build, Execution, Deployment | Compiler | Annotation Processors. Here we have a checkbox Enable annotation processing that we must check to use the annotations from IntelliJ IDEA. We can automate this setting with some configuration in our Gradle build file.

In the next example build file we alter the generated IntelliJ IDEA project file using the withXml hook. We can access the generated XML as a groovy.util.Node and change the XML.

// File: build.gradle
apply plugin: 'groovy'
apply plugin: 'idea'

repositories {
    jcenter()
}

dependencies {
    compile('org.projectlombok:lombok:1.16.6')
}

idea {
    project {
        ipr {
            withXml { provider ->
                // Get XML as groovy.util.Node to work with.
                def projectXml = provider.asNode()
                
                // Find compiler configuration component.
                def compilerConfiguration = projectXml.component.find { component ->
                    component.'@name' == 'CompilerConfiguration'
                }
                
                // Replace current annotationProcessing
                // that is part of the compiler configuration.
                def currentAnnotationProcessing = compilerConfiguration.annotationProcessing
                currentAnnotationProcessing.replaceNode {
                    annotationProcessing {
                        profile(name: 'Default', default: true, enabled: true) {
                            processorPath(useClasspath: true)
                        }
                    }
                }
            }
        }
    }
}

Written with Gradle 2.12 and IntelliJ IDEA 15.

Gradle Goodness: Add Spring Facet To IntelliJ IDEA Module

To create IntelliJ IDEA project files with Gradle we first need to apply the idea plugin. We can then further customise the created files. In this blog post we will add a Spring facet to the generated module file. By adding the Spring facet IntelliJ IDEA can automatically search for Spring configuration files. We can then use the Spring view to see which beans are configured in our project.

In the following example build file we use the withXml hook. This method is invoked just before the XML file is generated. We get an argument of type XmlProvider. From the XmlProvider we can access the XML as org.w3c.dom.Element, StringBuilder or groovy.util.Node. We use Node to alter the XML. We check if a FacetManager component is available. We need this to add a facet of type Spring.

// File: build.gradle
apply plugin: 'groovy'
apply plugin: 'idea'

idea {
    module {
        iml {
            withXml { 
                // Get root of module as groovy.util.Node.
                def moduleRoot = it.asNode()
                
                // Find if component with name 'FacetManager'
                // is already set.
                def facetManager = moduleRoot.component.find { component -> component.'@name' == 'FacetManager'}
                if (!facetManager) {
                    // Create new component with name 'FacetManager'
                    facetManager = moduleRoot.appendNode('component', [name: 'FacetManager'])
                }
                
                // Find Spring facet it might already be there.
                def springFacet = facetManager.facet.find { facet -> facet.'@type' == 'Spring' && facet.'@name' == 'Spring' }
                if (!springFacet) {
                    // If not set create new facet node with name 'Spring'
                    // and type 'Spring' and apply a default configuration.
                    springFacet = facetManager.appendNode('facet', [type: 'Spring', name: 'Spring'])
                    springFacet.appendNode('configuration')
                }
            }
        }
    }
}

Written with Gradle 2.12 and IntelliJ IDEA 15.

Gradle Goodness: Set VCS For IntelliJ IDEA In Build File

When we use the IDEA plugin in Gradle we can generate IntelliJ IDEA project files. We can customise the generated files in different ways. One of them is using a simple DSL to configure certain parts of the project file. With the DSL it is easy to set the version control system (VCS) used in our project.

In the next example build file we customise the generated IDEA project file and set Git as the version control system. The property is still incubating, but we can use it to have a proper configuration.

// File: build.gradle
apply plugin: 'groovy'
apply plugin: 'idea'

idea {
    project {
        // Set the version control system
        // to Git for this project.
        // All values IntelliJ IDEA supports
        // can be used. E.g. Subversion, Mercurial.
        vcs = 'Git'
    }
}

Written with Gradle 2.12 and IntelliJ IDEA 15.

Gradle Goodness: Configure IntelliJ IDEA To Use Gradle As Testrunner

When we run tests in IntelliJ IDEA the code is compiled by IntelliJ IDEA and the JUnit test runner is used. We get a nice graphical overview of the tasks that are executed and their results. If we use Gradle as the build tool for our project we can tell IntelliJ IDEA to always use Gradle for running tests.

We must open the Preferences or Settings dialog window. There we can search for Gradle and then look for Build, Execution, Deployment | Build Tools | Gradle | Runner:

We can select different values for the Run tests using option. The default value is Platform Test Runner. To use Gradle we select Gradle Test Runner. Finally we can choose for Let me choose per test. Let's select the option Gradle Test Runner and click on the OK button to close the dialog window.

Next we run our test code from the IDE:

The test is started using the Gradle tasks cleanTest and test with the option --tests with the name of our test class. In the Run window we can see how the test is executed and the graphical representation of the tests:

If we choose the option Let me choose per test then we must first select the runner if we run a test for the first time:

Our choice is remembered for next runs of the same test. We must delete the run configuration from Run | Edit configurations... if we want to choose the runner again.

Written with IntelliJ IDEA 15 and Gradle 2.12.

Javaland 2016 Conference Report

It has already been a week since Javaland 2016 started on Tuesday March 8th. Javaland is 3-day community driven conference in the amusement park Phantasialand in Brühl, Germany. I had the fortune to attend the conference this year and speak about Asciidoctor on the first day with my talk "Writing documentation in Asciidoctor is Awesome". The code and examples from the presentation are on Github. Also my colleague Rob Brinkman was at the conference for this talk about "Westy Tracking (turning a VW van into a Tesla)" and his presentation is online as well.

What I really liked about the conference is a lot of technical talks about all kind of Java subjects. Even for a non-German person there were a lot of talks in English to follow. Also the atmosphere was very nice, people are approachable and in between talks there was a nice community and sponsor exhibition room. The organization uses the knowledge and experience of 29 JUGs from Germany, Austria and Switzerland. And then the location is also great to have a conference. The amusement park wasn't open for the public so we as Java developers had part of the park for ourselves. The location of the talks were partially in theaters and in business rooms. And at Tuesday night we were allowed to go on rides as well. (Remember: first rides, then eat and drink, if you alter the order you might get in trouble).

The first day started with an explanation about the program, talks, different community events from the organization. Next we attended a session about how to visualize relations between Wikipedia articles from James Weaver. He showed a Spring application backend with an Angular frontend running on Cloudfoundry. Next up was Rob Brinkman with his excellent talk on how he added electronics to an "old" VW van, so he could save his trips and tracking information. He showed the software architecture he used with Vert.x 3, Redis, Java 8 and Angular to make it all work together. It was time for lunch and that was very good organized. A lot of different things to choose from and it tasted very well. After lunch we attended a short talk about streams and reactive programming that was very informative given by Jan Carsten Lohmüller. In the afternoon we stayed a while at the community floor and stumbled upon a nice small presentation from Andres Almiray about a JSR for desktop applications. The setting was very informative and I really liked this aspect of the conference. Furthermore we attended a session about Lombok to reduce the boilerplate code in Java presented by Roel Spilker and Reinier Zwitserloot. Bert Jan Schrijver gave a good presentation about performance testing with Gatling. He even did live Scala coding on stage! Gatling looks like a very nice tool to define scenario's for simulating multiple users accessing your application.

At night the park was open and some attractions were open, especially the roller coaster rides. Also there was a good diner organized at different locations.

The second day of the conference started for me with a talk by Josh Long about Spring Cloud. The Spring Cloud project has a lot of very useful subprojects to work with microservices in a distributed manner. Even though the session could only last 40 minutes Josh managed to show a lot of cool stuff with live coding small applications. At lunch time I attended a good talk which started with a cool Lego demo by Johan Janssen and Martin Kanters. They managed to control Lego trains and a fairy wheel from their browser. And it all worked as well. They used Akka on Raspberry Pi's to make it all work and explained the software architecture.

After another tasteful lunch I learned more about monads in Java 8. Normally this is a very theoretical subject, but presenter Oleg Shelajev did a good job and showed real code on how monads appear in Java. The last session of the day was about using Groovy as a system scripting language by Andrey Adamovich. He showed the cool stuff of Groovy to make as script developer so much easier. Instead of relying on Bash or another script language, just use Groovy and all the Java libaries we already know.

The final day of the conference was a tutorial/workshop day. I attended a Vert.x 3 workshop given by Jochen Mader. Although it was in German I could still follow it very well. He presented some theory and then we could make small exercises in Vert.x 3. Then we would look at possible solutions for the exercise given by Jochen. I learned a lot during this day.

It was the first time I went to Javaland and it was a very good experience. The location, the organization and the content are all excellent. Although I already know I cannot make it next year, I still want to come back during the next years.

Spring Sweets: Create New Projects From a URL

To quickly start with a Spring project we can use the website start.spring.io. Via a user interface we can set project properties and at the end we have a project archive (Zip or gzipped Tar file) or build file (pom.xml or build.gradle). We can also directory access an URL to create the output files and we set the properties via request parameters. This way you can share a link with someone and if they click on it they will download the generated project archive or build files.

We can choose different base URLs depending on the type of project archive we want. To get a Zip file we use http://start.spring.io/starter.zip and to get a gzipped Tar file we use http://start.spring.io/starter.tgz. To create a Gradle build file with all the configuration for a project we use http://start.spring.io/build.gradle. For a Maven POM XML file we use the URL http://start.spring.io/pom.xml.

All output format support the same request parameters to set the project properties:

Request parameterDescriptionSample
dependenciesAdd Spring Boot Starters and dependencies to your applicationweb,security
styleAlias for dependenciesactuator,sleuth,eureka&20discovery
typeUsed for project archives. Use gradle-project or maven-projectgradle-project
nameName of projectdemo
descriptionDescription for the projectDemo%20project%20for%20Spring%20Boot
groupIdValue for groupId for publishing projectcom.example
artifactIdValue for artifactId for publishing projectdemo
versionVersion of the project1.0.0.DEVELOPMENT
bootVersionVersion for Spring Boot1.3.3
packagingPackaging for project (jar or war)jar
applicationNameName of the applicationdemo
languageLanguage can be Java, Groovy or KotlinGroovy
packageNameName for package for example codecom.example
javaVersionJava version for project1.8
baseDirBase directory in archivesample


Let's create a URL for a Groovy project with a Gradle build file where we have a dependency on web, security and actuator:

http://start.spring.io/build.gradle?dependencies=web,security,actuator&name=sample&description=Sample&20Project&version=1.0.0.DEVELOPMENT&bootVersion=1.3.3.RELEASE&javaVersion=1.8&language=groovy&packaging=jar

When we save the Gradle build file we have the following file contents:

buildscript {
 ext {
  springBootVersion = '1.3.3.RELEASE'
 }
 repositories {
  mavenCentral()
 }
 dependencies {
  classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 
 }
}

apply plugin: 'groovy'
apply plugin: 'eclipse'
apply plugin: 'spring-boot' 

jar {
 baseName = 'demo'
 version = '1.0.0.DEVELOPMENT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
 mavenCentral()
}


dependencies {
 compile('org.springframework.boot:spring-boot-starter-actuator')
 compile('org.springframework.boot:spring-boot-starter-security')
 compile('org.springframework.boot:spring-boot-starter-web')
 compile('org.codehaus.groovy:groovy')
 testCompile('org.springframework.boot:spring-boot-starter-test') 
}


eclipse {
 classpath {
   containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
   containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
 }
}

task wrapper(type: Wrapper) {
 gradleVersion = '2.9'
}

Instead of just a build file we want to create a sample project archive file. We use the following URL:

http://start.spring.io/starter.tgz?dependencies=web,security,actuator&name=sample&description=Sample&20Project&version=1.0.0.DEVELOPMENT&bootVersion=1.3.3.RELEASE&javaVersion=1.8&language=groovy&packaging=jar&type=gradle-project&baseDir=sample

Let's open the archive and see the contents. Notice we used the baseDir request parameter so when we unpack we get a new directory.

$ tar xf starter.tgz 
$ tree sample/
sample/
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
    ├── main
    │   ├── groovy
    │   │   └── com
    │   │       └── example
    │   │           └── SampleApplication.groovy
    │   └── resources
    │       ├── application.properties
    │       ├── static
    │       └── templates
    └── test
        └── groovy
            └── com
                └── example
                    └── SampleApplicationTests.groovy

14 directories, 8 files
$

We can also use wget, cUrl or Httpie to download a starter template from start.spring.io using request parameters.

Written with Spring Boot 1.3.3.

Thursday, March 10, 2016

Groovy Goodness: Using Tuples

A tuple is an ordered, immutable list of elements. Groovy has it's own groovy.lang.Tuple class. We can create an instance of a Tuple by providing all elements that need to be in the Tuple via the constructor. We cannot add new elements to a Tuple instance or remove elements. We cannot even change elements in a tuple, so it is completely immutable. This makes it very useable as return value for a method where we need to return multiple values. Groovy also provides a Tuple2 class that can be used for tuple instance of only two elements. The elements are typed in a Tuple2 instance.

In the following example we see different uses of the Tuple and Tuple2 classes:

def tuple = new Tuple('one', 1, new Expando(number: 1))

assert tuple.size() == 3

// To get the value of an element
// at a certain position we use
// the get(index) method.
assert tuple.get(0) == 'one'

// We can use the [] syntax to
// get elements from the tuple.
assert tuple[1] == 1

// We can use methods added to the
// Collection API by Groovy.
assert tuple.last().number == 1

// We cannot change the tuple.
try {
    tuple.add('extra')
    assert false
} catch (UnsupportedOperationException e) {
    assert e
}

try {
    tuple.remove('one')
    assert false
} catch (UnsupportedOperationException e) {
    assert e
}

try {
    tuple[0] = 'new value'
    assert false
} catch (UnsupportedOperationException e) {
    assert e
}


// Create a Tuple with fixed size 
// of 2 elements, a pair.
def pair = new Tuple2('two', 2)

// The Tuple2 class has extra methods
// getFirst() and getSecond() to 
// access the values.
assert pair.first == 'two'
assert pair.second == 2

An example on how to use a Tuple2 as return value for a method:

def calculate(String key, Integer... values) {
    // Method return a Tuple2 instance.
    new Tuple2(key, values.sum())
}

// Use multiple assignment to
// extract the values from the tuple.
// Tuple2 has typed objects.
def (String a, Integer b) = calculate('sum', 1, 2, 3)

assert a == 'sum'
assert b == 6

Written with Groovy 2.4.6.

Thursday, March 3, 2016

Gradle Goodness: Adding Custom Extension To Tasks

We can add extensions to our project in Gradle to extend the build script with extra capabilities. Actually we can add extensions to any object in Gradle that implements the ExtensionAware interface. The Task interface for example extends the ExtensionAware interface so we can add custom extensions to Gradle tasks as well. Inside a task configuration we can then use that extension.

In the following build script we use a custom extension for JavaCompile tasks to configure the compiler -Xlint arguments. The extension is added via the plugin com.mrhaki.gradle.JavaCompilerLintPlugin. First we take a look ate the extension class. This is a POGO for configuring the compiler arguments with -Xlint options:

// File: buildSrc/src/main/groovy/com/mrhaki/gradle/JavaCompilerLintExtension.groovy
package com.mrhaki.gradle

/**
 * Extension class for use with JavaCompile tasks
 * to set -Xlint options.
 */
class JavaCompilerLintExtension {

    Boolean cast
    Boolean classfile
    Boolean deprecation
    Boolean depAnn
    Boolean divzero
    Boolean empty
    Boolean fallthrough
    Boolean finallyblocks
    Boolean options
    Boolean overrides
    Boolean path
    Boolean processing
    Boolean rawtypes
    Boolean serial
    Boolean staticref
    Boolean tryblocks
    Boolean unchecked
    Boolean varargs

    void enableAll() {
        cast = true
        classfile = true
        deprecation = true
        depAnn = true
        divzero = true
        empty = true
        fallthrough = true
        finallyblocks = true
        options = true
        overrides = true
        path = true
        processing = true
        rawtypes = true
        serial = true
        staticref = true
        tryblocks = true
        unchecked = true
        varargs = true
    }

    /**
     * Create list of compiler -Xlint arguments.
     * 
     * @return List of -Xlint compiler arguments.
     */
    List<String> asCompilerArgs() {
        final List<String> optionArgs = []
        optionArgs << optionArg('cast', cast)
        optionArgs << optionArg('classfile', classfile)
        optionArgs << optionArg('deprecation', deprecation)
        optionArgs << optionArg('dep-ann', depAnn)
        optionArgs << optionArg('divzero', divzero)
        optionArgs << optionArg('empty', empty)
        optionArgs << optionArg('fallthrough', fallthrough)
        optionArgs << optionArg('finally', finallyblocks)
        optionArgs << optionArg('options', options)
        optionArgs << optionArg('overrides', overrides)
        optionArgs << optionArg('path', path)
        optionArgs << optionArg('processing', processing)
        optionArgs << optionArg('rawtypes', rawtypes)
        optionArgs << optionArg('serial', serial)
        optionArgs << optionArg('static', staticref)
        optionArgs << optionArg('try', tryblocks)
        optionArgs << optionArg('unchecked', unchecked)
        optionArgs << optionArg('varargs', varargs)

        // filter null values.
        final List<String> compilerArgs = optionArgs.findAll() 
        return compilerArgs
    }

    /**
     * Create -Xlint compile option if option is set. 
     * 
     * @param name Name of the -Xlint compile option.
     * @param enable Set option argument as -Xlint:option if true, otherwise as -Xlint:-option if false.
     * @return Null if enable is null, otherwise a valid -Xlint compiler option.
     */
    private String optionArg(final String name, final Boolean enable) {
        if (enable != null) {
            final String option = enable ? name : "-$name"
            return "-Xlint:$option"
        }
        return null
    }
}

Next we have a plugin class that registers the extension with the name lint on all JavaCompile tasks in our project:

// File: buildSrc/src/main/groovy/com/mrhaki/gradle/JavaCompilerLintPlugin.groovy
package com.mrhaki.gradle

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.compile.JavaCompile

/**
 * Plugin for applying a custom extension to 
 * JavaCompile tasks for configuring the 
 * -Xlint options.
 */
class JavaCompilerLintPlugin implements Plugin<Project> {
    
    void apply(final Project project) {
        
        // For all JavaCompile tasks we add 
        // a custom extension with the name lint
        // for configuring -Xlint options.
        project.tasks.withType(JavaCompile) { task ->
            
            // Let Gradle create a new extension.
            // Users can configure a compile task 
            // from the Java plugin like:
            // compileJava {
            //   lint {
            //     cast = true
            //   }
            // }
            JavaCompilerLintExtension taskExtension =
                    task.extensions.create('lint', JavaCompilerLintExtension)

            // Use options set via the lint extension
            // and assign them to the options.compilerArgs
            // property.
            // We do this in doFirst because the options are not
            // set yet at the Gradle configuration phase.
            task.doFirst {
                options.compilerArgs = taskExtension.asCompilerArgs()
            }
        }
    }
    
}

We have everything ready, so let's use the plugin in our Java project:

// File: build.gradle
apply plugin: 'java'

apply plugin: com.mrhaki.gradle.JavaCompilerLintPlugin

repositories {
    jcenter()
}

dependencies {
    testCompile 'junit:junit:4.11'
}

compileJava {
    // Here we use the custom
    // task extension. The closure
    // delegates to JavaCompilerLintExtension. 
    lint {
        enableAll()
        empty = false
        depAnn = false
    }
}

compileTestJava {
    // All JavaCompile task have the 
    // lint extension.
    lint {
        cast = true
    }
}

Written with Gradle 2.11.

Monday, February 29, 2016

Gradle Goodness: Lazy Task Properties

When we create our own custom tasks we might need to support lazy evaluation of task properties. A Gradle build has three phases: initialisation, configuration and execution. Task properties can be set during the configuration phase, for example when a task is configured in a build file. But our task can also evaluate the value for a task property at execution time. To support evaluation during execution time we must write a lazy getter method for the property. Also we must define the task property with def or type Object. Because of the Object type we can use different types to set a value. For example a Groovy Closure or Callable interface implementation can be used to execute later than during the configuration phase of our Gradle build. Inside the getter method we invoke the Closure or Callable to get the real value of the task property.

Let's see this with a example task. We create a simple class with two task properties: user and outputFile. The user property must return a String object and the outputFile property a File object. For the outputFile property we write a getOutputFile method. We delegate to the Project.file method, which already accepts different argument types for lazy evaluation. We also write an implementation for getUser method where we run a Closure or Callable object if that is used to set the property value.

// File: buildSrc/src/main/groovy/com/mrhaki/gradle/Hello.groovy
package com.mrhaki.gradle

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import java.util.concurrent.Callable

class Hello extends DefaultTask {

    // Setter method will accept Object type.
    def outputFile

    File getOutputFile() {
        // The Project.file method already
        // accepts several argument types:
        // - CharSequence
        // - File
        // - URI or URL
        // - Closure
        // - Callable
        project.file outputFile
    }

    // Setter method will accept Object type.
    def user

    String getUser() {
        // If the value is set with a Closure
        // or Callable then we calculate
        // the value. Closure implements Callable.
        if (user instanceof Callable) {
            user.call()
        // For other types we return the
        // result of the toString method.
        } else {
            user.toString()
        }
    }

    @TaskAction
    void sayHello() {
        getOutputFile().text = "Hello ${getUser()}"
    }
}

We already learned in a previous post that setting a property value can also be done using a setter method that is created by Gradle. In the following specification we use different methods and types to assign values to the user and outputFile properties:

package com.mrhaki.gradle

import org.gradle.api.Project
import org.gradle.testfixtures.ProjectBuilder
import spock.lang.Specification
import spock.lang.Subject

import java.util.concurrent.Callable

class HelloTaskSpec extends Specification {

    @Subject
    private Hello task

    private Project project = ProjectBuilder.builder().build()

    def setup() {
        task = project.task('helloSample', type: Hello)
    }

    def "set user property during configuration phase"() {
        when:
        project.ext.username = 'sample'

        and:
        // Property value known at configuration time.
        task.user project.property('username')

        then:
        task.user == 'sample'
    }

    def "user property not set when value not known during configuration phase"() {
        when:
        // Property value not known at configuration time.
        // Exception will be thrown because username property
        // is not set yet.
        task.user project.property('username')
        
        and:
        project.ext.username = 'sample'

        then:
        thrown(MissingPropertyException)
    }

    def "set user property with lazy evaluation GString during configuration phase"() {
        when:
        // Property value not known at configuration time.
        // Using GString lazy evaluation.
        task.user "${ -> project.property('username')}"

        and:
        project.ext.username = 'lazyGString'

        then:
        task.user == 'lazyGString'
    }

    def "set user property during execution phase using Closure"() {
        when:
        // Property value known at execution time, but not
        // during configuration phase.
        task.user { project.property('username') }

        and:
        // Set value for user property assignment.
        project.ext.username = 'closureValue'

        then:
        task.user == 'closureValue'
    }

    def "set user property during execution phase using Callable"() {
        when:
        // Property value known at execution time, but not
        // during configuration phase.
        task.user = new Callable<String>() {
            @Override
            String call() throws Exception {
                project.property('username')
            }
        }

        and:
        // Set value for user property assignment.
        project.ext.username = 'callableValue'

        then:
        task.user == 'callableValue'
    }
    
    def "delegate getOutputFile to project.file() and support all types for project.file()"() {
        given:
        task.user 'mrhaki'
        
        task.outputFile { project.property('helloOutput') }
        
        and:
        project.ext.helloOutput = 'hello.txt'

        when:
        task.sayHello()
        
        then:
        task.outputFile.text == 'Hello mrhaki'
    }
    
}

Written with Gradle 2.11.