Search

Dark theme | Light theme
Showing posts with label GradleGoodness:Groovy. Show all posts
Showing posts with label GradleGoodness:Groovy. Show all posts

February 10, 2016

Gradle Goodness: Running Groovy Scripts Like From Groovy Command Line

In a previous post we have seen how to execute a Groovy script in our source directories. But what if we want to use the Groovy command line to execute a Groovy script? Suppose we want to evaluate a small Groovy script expressed by a String value, that we normally would invoke like $ groovy -e "println 'Hello Groovy!'". Or we want to use the command line option -l to start Groovy in listening mode with a script to handle requests. We can achieve this by creating a task with type JavaExec or by using the Gradle javaexec method. We must set the Java main class to groovy.ui.Main which is the class that is used for running the Groovy command line.

In the following sample build file we create a new task runGroovyScript of type JavaExec. We also create a new dependency configuration groovyScript so we can use a separate class path for running our Groovy scripts.

// File: build.gradle

repositories {
    jcenter()
}

// Add new configuration for 
// dependencies needed to run
// Groovy command line scripts.
configurations {
    groovyScript
}

dependencies {
    // Set Groovy dependency so 
    // groovy.ui.GroovyMain can be found.
    groovyScript localGroovy()
    // Or be specific for a version:
    //groovyScript "org.codehaus.groovy:groovy-all:2.4.5"
}

// New task to run Groovy command line
// with arguments.
task runGroovyScript(type: JavaExec) {

    // Set class path used for running
    // Groovy command line.
    classpath = configurations.groovyScript

    // Main class that runs the Groovy
    // command line.
    main = 'groovy.ui.GroovyMain'

    // Pass command line arguments.
    args '-e', "println 'Hello Gradle!'"

}

We can run the task runGroovyScript and we see the output of our small Groovy script println 'Hello Gradle!':

$ gradle runGroovyScript
:runGroovyScript
Hello Gradle!

BUILD SUCCESSFUL

Total time: 1.265 secs
$

Let's write another task where we use the simple HTTP server from the Groovy examples to start a HTTP server with Gradle. This can be useful if we have a project with static HTML files and want to serve them via a web server:

// File: build.gradle

repositories {
    jcenter()
}

configurations {
    groovyScript
}

dependencies {
    groovyScript localGroovy()
}

task runHttpServer(type: JavaExec) {
    classpath = configurations.groovyScript
    main = 'groovy.ui.GroovyMain'

    // Start Groovy in listening mode on 
    // port 8001.
    args '-l', '8001'

    // Run simple HTTP server.
    args '-e', '''\
// init variable is true before
// the first client request, so
// the following code is executed once.
if (init) {
    headers = [:]
    binaryTypes = ["gif","jpg","png"]
    mimeTypes = [
        "css" : "text/css",
        "gif" : "image/gif",
        "htm" : "text/html",
        "html": "text/html",
        "jpg" : "image/jpeg",
        "png" : "image/png"
    ]
    baseDir = System.properties['baseDir'] ?: '.'
}

// parse the request
if (line.toLowerCase().startsWith("get")) {
    content = line.tokenize()[1]
} else {
    def h = line.tokenize(":")
    headers[h[0]] = h[1]
}

// all done, now process request
if (line.size() == 0) {
    processRequest()
    return "success"
}

def processRequest() {
    if (content.indexOf("..") < 0) { //simplistic security
        // simple file browser rooted from current dir
        def file = new File(new File(baseDir), content)
        if (file.isDirectory()) {
            printDirectoryListing(file)
        } else {
            extension = content.substring(content.lastIndexOf(".") + 1)
            printHeaders(mimeTypes.get(extension,"text/plain"))

            if (binaryTypes.contains(extension)) {
                socket.outputStream.write(file.readBytes())
            } else {
                println(file.text)
            }
        }
    }
}

def printDirectoryListing(dir) {
    printHeaders("text/html")
    println "<html><head></head><body>"
    for (file in dir.list().toList().sort()) {
        // special case for root document
        if ("/" == content) {
            content = ""
        }
        println "<li><a href='${content}/${file}'>${file}</a></li>"
    }
    println "</body></html>"
}

def printHeaders(mimeType) {
    println "HTTP/1.0 200 OK"
    println "Content-Type: ${mimeType}"
    println ""
}
    '''

    // Script is configurable via Java
    // system properties. Here we set
    // the property baseDir as the base
    // directory for serving static files.
    systemProperty 'baseDir', 'src/main/resources'
}

We can run the task runHttpServer from the command line and open the page http://localhost:8001/index.html in our web browser. If there is a file index.html in the directory src/main/resources it is shown in the browser.

$ gradle runGroovyScript
:runHttpServer
groovy is listening on port 8001
> Building 0% > :runHttpServer

Written with Gradle 2.11.

September 21, 2015

Gradle Goodness: Pass Java System Properties To Java Tasks

Gradle is of course a great build tool for Java related projects. If we have tasks in our projects that need to execute a Java application we can use the JavaExec task. When we need to pass Java system properties to the Java application we can set the systemProperties property of the JavaExec task. We can assign a value to the systemProperties property or use the method systemProperties that will add the properties to the existing properties already assigned. Now if we want to define the system properties from the command-line when we run Gradle we must pass along the properties to the task. Therefore we must reconfigure a JavaExec task and assign System.properties to the systemProperties property.

In the following build script we reconfigure all JavaExec tasks in the project. We use the systemProperties method and use the value System.properties. This means any system properties from the command-line are passed on to the JavaExec task.

apply plugin: 'groovy'
apply plugin: 'application'

mainClassName = 'com.mrhaki.sample.Application'

repositories.jcenter()

dependencies {
    compile 'org.codehaus.groovy:groovy-all:2.4.4'
}

// The run task added by the application plugin
// is also of type JavaExec.
tasks.withType(JavaExec) {
    // Assign all Java system properties from 
    // the command line to the JavaExec task.
    systemProperties System.properties
}

We write a simple Groovy application that uses a Java system property app.greeting to print a message to the console:

// File: src/main/groovy/com/mrhaki/sample/Application.groovy
package com.mrhaki.sample

println "Hello ${System.properties['app.greeting']}"

Now when we execute the run task (of type JavaExec) and define the Java system property app.greeting in our command it is used by the application:

$ gradle -Dapp.greeting=Gradle! -q run
Hello Gradle!

Written with Gradle 2.7.

September 16, 2015

Spring Sweets: Reload Classes Spring Boot With Spring Loaded And Gradle Continuous Build

When we develop a Spring Boot application we can hot reload newly compiled classes using Gradle. The bootRun task of the Spring Boot Gradle plugin has support for Spring Loaded. We must add a dependency to Spring Loaded as a dependency for the classpath configuration in the buildscript block. If we now use the bootRun task everything is ready to reload changed classes. Now we can use the continuous build feature of Gradle to listen for changes in our source files to recompile them. The recompiled classes are then reloaded in the running Spring Boot application started with bootRun. We start a second Gradle instance with the -t option for the classes task. This way when we change a source file it gets recompiled automatically and reloaded.

The following build script shows how we add Spring Loaded:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE"
        classpath 'org.springframework:springloaded:1.2.4.RELEASE'
    }
}

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

jar {
    baseName = 'sample'
    version =  '1.0'
}

repositories {
    jcenter()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile "org.springframework.boot:spring-boot-starter-web"
    compile 'org.codehaus.groovy:groovy-all:2.4.4'
}

Let's also create a very simple Spring Boot application:

package com.mrhaki.sample

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.ResponseBody

@EnableAutoConfiguration
@Controller
class SampleController {

    @RequestMapping(value = '/', method = RequestMethod.GET)
    @ResponseBody
    String sample() {
        'Sample controller'
    }

    static void main(String... args) {
        SpringApplication.run(SampleController, args)
    }

}

Now we can start a Gradle proces that will recompile class files if the source file changes:

$ gradle -t classes
Continuous build is an incubating feature.
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes

BUILD SUCCESSFUL

Total time: 2.847 secs

Waiting for changes to input files of tasks... (ctrl-d to exit)

In another terminal we start the bootRun task:

$ gradle bootRun
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:findMainClass
:bootRun
objc[16206]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/bin/java and /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.2.5.RELEASE)

...
> Building 83% > :bootRun

Written with Gradle 2.7 and Spring Boot 1.2.5.

August 24, 2015

Gradle Goodness: Using Continuous Build Feature

Gradle introduced the continuous build feature in version 2.5. The feature is still incubating, but we can already use it in our daily development. The continuous build feature means Gradle will not shut down after a task is finished, but keeps running and looks for changes to files to re-run tasks automatically. It applies perfectly for a scenario where we want to re-run the test task while we write our code. With the continuous build feature we start Gradle once with the test task and Gradle will automatically recompile source files and run tests if a source file changes.

To use the continuous build feature we must use the command line option --continuous or the shorter version -t. With this option Gradle will start up in continuous mode. To stop Gradle we must use the Ctrl+D key combination.

In the following output we see how to start Gradle in continuous mode and run the test tasks. The first time our test code fails, we change the source file and without restarting Gradle the file is compiled and the test task is run again. Notice that Gradle will honour the task dependencies to see if files have changed:

$ gradle -t test
Continuous build is an incubating feature.
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes
:compileTestJava UP-TO-DATE
:compileTestGroovy
:processTestResources UP-TO-DATE
:testClasses
:test

com.mrhaki.SampleSpec > get message FAILED
    org.spockframework.runtime.SpockComparisonFailure at SampleSpec.groovy:7

1 test completed, 1 failed
:test FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':test'.
> There were failing tests. See the report at: file:///Users/mrhaki/.../build/reports/tests/index.html

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 4.464 secs

Waiting for changes to input files of tasks... (ctrl-d to exit)
Change detected, executing build...

:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava UP-TO-DATE
:compileTestGroovy
:processTestResources UP-TO-DATE
:testClasses
:test

BUILD SUCCESSFUL

Total time: 1.792 secs

Waiting for changes to input files of tasks... (ctrl-d to exit)

Written with Gradle 2.6.

September 29, 2014

Gradle Goodness: Running Groovy Scripts as Application

In a previous post we learned how to run a Java application in a Gradle project. The Java source file with a main method is part of the project and we use the JavaExec task to run the Java code. We can use the same JavaExec task to run a Groovy script file.

A Groovy script file doesn't have an explicit main method, but it is added when we compile the script file. The name of the script file is also the name of the generated class, so we use that name for the main property of the JavaExec task. Let's first create simple Groovy script file to display the current date. We can pass an extra argument with the date format we wan't to use.

// File: src/main/groovy/com/mrhaki/CurrentDate.groovy
package com.mrhaki

// If an argument is passed we assume it is the
// date format we want to use.
// Default format is dd-MM-yyyy.
final String dateFormat = args ? args[0] : 'dd-MM-yyyy'

// Output formatted current date and time.
println "Current date and time: ${new Date().format(dateFormat)}"

Our Gradle build file contains the task runScript of type JavaExec. We rely on the Groovy libraries included with Gradle, because we use localGroovy() as a compile dependency. Of course we can change this to refer to another Groovy version if we want to using the group, name and version notation together with a valid repository.

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

dependencies {
    compile localGroovy()
}

task runScript(type: JavaExec) {
    description 'Run Groovy script'

    // Set main property to name of Groovy script class.
    main = 'com.mrhaki.CurrentDate'

    // Set classpath for running the Groovy script.
    classpath = sourceSets.main.runtimeClasspath

    if (project.hasProperty('custom')) {
        // Pass command-line argument to script.
        args project.getProperty('custom')
    }
}

defaultTasks 'runScript'

We can run the script with or without the project property custom and we see the changes in the output:

$ gradle -q
Current date and time: 29-09-2014
$ gradle -q -Pcustom=yyyyMMdd
Current date and time: 20140929
$ gradle -q -Pcustom=yyyy
Current date and time: 2014

Code written with Gradle 2.1.