Fixed Minute Timers

03 March 2017 ~ blog groovy

A co-worker of mine recently complained about how our metrics reporting component wasn’t smart enough to start the reporting timer on discrete minutes, but rather it just starts reporting at the start time, for example if you start the application at 10:42:34 and report every five minutes, you will get events recorded at the following times:

10:47:34
10:52:34
10:57:34

which can be annoying for a user when you want to determine metric changes over time, especially when using a dashboard tool. While this is a critical defect, it can be a data quality annoyance and it turns out, its not all that hard to fix.

What you want to do is determine the delay between now and the next desired minute-mark, the five-minute mark in our case, and you can do this with a little math:

def delay(final int mark, final LocalTime now = LocalTime.now()){
    int minute = now.minute + 1

    int minuteMark = minute % mark
    minuteMark = minuteMark == 0 ? minute : minute - minuteMark + mark

    int hour = now.hour
    if( minuteMark == 60 ){
        hour++
        minuteMark = 0
    }

    now.until(LocalTime.of(hour, minuteMark, 0, 0), ChronoUnit.MILLIS)
}

where mark is your minute-mark (5), and now is either a time you pass in (mostly for testing) or the current time by default. We need to roll the minute hand forward one to account for how far we are already into that minute and then we figure out what the next minute-mark is (accounting for hour-boundary rollover). Then you determine the difference between that next interval time and the current time, returning that value.

This does not account for the time spent in the method itself, but we are working on the scale of minutes and seconds here so our calculation time should not matter.

A full example of using this to schedule a timer on the five-minute marks follows:

import java.time.*
import java.time.temporal.*
import java.util.concurrent.*

def delay(final int mark, final LocalTime now = LocalTime.now()){
    int minute = now.minute + 1

    int minuteMark = minute % mark
    minuteMark = minuteMark == 0 ? minute : minute - minuteMark + mark

    int hour = now.hour
    if( minuteMark == 60 ){
        hour++
        minuteMark = 0
    }

    now.until(LocalTime.of(hour, minuteMark, 0, 0), ChronoUnit.MILLIS)
}

def now = LocalTime.now()
println "Now: $now"

int mark = 1
long delay = delay(mark,now)
println "Delay: $delay ms"
println "Start: ${now.plus(delay, ChronoUnit.MILLIS)}"

ScheduledExecutorService ses = Executors.newScheduledThreadPool(1)
ses.scheduleAtFixedRate({
    println LocalTime.now()
}, delay, mark*60000, TimeUnit.MILLISECONDS)

which will print out something like:

Now: 08:33:22.611
Delay: 97389 ms
Start: 08:35
08:35:00.088
08:40:00.088
08:45:00.088

These nice clean time bounaries lead to cleaner reporting visualizations. You can use any minute as the mark points, but generally you would use: 1, 5, 10, 15, 20, 30, or 60.

Ignoring SSL Issues

15 January 2017 ~ blog groovy

SSL is great, but it can be a real pain to deal with in testing or when you use self-signed certificates; browsers, generally handle it gracefully after manually accepting the certificate, but APIs can be tricky. In working on HttpBuilder-NG to add the “ignore SSL issues” feature back in from the original version, I got the grand tour of how to ignore certificate issues in some modern HTTP clients.

All you need are a couple custom components, which are thankfully shared across the client implementations I will discuss. You need an all-trusting javax.net.ssl.TrustManager:

X509TrustManager allTrusting = new X509TrustManager() {
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[]{};
    }

    public void checkClientTrusted(X509Certificate[] certs, String authType) {
    }

    public void checkServerTrusted(X509Certificate[] certs, String authType) {
    }
}

and an all-accepting javax.net.ssl.HostnameVerifier:

HostnameVerifier ANY_HOSTNAME = (s, sslSession) -> true;

With these, we can create an javax.net.ssl.SSLContext:

SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{allTrusting}, new SecureRandom());

Now you are ready to configure your clients. For the Java core HttpsURLConnection you can inject these using:

HttpsURLConnection https = // created elsewhere
https.setHostnameVerifier(ANY_HOSTNAME);
https.setSSLSocketFactory(sslContext.getSocketFactory());

If you are using the Apache HttpComponents library, it is also quite simple when using the HttpClientBuilder:

HttpClientBuilder builder = // created elsewhere
builder.setSSLContext(sslContext);
builder.setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext, ANY_HOSTNAME));

Lastly, if you are using the OkHttp client, you can:

OkHttpClient.Builder builder = // created elsewhere
builder.sslSocketFactory(sslContext.getSocketFactory(), allTrusting);
builder.hostnameVerifier(ANY_HOSTNAME);

Ok, now that the gritty details have been discussed, what about a simpler approach - how can this be done in HttpBuilder-NG? All you need to do is apply the ignoreSslIssues() helper method to your configuration as:

def http = JavaHttpBuilder.configure {
    ignoreSslIssues execution
    // other config...
}

Which will apply the configurations discussed above and you are ready to go. A means of doing this via system property is also provided (see the User Guide for more details).

Now you are off and running to ignore SSL certificate issues. As a quick disclaimer and reminder, SSL is an important security measure for web connections and should not be disabled/ignored ligthly and never in an internet-facing production environment - these procedures for ignoring errors are really meant for testing purposes.

Fuzzy Text Matching

12 January 2017 ~ blog groovy

From time to time I have needed to find matching text data based on some user input data, for example given a list of known company names, return a list of potential matches to a company name entered by the user - or for our example here: given a list of people’s first names, find the best matches to the user-provided name. Yes, there are tools, libraries and frameworks to do this in really efficient ways and in large volume, but if you are not already using them and if this is the only such problem you have to solve, it’s better to have a simple solution that works well-enough without adding bulk to your application.

As I mentioned above, let’s say we have a list of first names - I collected 100 from a random name generator site and put them in a text file (a sample is shown below):

names.txt
Sona
Terisa
Shasta
Jerold
Joetta
Harrison
Earle
Isaiah
Torrie
Valarie
Lynell
Mignon
Sharla
Kiesha
Art

When given a name, such as "Harry", how can we filter the list of names to provide the best matches? I have found the getJaroWinklerDistance in the Apache Commons Lang StringUtils class to be quite useful. It’s a string similarity algorithm that returns a double similarity result given two strings - the larger the number, the better the match.

With that you can load the names into a collection and process each of them against your given name to find the best N results (let’s say 10). The script is as follows:

find_name.groovy
@Grapes(
    @Grab('org.apache.commons:commons-lang3:3.5')
)

import static org.apache.commons.lang3.StringUtils.getJaroWinklerDistance

def query = args[0].toLowerCase()
def names = new File('./names.txt').readLines().unique()*.toLowerCase()

println "Searching for: ${query}\n"
println 'Name           Score'
println '--------------------'

names.collect { n->
    new Tuple(n, getJaroWinklerDistance(n, query))
}.sort { -it.get(1) }[0..10].each { r->
    println "${r.get(0).padRight(15)}${r.get(1)}"
}
println ''

If I run this against the set of 100 names I used, I get the following result:

> groovy find_name.groovy Harry
Searching for: harry

Name           Score
--------------------
harrison       0.86
gary           0.78
sharla         0.7
darrin         0.7
art            0.69
margart        0.68
maryellen      0.64
sari           0.63
hana           0.63
earle          0.6
shana          0.6

We see that there is actually a pretty good match, "Harrison", and even "Gary" for that matter. I have used this method to provide a list of suggestions back to the user so that they can make the final selection from them (being the list of items actually available in your system).

It’s an interesting technique and I am sure that there are better ways - feel free to suggest them.

Introducing Ersatz

10 December 2016 ~ blog groovy testing

While working on tests for the HttpBuilder-NG project, I tried out a couple different mock server libraries, my old go-to Mock Server and then the OkHttp Mock Server, but both had their own issues and just didn’t really fit the bill for what I wanted to be able to do with mock server testing. So, I decided to do some prototyping over a long weekend and I was able to come up with the Ersatz Server.

My goal was to use an standardized embedded HTTP server and then provide a rich DSL to configure expectations on it with all the bells and whistles of any other mocking library. I used the Undertow web server with both a Java 8 chained builder and a Groovy DSL approach to configuration to allow very simple and expressive expectation configuration.

With the Groovy DSL you can define expectations such as:

ErsatzServer ersatz = new ErsatzServer()

server.expectations {
    get('/say/hello'){
        verifier once()
        query 'name','Ersatz'
        responder {
            content 'Hello Ersatz','text/plain'
        }
    }
}

ersatz.start()

URL url = "${ersatz.serverUrl}/say/hello?name=Ersatz".toURL()
assert url.text == 'Hello Ersatz'

assert ersatz.verify()

ersatz.stop()

which will respond to a GET request to /say/hello?name=Ersatz with the text content Hello Ersatz and it will be expected that this request is called exactly once, or the verify() call will fail. This could also be written in standard Java:

server.expectations( expect -> {
    expect.get("/say/hello").verifier(once()).query("name","Ersatz").responds().content("Hello Ersatz","text/plain");
});

The builder form and the DSL form are equivalent and may be used together when developing in Groovy.

Expectations can be configured across the major HTTP request methods and can be matched by path as well as headers, cookies, body contents and other custom conditions. Multiple responses may be configured on a request so, for example, the first call would respond with some value, but all subsequent calls would respond with a 500 error status, such as:

server.expectations {
    post('/save'){
        body data, 'application/json'
        responder {
            content outdata, 'application/json'
        }
        responder {
            code 500
        }
    }
}

This allows for some interesting and flexible configuration options.

It’s a new library but I have replaced the mock server code in HttpBuilder-NG with it and it makes the tests a bit cleaner and adds some nice features that we can utilize going forward that were not present in the other mock server libraries. Give it a try.

Writing Gradle Plugins

07 December 2016 ~ blog groovy gradle

In my last post, Gradle: A Gentle Introduction, I discussed the basics of Gradle and how to get up and running quickly. Now, I am going to dive into the deeper part of the pool and talk about how to write your own Gradle plugins.

First, we need a project to work with. Let’s say that we want to add a custom banner to our build output - who doesn’t love banners? Something like:

  _______ _            ____        _ _     _
 |__   __| |          |  _ \      (_) |   | |
    | |  | |__   ___  | |_) |_   _ _| | __| |
    | |  | '_ \ / _ \ |  _ <| | | | | |/ _` |
    | |  | | | |  __/ | |_) | |_| | | | (_| |_ _ _
    |_|  |_| |_|\___| |____/ \__,_|_|_|\__,_(_|_|_)

We need to create a directory named banner-build and then create a build.gradle file in it with the following starting content:

build.gradle
plugins {
    id 'groovy'
}

We just need a basic starting point. Run ./gradle wrapper --gradle-version=3.2 to generate the wrapper and we are ready to start (we can run /gradlew from here on out).

Now, in order to write out a banner we need to create a custom task that will render it for us:

task banner {
    doFirst {
        if( !project.hasProperty('noBanner') ){
            file('banner.txt').eachLine { line->
                logger.lifecycle line
            }
        }
    }
}

gradle.startParameter.taskNames = [':banner'] + gradle.startParameter.taskNames

This task will add our action to the top of the execution list (the startPrameter modification makes it always run) so that if the noBanner property is not specified, our banner will be loaded from the specified file and displayed to the output log.

We will read our banner from a file, banner.txt in the root of the project - so we will need to create that with the banner content from above. Then, when you run ./gradlew build you will see something like the following:

> ./gradlew build
:banner
  _______ _            ____        _ _     _
 |__   __| |          |  _ \      (_) |   | |
    | |  | |__   ___  | |_) |_   _ _| | __| |
    | |  | '_ \ / _ \ |  _ <| | | | | |/ _` |
    | |  | | | |  __/ | |_) | |_| | | | (_| |_ _ _
    |_|  |_| |_|\___| |____/ \__,_|_|_|\__,_(_|_|_)
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar
:assemble
:compileTestJava UP-TO-DATE
:compileTestGroovy UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 0.559 secs

Notice also, that we can turn off the banner, passing the -PnoBanner option on the command line or as a property in your gradle.properties file, if you have one - if you run under one of those conditions, the banner will not be printed.

At this point, we have accomplished our original goal and we can go on with our lives…​ until the next project comes along and you need the same sort of functionality. You could just copy and paste this code into your project, but you don’t do that…​ right? That’s where plugins come into play; they allow us to share functionality across different project builds.

To create the plugin, first we need a separate Gradle project for it; create a directory (outside of the one for our demo project), called banner-plugin and add a build.gradle file to it with:

banner-plugin/build.gradle
plugins {
    id 'groovy'
    id 'java-gradle-plugin'
}

version = "0.1.0"
group = "com.stehno.gradle"

sourceCompatibility = 8
targetCompatibility = 8

repositories {
    jcenter()
}

dependencies {
    compile gradleApi()
    compile localGroovy()

    testCompile('org.spockframework:spock-core:1.0-groovy-2.4') {
        exclude module: 'groovy-all'
    }
}

and run gradle wrapper --gradle-version=3.2 in it to generate our wrapper. The build file for a plugin project is a standard Gradle build file, but with the java-gradle-plugin plugin to provide extra tools needed for plugins, as well as dependencies for the Gradle API and it’s associated Groovy distribution. With plugins, the project name is used as part of the unique plugin ID, so it’s generally a good practice to be explicit about the project name using a settings.gradle file:

banner-plugin/settings.gradle
rootProject.name = 'banner-plugin'

The last piece of plugin-specific configuration is the plugin properties file, which is a file in the resources/META-INF/gradle-plugins directory named <group>.<name>.properties, for this example:

banner-plugin/src/main/resources/META-INF/gradle-plugins/com.stehno.gradle.banner-plugin.properties
implementation-class=com.stehno.gradle.banner.BannerPlugin

Now we can create the basic skeleton for our plugin, which is an implementation of the Gradle Plugin<Project> interface:

banner-plugin/src/main/groovy/com/stehno/gradle/banner/BannerPlugin.groovy
package com.stehno.gradle.banner

import org.gradle.api.Plugin
import org.gradle.api.Project

class BannerPlugin implements Plugin<Project> {

    @Override void apply(final Project project) {
        // your config here...
    }
}

This is the main entry point for our plugin. When it is "applied" to the project, the apply(Project) method will be called. If we do a clean build of the project at this point, it will pass, but it does nothing. We need to transfer our functionality (the banner task) from our original build.gradle file to the plugin. Let’s create the plugin task skeleton:

banner-plugin/src/main/groovy/com/stehno/gradle/banner/BannerTask.groovy
package com.stehno.gradle.banner

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction

class BannerTask extends DefaultTask {

}

and give it something to do:

@TaskAction
void displayBanner(){
    logger.lifecycle 'Doing something!'
}

Once we have a task, we need to wire it into the plugin so that it is applied to the project. Change the apply(Project) method of our BannerPlugin class to the following:

@Override void apply(final Project project) {
    project.task 'banner', type:BannerTask

    project.gradle.startParameter.taskNames = [':banner'] + project.gradle.startParameter.taskNames
}

This will apply our new task and then cause it to be called whenever the build is run. Now, how do we check our progress? We could build the plugin and deploy it to our original project but that would be quite a lot of round-trip time every time we wanted to test a change, but there is no need for that, Gradle provides a rich test framework which works well with Spock. Let’s create a Spock test for our task:

banner-plugin/src/test/groovy/com/stehno/gradle/banner/BannerTaskSpec.groovy
package com.stehno.gradle.banner

import spock.lang.Specification
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.BuildTask
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.TaskOutcome

class BannerTaskSpec extends Specification {

    @Rule TemporaryFolder projectRoot = new TemporaryFolder()

    def 'simple run'(){
        given:
        File buildFile = projectRoot.newFile('build.gradle')
        buildFile.text = '''
            plugins {
                id 'groovy'
                id 'com.stehno.gradle.banner-plugin'
            }
        '''.stripIndent()

        projectRoot.newFile('banner.txt').text = 'Awesome Banner!'

        when:
        BuildResult result = GradleRunner.create()
            .withPluginClasspath()
            .withProjectDir(projectRoot.root)
            .withArguments('clean build'.split(' '))
            .build()

        then:
        println result.output
    }
}

It’s a bit of code, but it’s not too bad once you dig in. We have a standard Spock test, with a TemporaryFolder rule - this will be our test project directory. Then, we create a build.gradle file for our test with our plugin and the groovy plugin, similar to what our original Gradle file looked like. Next, we use the GradleRunner to create and configure a Gradle environment using our file, which is then executed as a build. The results are then printed out to the command line. If you run ./gradlew test on the project now and view the test output (in the report standard out), you will see:

:banner
Doing something!
:clean UP-TO-DATE
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar
:assemble
:compileTestJava UP-TO-DATE
:compileTestGroovy UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 2.019 secs

where we can see our output and we have a way to quickly test our new task. So, moving onward, we need to add the real functionality to our task. Update the displayBanner() method to:

@TaskAction
void displayBanner(){
    if( !project.hasProperty('noBanner') ){
        project.file('banner.txt').eachLine { line->
            logger.lifecycle line
        }
    }
}

Notice that we prefixed project. before the file() call since we are no longer directly in the "project" scope, but other than that this code was copied right from our original build file. If you run the test, you see our message in the test output:

:banner
Awesome banner!
:clean UP-TO-DATE
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar
:assemble
:compileTestJava UP-TO-DATE
:compileTestGroovy UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 2.019 secs

Our test is good, but it doesn’t really verify anything, it just prints out the build output. Let’s make it verify that the build passed and that our expected message is in the output - the then: block becomes:

then:
result.tasks.every { BuildTask task ->
    task.outcome == TaskOutcome.SUCCESS || task.outcome == TaskOutcome.UP_TO_DATE
}

result.output.contains('Awesome Banner!')

The test will no longer generate the build output to the command line, but we are actually verifying the expected behavior.

We can test the noBanner property support as well, but we should also refactor the test a bit so that shared code is reused - now our test looks like:

banner-plugin/src/test/groovy/com/stehno/gradle/banner/BannerTaskSpec.groovy
package com.stehno.gradle.banner

import spock.lang.Specification
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.BuildTask
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.TaskOutcome

class BannerTaskSpec extends Specification {

    @Rule TemporaryFolder projectRoot = new TemporaryFolder()

    private File buildFile

    def setup(){
        buildFile = projectRoot.newFile('build.gradle')
        buildFile.text = '''
            plugins {
                id 'groovy'
                id 'com.stehno.gradle.banner-plugin'
            }
        '''.stripIndent()

        projectRoot.newFile('banner.txt').text = 'Awesome Banner!'
    }

    def 'simple run'(){
        when:
        BuildResult result = GradleRunner.create()
            .withPluginClasspath()
            .withProjectDir(projectRoot.root)
            .withArguments('clean build'.split(' '))
            .build()

        then:
        println result.output
        buildPassed result

        result.output.contains('Awesome Banner!')
    }

    def 'simple run with status hidden'(){
        when:
        BuildResult result = GradleRunner.create()
            .withPluginClasspath()
            .withProjectDir(projectRoot.root)
            .withArguments('clean build -PnoBanner'.split(' '))
            .build()

        then:
        buildPassed result

        !result.output.contains('Awesome Banner!')
    }

    private boolean buildPassed(final BuildResult result){
        result.tasks.every { BuildTask task ->
            task.outcome == TaskOutcome.SUCCESS || task.outcome == TaskOutcome.UP_TO_DATE
        }
    }
}

Mostly I just extracted the setup code and the buildPassed check, then added a test for the noBanner property support.

Wouldn’t it be nice to make the banner file location configurable? Gradle plugins have a "extension" construct that allows for rich configuration of plugins by adding functionality to the Gradle DSL. For our plugin, we would like to support something like the following:

banner {
    enabled = true
    location = file('banner.txt')
}

which would be used to toggle the banner display on and off and also provide a means of configuring the banner file location. This structure and both of its properties are optional, but allow additional configuration. Adding them to the plugin is fairly simple. The extension itself is just a POGO class, which for our case would be:

banner-plugin/src/main/groovy/com/stehno/gradle/banner/BannerExtension.groovy
package com.stehno.gradle.banner

class BannerExtension {

    boolean enabled = true
    File location
}

To register the extension with the plugin, you add the following to the first line of the BannerPlugin apply(Project) method:

project.extensions.create('banner', BannerExtension)

The last part of adding the extension support is to have the task actually make use of it. The displayBanner method of the task will look like the following when we are done:

@TaskAction
void displayBanner(){
    BannerExtension extension = project.extensions.getByType(BannerExtension)

    boolean enabled = project.hasProperty('bannerEnabled') ? project.property('bannerEnabled').equalsIgnoreCase('true') : extension.enabled

    File bannerFile = project.hasProperty('bannerFile') ? new File(project.property('bannerFile')) : (extension.location ?: project.file('banner.txt'))


    if( enabled ){
        bannerFile.eachLine { line->
            logger.lifecycle line
        }
    }
}

I modified the noBanner property and converted it to a flag so that now you would pass in -PbannerEnabled=false to disable it. I also added a means of configuring the banner file from the command line or via the extension, with the default still being banner.txt. The CLI and settings properties will override the extension values if they are present. We need to modify the 'simple run with status hidden' test to handle the new parameter:

def 'simple run with status hidden'(){
    when:
    BuildResult result = GradleRunner.create()
        .withPluginClasspath()
        .withProjectDir(projectRoot.root)
        .withArguments('clean build -PbannerEnabled=false'.split(' '))
        .build()

    then:
    buildPassed result

    !result.output.contains('Awesome Banner!')
}

Now, if you run the tests, everything still passes - so the defaults work as expected. Let’s add some tests using the extension to override the file location.

def 'extension run'(){
    setup:
    buildFile.text = '''
        plugins {
            id 'groovy'
            id 'com.stehno.gradle.banner-plugin'
        }

        banner {
            location = file('other-banner.txt')
        }
    '''.stripIndent()

    when:
    BuildResult result = GradleRunner.create()
        .withPluginClasspath()
        .withProjectDir(projectRoot.root)
        .withArguments('clean build'.split(' '))
        .build()

    then:
    buildPassed result

    result.output.contains('Awesome-er Banner!')
}

In this test we have to override the default build file we created in setup. I also added the creation of the other banner file in the setup method:

projectRoot.newFile('other-banner.txt').text = 'Awesome-er Banner!'

Now, run the tests again and see that our extension works as expected.

With our newly minted Gradle plugin we should be able to use it in our original project as a local test before deployment. An easy way to do this is to publish it to your local maven repository and then configure the other project to use it. In the plugin project, add id 'maven-publish' to the plugins block, which will allow us to publish to the local maven repo. Then run ./gradlew publishToMavenLocal, which does what it says.

In the original external build.gradle file we need to add bootstrapping code to bring in the local plugin and also remove the old banner task. The updated build.gradle file will look like this:

build-banner/build.gradle
buildscript {
    repositories {
        mavenLocal()
    }
    dependencies {
        classpath "com.stehno.gradle:banner-plugin:0.1.0"
    }
}

plugins {
    id 'groovy'
}

apply plugin: "com.stehno.gradle.banner-plugin"

Notice that we are pulling the plugin from the local maven repository. If you run the build now, you get your expected banner:

> ./gradlew build
:banner
  _______ _            ____        _ _     _
 |__   __| |          |  _ \      (_) |   | |
    | |  | |__   ___  | |_) |_   _ _| | __| |
    | |  | '_ \ / _ \ |  _ <| | | | | |/ _` |
    | |  | | | |  __/ | |_) | |_| | | | (_| |_ _ _
    |_|  |_| |_|\___| |____/ \__,_|_|_|\__,_(_|_|_)
:build

BUILD SUCCESSFUL

Total time: 0.543 secs

However, we should be able to use a different banner file. Create another banner file as flag.txt (with whatever you want in it) and configure the build to use it by adding:

banner {
    location = file('flag.txt')
}

to the bottom of the build file. Now, with my new version, I get:

> ./gradlew build
:banner
This is GRADLE!!!
:build

BUILD SUCCESSFUL

Total time: 0.474 secs

We can also disable the banner via config, set enabled = false in the extension code, and it will not appear. But, you can force it on the command line by adding -PbannerEnabled=true.

From here, you can distribute your plugin to friends and coworkers as long as you have some shared repository that you can point them to, but what if you came up with something cool enough to share to a larger audience? For that you want to publish to the http://plugins.gradle.com repo, which is what is used by the plugins block of the build.gradle file. I won’t go too far down that path in this post, but basically you will need to add the id 'com.gradle.plugin-publish' version '0.9.4' plugin to the plugin project, which will handle the actual publishing for you once you configure it for your project. In our case this would be something like:

pluginBundle {
    website = 'http://yourdomain.com/banner-plugin'
    vcsUrl = 'https://github.com/cjstehno/banner-plugin'
    description = 'Gradle plugin to add a fancy banner to your build log.'
    tags = ['gradle', 'groovy']

    plugins {
        webpreviewPlugin {
            id = 'com.stehno.gradle.banner-plugin'
            displayName = 'Gradle Build Banner Plugin'
        }
    }
}

Once you have that in place and have signed up with the plugins portal (free) you run ./gradlew publishPlugins and if all goes well, you have a publicly available plugin.

This tutorial has really only scratched the surface of plugin development, there is a lot more there to work with and most of it is well documented in the Gradle User Guide or through some Google searches. It’s a powerful framework and well worth spending the time to learn if you are working in Gradle.

Gradle: A Gentle Introduction

02 November 2016 ~ blog groovy gradle

The Gradle build tool has become widely-used over the past few years, but there are still a lot of developers who are unfamiliar with it, and like any new framework or technology it is easier to get started with some guidance. Hopefully this will provide a nice jump start into doing some actual work with Gradle. With that being said, let’s dig in!

I will forgo installing Gradle - you can read about how to do that for your platform in the Gradle documentation. Let’s assume you have Gradle installed, preferably a current version. If you run gradle --version you should see something like:

------------------------------------------------------------
Gradle 3.1
------------------------------------------------------------

Build time:   2016-09-19 10:53:53 UTC
Revision:     13f38ba699afd86d7cdc4ed8fd7dd3960c0b1f97

Groovy:       2.4.7
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_102 (Oracle Corporation 25.102-b14)
OS:           Linux 4.8.0-26-generic amd64

First, create a directory for your project and cd into it:

mkdir hellogradle
cd hellogradle

Every Gradle project needs at least a build.gradle file so we will start with the minimal requirement. Create the following file in your project directory:

build.gradle
plugins {
    id 'groovy'
}

repositories {
    jcenter()
}

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

The plugins block is used to specify the Gradle plugins used in the build; in this case we just need groovy since we are making a Groovy project. The groovy plugin extends the java plugin so we get its functionality as well.

The repositories block specifies which repositories are available for resolving dependency artifacts - in most cases jcenter() (the Bintray repository) is enough to start with.

Lastly, the dependencies block is where the project dependencies are defined as <configuration> '<group>:<artifact>:<version>'.

At this point you have a working Gradle project. You can build it:

gradle clean build

You should see something like the following:

> hellogradle gradle clean build
:clean
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar
:assemble
:compileTestJava UP-TO-DATE
:compileTestGroovy UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 0.492 secs

You can see that it is already doing quite a bit for so few lines of build code. You can run gradle tasks to see a list of the tasks available to your project.

So far, we have been running against my local version of Gradle. One of the nice features of Gradle is the wrapper functionality. The wrapper allows the project to specify the version of Gradle it should be built under; this code is then checked into your source control system so that a new developer can checkout the project and build it with the correct version of Gradle without it being installed on their system.

Add the following to the bottom of the build.gradle file:

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

Then, whenever you add the wrapper or change the supported version, you need to execute the gradle wrapper task to regenerate the configuration. Once the wrapper is in place, you will want to execute all your Gradle tasks using it rather than your local installation. You do this using the gradlew or gradlew.bat scripts provided in the root of your project. Now let’s do a clean build again with the wrapper:

> hellogradle ./gradlew clean build
:clean
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar
:assemble
:compileTestJava UP-TO-DATE
:compileTestGroovy UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 0.678 secs

We end up with the same result as before.

This project doesn’t do anything at this point - there is no code. Let’s add some Groovy code; create the directories for src/main/groovy/demo and then add the file:

HelloGradle.groovy
package demo

class HelloGradle {

    String greet(final String name){
        "Hello, ${name ?: 'Gradle'}!"
    }
}

This code simply says hello to the name passed in as an argument, or Gradle by default. Now we will need to unit test our work, so let’s add support for the Spock testing framework. Add the following to your dependencies closure:

testCompile 'org.spockframework:spock-core:1.0-groovy-2.4'

We now have Spock available, so let’s write a unit test for our code. Create the test directories: src/test/groovy/demo and then create the file:

HelloGradleSpec.groovy
package demo

import spock.lang.Specification
import spock.lang.Unroll

class HelloGradleSpec extends Specification {

    private final HelloGradle greeter = new HelloGradle()

    @Unroll def 'say hello #name'(){
        expect:
        greeter.greet(name) == result

        where:
        name    | result
        null    | 'Hello, Gradle!'
        ''      | 'Hello, Gradle!'
        'Chris' | 'Hello, Chris!'
    }
}

This test will verify that our greeter returns the expected values for null-ish inputs as well as when a name is provided. I won’t go into the details of the Spock test at this point. Now, when you build the project, you will also run the tests by default:

> hellogradle ./gradlew clean build
:clean
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:compileTestGroovy
:processTestResources UP-TO-DATE
:testClasses
:test
:check
:build

BUILD SUCCESSFUL

Total time: 1.789 secs

Notice :test near the bottom. Gradle also provides an HTML report of your test results. The report will be generated in the build/reports directory and will look something like the following image:

gradle test report

Now that we have a test, it might be nice to have some idea of our test coverage. Gradle provides a plugin for the jacoco code coverage library. You can add the plugin by adding id 'jacoco' to the plugins block of your build.gradle file, which allows you to run:

./gradlew clean build jacocoTestReport

to build the project with tests and a generated test coverage report. Again, the report is generated in the build/reports directory - it will look something like:

gradle coverage report

The coverage report allows you to drill down into the source code and see what is and is not covered by your tests.

Testing your code is nice, but you need a way to run your application outside of testing. Let’s first add a main method to our Groovy code:

static void main(args){
    println new HelloGradle().greet(args ? args[0] : null)
}

Nothing fancy, just instantiate the HelloGradle class and call the greet(String) method with the first argument, if there is one. To make the project runnable, we need to add the application plugin and specify a "main class". To do this:

  • Add id 'application' to the plugins block

  • Add group = 'demo' to give the project an artifact group

  • Add version = '0.0.1' to give your project a version

  • Add mainClassName = 'demo.HelloGradle' to the build.gradle file outside of other configuration blocks.

With that, you now have a new task run which will run the application for you:

> hellogradle ./gradlew run
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes
:run
Hello, Gradle!

BUILD SUCCESSFUL

Total time: 1.526 secs

It also generates .tar and .zip distributions of the project which contain starter scripts and all required dependencies to deploy and run your application outside of the project itself.

Code quality analysis tools are also available as Gradle plugins. A common one for Groovy development is CodeNarc which runs quality rules against your code to generate a report of possible issues. We can add this to the project by adding id 'codenarc' to the plugins block and adding some additional config to build.gradle:

codenarcMain {
    ignoreFailures false
    configFile file('config/codenarc-main.rules')

    maxPriority1Violations 0
    maxPriority2Violations 5
    maxPriority3Violations 10
}

codenarcTest {
    ignoreFailures true
    configFile file('config/codenarc-test.rules')
}

Which configures a different rules and criteria for main source code vs test source code. The main and test rule sets are based on their suggested configurations, personal preference and experience - I generally use the files from my Vanilla project (main, test) for simplicity. This configuration will fail the build when the violation thresholds are exceeded for the main classes, but will simply report on the violations for test classes. The build will now run the codenarc checks when a build is executed.

The build will let you know if violations were found, and in any case will generate a report in the build/reports/codenarc directory. The report will look something like the following:

gradle codenarc report

At this point, we have a Gradle-based Groovy project with portable support for building, testing, coverage, code quality and application run/deployment, all with a few dozen lines of understandable code. While there is a lot more you can and should do with Gradle, this is a good starting point. From here, you should read through their documentation in general or touch on topics as you need them to figure out how to do something. Also Google is your best reference for finding how-tos or 3rd-party plugins; however, there is an official plugin repository that is starting to catch on.

Once you get the hang of it Gradle is hard to let go of due to its compact code, expressiveness and flexibility without the pains and rigor of older tools, like Maven and Ant.

Gradle Natives Plugin Update

19 September 2016 ~ blog java groovy gradle

A few years ago I wrote a post about my Gradle-Natives plugin, called "Going Native with Gradle". The plugin was the result of some failed attempts at game programming and it pretty much stopped there; however, it seems there are some users who found it useful. In the years since it was written, it sat and got buggy and then recently just became useless due to external library changes and the rigidity of the plugin functionality. Tryign to be a good open source citizen, I figured it would be a good time to do some updates that will hopefully keep the plugin viable for a while.

With the new release, I figured it would be good to go back to the original post and attempt a similar example. Using the example code from the LWJGL Getting Started Guide we have:

import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;

import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.*;

public class HelloWorld {

	// The window handle
	private long window;

	public void run() {
		System.out.println("Hello LWJGL " + Version.getVersion() + "!");

		try {
			init();
			loop();

			// Free the window callbacks and destroy the window
			glfwFreeCallbacks(window);
			glfwDestroyWindow(window);
		} finally {
			// Terminate GLFW and free the error callback
			glfwTerminate();
			glfwSetErrorCallback(null).free();
		}
	}

	private void init() {
		// Setup an error callback. The default implementation
		// will print the error message in System.err.
		GLFWErrorCallback.createPrint(System.err).set();

		// Initialize GLFW. Most GLFW functions will not work before doing this.
		if ( !glfwInit() )
			throw new IllegalStateException("Unable to initialize GLFW");

		// Configure our window
		glfwDefaultWindowHints(); // optional, the current window hints are already the default
		glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
		glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable

		int WIDTH = 300;
		int HEIGHT = 300;

		// Create the window
		window = glfwCreateWindow(WIDTH, HEIGHT, "Hello World!", NULL, NULL);
		if ( window == NULL )
			throw new RuntimeException("Failed to create the GLFW window");

		// Setup a key callback. It will be called every time a key is pressed, repeated or released.
		glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
			if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
				glfwSetWindowShouldClose(window, true); // We will detect this in our rendering loop
		});

		// Get the resolution of the primary monitor
		GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
		// Center our window
		glfwSetWindowPos(
			window,
			(vidmode.width() - WIDTH) / 2,
			(vidmode.height() - HEIGHT) / 2
		);

		// Make the OpenGL context current
		glfwMakeContextCurrent(window);
		// Enable v-sync
		glfwSwapInterval(1);

		// Make the window visible
		glfwShowWindow(window);
	}

	private void loop() {
		// This line is critical for LWJGL's interoperation with GLFW's
		// OpenGL context, or any context that is managed externally.
		// LWJGL detects the context that is current in the current thread,
		// creates the GLCapabilities instance and makes the OpenGL
		// bindings available for use.
		GL.createCapabilities();

		// Set the clear color
		glClearColor(1.0f, 0.0f, 0.0f, 0.0f);

		// Run the rendering loop until the user has attempted to close
		// the window or has pressed the ESCAPE key.
		while ( !glfwWindowShouldClose(window) ) {
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer

			glfwSwapBuffers(window); // swap the color buffers

			// Poll for window events. The key callback above will only be
			// invoked during this call.
			glfwPollEvents();
		}
	}

	public static void main(String[] args) {
		new HelloWorld().run();
	}

}

If we put this in a simple Gradle project with build.gradle as:

plugins {
    id 'com.stehno.natives' version '0.2.4'
    id 'java'
    id 'application'
}

version = "0.0.1"
group = "com.stehno"
mainClassName = 'hello.HelloWorld'

sourceCompatibility = 8
targetCompatibility = 8

repositories {
    jcenter()
}

dependencies {
    compile 'org.lwjgl:lwjgl:3.0.0'
    compile 'org.lwjgl:lwjgl-platform:3.0.0:natives-windows'
    compile 'org.lwjgl:lwjgl-platform:3.0.0:natives-linux'
    compile 'org.lwjgl:lwjgl-platform:3.0.0:natives-osx'
}

task wrapper(type: Wrapper) {
    gradleVersion = "2.14"
}

We can view the native libraries for all platforms using ./gradlew listNatives:

:listNatives
Native libraries found for configurations (compile, runtime)...
 - lwjgl-platform-3.0.0-natives-linux.jar:
        [LINUX] libjemalloc.so
        [LINUX] liblwjgl.so
        [LINUX] libglfw.so
        [LINUX] libopenal.so
 - lwjgl-platform-3.0.0-natives-osx.jar:
        [MAC] liblwjgl.dylib
        [MAC] libjemalloc.dylib
        [MAC] libglfw.dylib
        [MAC] libopenal.dylib
 - lwjgl-platform-3.0.0-natives-windows.jar:
        [WINDOWS] lwjgl.dll
        [WINDOWS] lwjgl32.dll
        [WINDOWS] OpenAL.dll
        [WINDOWS] jemalloc.dll
        [WINDOWS] glfw.dll
        [WINDOWS] glfw32.dll
        [WINDOWS] jemalloc32.dll
        [WINDOWS] OpenAL32.dll

and we can build and run the HelloWorld application with ./gradlew clean build run, which begs the question of whether or not this plugin is needed, since at this point the application works and we have not used the plugin at all. I will leave that to developers who actually work with this stuff and may use the plugin - I am just updating the existing functionality.

You can inlude the native libraries in the build using ./gradlew clean build includeNatives which will unpack the native libraries into the project build directory.

There are still a number of configuration options available through the natives DSL extension, such as including and excluding libraries, as well as limiting the scan to certain configurations and platforms, but I will leave those for the official documentation. Without any additional configuration you get all of the native libraries from the compile and runtime configurations for all platforms unpacked into the build/natives directory.

This plugin is still pretty raw, but hopefully it is useful enough to make some developers lives easier.

HTTP Builder NG for Groovy and Java

18 September 2016 ~ blog groovy

The HttpBuilder project has been a go-to library for the simplification of HTTP requests for years; however, development on the project has stalled and seemingly died. A friend of mine (Dave Clark) decided to pick up where the project left off and to bring it up-to-date with modern Groovy and Java 8 support. The HTTP Builder NG project is a major update and refactor of the original project. I joined on to help with development, documentation and testing. In my opinion, this effort has brought the library back from the dead, better than ever. In this post, I will walk through accessing a simple REST service using the HttpBuilder with both Groovy and Java examples - yes, the new version of the library supports standard Java 8 coding.

First, we need a REST service to work with. I have thrown together a simple set of endpoints using the Spark Web Framework to make a "message of the day" service. There are three endpoints:

  • GET /message - retrieves the current stored message

  • POST /message - saves the text field of the JSON body content as the new message

  • DELETE /message - deletes the current message

There is not much to it, but it should be enough to play with. You can find the code in the [repo for this post](https://github.com/cjstehno/httpb-demo). Startup the server by running:

./gradlew run

In the root of the project. The server will be running on http://localhost:4567.

Let’s start off by retrieving the current message from the server. We need a base configured HttpBuilder object to make requests from:

HttpBuilder http = HttpBuilder.configure {
    request.uri = 'http://localhost:4567'
}

Then, we need to make a GET request to the /message path:

def result = http.get {
    request.uri.path = '/message'
}

When you run this code, you will get the following:

[text:n/a, timestamp:2016-09-16T12:47:55+0000]

which is a Map of the parsed JSON data coming back from the server - the HttpBuilder recognizes the application/json response content and parses it for you. In this case all we really want is the text, so let’s transform the response data a bit:

String text = http.get(String){
    request.uri.path = '/message'
    response.success { FromServer from, Object body->
        body.text
    }
}

We have added an expected result type of String and a response.success() handler. This handler will be called when a successful response code is received (code < 400). When it is called it will pull the text field out of our body object, which in this case, is the already-parsed JSON data. The return value from the success() method is returned as the result - the text of the current message. When you run this version of the code you get the current message text:

n/a

This is the default "empty" message content. How do we update the message to something more interesting? The service exposes POST /message which will take the text field of the request body content and use it as the new message. We can write a POST request just as easily as our GET request:

String updated = http.post(String) {
    request.uri.path = '/message'
    request.contentType = 'application/json'
    request.body = { text 'HttpBuilder is alive!' }
    response.success { FromServer from, Object body ->
        body.text
    }
}

Again, we will expect the text of the new message back from the server, but this time we are calling the post() method with a JSON content type. Note that our body content is using the Groovy JsonBuilder closure format, it could have just as easily been a Map of the data to be encoded. Similar to the response decoding, the request body is automatically encoded based on the content type.

If you run the code now, you will get:

HttpBuilder is alive!

You could also call the get() method again and verify that it is the current message.

As a final example with our service, let’s call the DELETE /message endpoint to reset the message back to it’s "empty" state. A DELETE request is just as simple:

String deleted = http.delete(String){
    request.uri.path = '/message'
    response.success { FromServer from, Object body ->
        body.text
    }
}

The result will be the new message after deletion:

n/a

which is the "empty" state.

One thing we notice now that we have written all of the verb calls is that there are a lot of similarities between them. They all call the same path and they all handle the successful response content in the same manner. I am not a fan of duplication, so we can move the common configuration up into the main configure method:

HttpBuilder http = HttpBuilder.configure {
    request.uri = 'http://localhost:4567/message'
    response.success { FromServer from, Object body ->
        body.text
    }
}

and our verb methods, now contain only what they need to do their work:

String message = http.get(String) {}

String updated = http.post(String) {
    request.contentType = 'application/json'
    request.body = { text 'HttpBuilder is alive!' }
}

String deleted = http.delete(String) {}

Nice and clean. Now wait, I know, I promised something similar in plain old Java, well Java 8 anyway…​ ok, you can do the same operations in Java with a fairly similar expressiveness:

HttpBuilder http = HttpBuilder.configure(config -> {
    config.getRequest().setUri("http://localhost:4567/message");
    config.getResponse().success(new BiFunction<FromServer, Object, String>() {
        @Override public String apply(FromServer fromServer, Object body) {
            return ((Map<String, Object>) body).get("text").toString();
        }
    });
});

String message = http.get(String.class, config -> {});

System.out.println("Starting content: " + message);

// update the content

String updated = http.post(String.class, config -> {
    config.getRequest().setContentType("application/json");
    config.getRequest().setBody(singletonMap("text", "HttpBuilder works from Java too!"));
});

System.out.println("Updated content: " + updated);

// delete the content

String deleted = http.delete(String.class, config -> {});

System.out.println("Post-delete content: " + deleted);

Notice that the Java 8 lambdas make the syntax about as simple as the Groovy DSL. When you run this version of the client you get:

Starting content: n/a
Updated content: HttpBuilder works from Java too!
Post-delete content: n/a

In Java or Groovy, the library makes HTTP interactions much easier to work with. Check out the project and feel free to submit bug reports and feature requests, or even suggested details to be documented.

ND4J Matrix Math

12 August 2016 ~ blog groovy

In my last post (Commons Math - RealMatrix), I discussed the matrix operations support provided by the Apache Commons Math API. In doing my research I also stumbled on a library that is much closer in functionality to the Python NumPy library (commonly used in Machine Learning examples). The ND4J library is a scientific computing library for the JVM, meant to be used in production environments, which means routines are designed to run fast with minimum RAM requirements.

The main draw I had at this point was that their support for array-style element-by-element operations was much deeper than the matrix operations provided by the Apache Commons Math API and much closer to what I was seeing in the Python code I was working with, which makes conversion simpler.

With NumPy in Python you can multiply two arrays such that the result is the multiplication of each value of the array by the corresponding value in the second array. This is not so simple with matrices (as shown in my last post). With ND4J, it becomes much simpler:

def arrA = Nd4j.create([1.0, 2.0, 3.0] as double[])
def arrB = Nd4j.create([2.0, 4.0, 6.0] as double[])
def arrC = arrA.mul(arrB)
println "$arrA + $arrB = $arrC"

will result in:

[1.00, 2.00, 3.00] * [2.00, 4.00, 6.00] = [ 2.00,  8.00, 18.00]

which is as we would expect from the Python case. ND4J also has the ability to do two-dimensional (matrix-style) arrays:

def matA = Nd4j.create([
    [1.0, 2.0, 3.0] as double[],
    [4.0, 5.0, 6.0] as double[]
] as double[][])
println "Matrix: $matA\n"

which will produce:

Matrix: [[1.00, 2.00, 3.00],
 [4.00, 5.00, 6.00]]

All of the other mathematical operations I mentioned in the previous post are available and with data structures that feel a lot more rich and refined for general use. This is barely scratching the surface of the available functionality. Also, the underlying code is native-based and has support for running on CUDA cores for higher performance. This library is definitely one to keep in mind for cases when you have a lot of array and matrix-based operations.

Apache Commons Math - RealMatrix

11 August 2016 ~ blog groovy

I have been reading Machine Learning in Action, which is a great book; however, all of the examples are in Python. While Python seems like a decent language, it is not one of my primary languages. With that in mind, I have been converting the Python examples into Groovy so that a few months from now when I come back and try to understand what I learned, I will be able to decipher the code.

What I have found is that, at least in the examples for this book, there are numerous Matrix-based operations. My Linear Algebra was a long time ago, but I think I remember some of the basics; however, it’s nice to have a Java-based implementation in the Apache Commons Math RealMatrix implementations (there are others but this is what I have been focussing on). It took me a little time to get back up to speed, especially since the Python examples will have something like:

someMatrix = someMatrix * anotherMatrix + thirdMatrix * number

where the resulting matrix is the product of two matrices added to the product of a matrix and a scalar number. Conceptually, this boils down to:

  1. Multiply someMatrix by anotherMatrix

  2. Multiply every element of thirdMatrix by the scalar number value

  3. Add every element of the matrix in step 1 with the element at the same position of the matrix from step 2.

Not hard to grasp, and not even all that hard to code; however, this is something I’d rather push off to someone else’s implementation instead of writing it myself. That is where the Commons Math library comes into play. The RealMatrix interface defines matrix support for double values - there is also a more flexible FieldMatrix<T> interface, but double values work well as an example. Let’s start by setting up a simple Groovy script for playing with matrices. Create a file named matrix-math.groovy and add the following to it:

matrix-math.groovy
@Grapes(
   @Grab('org.apache.commons:commons-math3:3.6.1')
)

import org.apache.commons.math3.linear.*

def mat = new Array2DRowRealMatrix(4,3)

println mat

This script will download the artifacts for the Apache Commons Math library and create a simple RealMatrix with 4 rows and 3 columns. It will then be printed to the console. When you run it, you should see

Array2DRowRealMatrix{{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}}

which represents our empty 4x3 matrix. While this is not a bad representation, it would be nicer if we could get a better representation of the rows and columns of data for our poor human eyes. The library provides a RealMatrixFormat for this. Add the following to the script:

def formatter = new RealMatrixFormat('{', '}', '{', '}', ',\n ', ',\t')

println formatter.format(mat)

Note that the println line replaces the existing one. Now we get a better, more human-readable representation:

{{0,    0,      0},
 {0,    0,      0},
 {0,    0,      0},
 {0,    0,      0}}

Interesting so far, but we would really like some data. With the existing matrix, you can add data in rows or columns by index, similar to an array:

mat.setRow(0, [1.0, 2.0, 3.0] as double[])
mat.setColumn(1, [9.0, 8.0, 7.0, 6.0] as double[])

Now when you run the code, notice that you get the first row and the second column populated with the provided data:

{{1,    9,      3},
 {0,    8,      0},
 {0,    7,      0},
 {0,    6,      0}}

Also notice that the column data overwrote the row data we set for the second column (index 1). In our row data it was 2.0, but the 9.0 value from the column was applied after and is the final value. The other main method of creating a matrix is by providing the data directly in the constructor. Say we want to create a matrix with the same dimensions, but with a sequential collection of values, such as:

1  2  3
4  5  6
7  8  9
10 11 12

You can do the following in the code:

def seqMat = new Array2DRowRealMatrix([
    [1.0, 2.0, 3.0] as double[],
    [4.0, 5.0, 6.0] as double[],
    [7.0, 8.0, 9.0] as double[],
    [10.0, 11.0, 12.0] as double[]
] as double[][])

println formatter.format(seqMat)

This code creates a matrix with an array of arrays, where the inner arrays are the rows of data. When printed out, you get the following:

{{1,    2,      3},
 {4,    5,      6},
 {7,    8,      9},
 {10,   11,     12}}

Now, let’s do some operations on our matrices. You can do common math operations on two matrices. Adding two matrices:

def sum = mat.add(seqMat)
println formatter.format(sum)

This gives you the element-by-element sum of the values and yields:

{{2,    11,     6},
 {4,    13,     6},
 {7,    15,     9},
 {10,   17,     12}}

Subtracting one matrix from another:

def diff = seqMat.subtract(mat)
println formatter.format(diff)

Gives:

{{0,    -7,     0},
 {4,    -3,     6},
 {7,    1,      9},
 {10,   5,      12}}

Multiplication of matrices is not what you might intuitively think it is, unless you are up on your Linear Algebra. Since there are whole wiki pages devoted to Matrix Multiplication, I won’t go into it here beyond stating that it can be done when you have square matrices (ours are not). Not being a tutorial on Linear Algebra, I am going to leave it at that. You can also multiply a matrix by a scalar number:

def prod = mat.scalarMultiply(2)
println formatter.format(prod)

Which multiplies every element by the given value and results in:

{{2,    18,     6},
 {0,    16,     0},
 {0,    14,     0},
 {0,    12,     0}}

Similarly, there is a scalarAdd(double) method.

Other useful operations may be performed on matrices. You can "transpose" the matrix:

def trans = seqMat.transpose()
println formatter.format(trans)

This rotates the values of the matrix to turn rows into columns, as in our example:

{{1,    2,      3},
 {4,    5,      6},
 {7,    8,      9},
 {10,   11,     12}}

becomes

{{1,    4,      7,      10},
 {2,    5,      8,      11},
 {3,    6,      9,      12}}

There are a handful of other built-in operations available to matrices that are probably useful if you know what you are doing, but at this point, I do not. Another useful construct is the set of "walker" methods that allow you to walk through the elements of the matrix in various ways, allowing you to modify the elements or simply read them. Let’s take our initial matrix as an example and multiply every element by 2.0 both in place and in an external collection.

For the in-place modification we need a RealMatrixChangingVisitor

class MultiplicationVisitor extends DefaultRealMatrixChangingVisitor {

    double factor

    double visit(int row, int column, double value){
        value * factor
    }
}

mat.walkInOptimizedOrder(new MultiplicationVisitor(factor:2.0))
println formatter.format(mat)

This visitor simply multiplies each value by the provided factor and returns it, which will update the value in the matrix. The resulting matrix has the following:

{{2,    18,     6},
 {0,    16,     0},
 {0,    14,     0},
 {0,    12,     0}}

You can also walk a matrix without the ability to change the internal values. This requires a RealMatrixPreservingVisitor:

class CollectingVisitor extends DefaultRealMatrixPreservingVisitor {

    List values = []

    void visit(int row, int column, double value){
        values << value
    }
}

def collectingVisitor = new CollectingVisitor()
mat.walkInOptimizedOrder(collectingVisitor)
println collectingVisitor.values

In this case, the values are collected into a list and no matrix value is modified. You get the following result:

[2.0, 18.0, 6.0, 0.0, 16.0, 0.0, 0.0, 14.0, 0.0, 0.0, 12.0, 0.0]

This contains a list of all the values from our original matrix after the previous visitor has modified it.

Matrix operations can seem quite complicated; however, they are not bad with a helpful library. So far the Commons Math API seems pretty useful for these more advanced math concepts.

The entire script for this tutorial is provided below for completeness:

matrix-math.groovy
@Grapes(
   @Grab('org.apache.commons:commons-math3:3.6.1')
)

import org.apache.commons.math3.linear.*

def formatter = new RealMatrixFormat('{', '}', '{', '}', ',\n ', ',\t')

def mat = new Array2DRowRealMatrix(4,3)
mat.setRow(0, [1.0, 2.0, 3.0] as double[])
mat.setColumn(1, [9.0, 8.0, 7.0, 6.0] as double[])

println formatter.format(mat)
println()

def seqMat = new Array2DRowRealMatrix([
    [1.0, 2.0, 3.0] as double[],
    [4.0, 5.0, 6.0] as double[],
    [7.0, 8.0, 9.0] as double[],
    [10.0, 11.0, 12.0] as double[]
] as double[][])

println formatter.format(seqMat)
println()

def sum = mat.add(seqMat)
println formatter.format(sum)
println()

def diff = seqMat.subtract(mat)
println formatter.format(diff)
println()

def prod = mat.scalarMultiply(2)
println formatter.format(prod)
println()

def trans = seqMat.transpose()
println formatter.format(trans)
println()

class MultiplicationVisitor extends DefaultRealMatrixChangingVisitor {

    double factor

    double visit(int row, int column, double value){
        value * factor
    }
}

mat.walkInOptimizedOrder(new MultiplicationVisitor(factor:2.0))
println formatter.format(mat)
println()

class CollectingVisitor extends DefaultRealMatrixPreservingVisitor {

    List values = []

    void visit(int row, int column, double value){
        values << value
    }
}

def collectingVisitor = new CollectingVisitor()
mat.walkInOptimizedOrder(collectingVisitor)
println collectingVisitor.values
println()

Gradle Dependencies Behind the Wall

10 July 2016 ~ blog groovy gradle

Some companies like to take full control of their build environments and disallow builds that pull artifacts from external sources so that only approved internal artifact repositories are used containing only approved artifacts. While the validity of this is debatable, it exists and in my experience tends to add roadblocks to development, especially when working with new frameworks and libraries.

Consider the scenario where you are working on a poject that uses a newer version of the Spring Framework than has been previously used in the company. Now you need to get the new Spring artifacts into your approved repository, which requires an issue ticket of some sort and at least one or two architects to approve it. I am sure I am not shocking you when I say that Spring has numerous dependencies if you are doing anything interesting with it and they are all transient. How do you get a list of the dependencies that you need to have added without an arduous catalogging of artifacts and their dependencies or numerous iterations of the list-ticket-approval work flow( which is not generally speedy)? You write a Gradle plugin to do it for you.

I have added a checkAvailability task to my Dependency Checker Plugin. This task allows you to do your development work using the standard jcenter or mavenCentral artifact repositories so that you can get things working, but when you are ready to lock down your dependencies you can run:

./gradlew checkAvailability -PrepoUrls=http://artifacts.mycompany.com/repository

Which will list out the dependencies missing from the specified repository without affecting your build. The reported console entries will look something like:

Availability check for (commons-lang:commons-lang:2.1.2): FAILED

You can provide additional configuration to futher configure the task:

checkAvailability {
    repoUrls = ['http://artifacts.mycompany.com/repository']
    configurations = ['runtime']
    ignored = ['com.something:thingifier:1.2.3']
    failOnMissing = true
}

This configuration will specify the default repoUrls to be used, which may still be overridden on the command line. The configurations property allows you to limit the dependency configurations searched (to only runtime in this case). The ignored property allows specified artifacts to be ignored even if they are missing. And finally, the failOnMissing property will cause the build to fail when set to true after reporting all the missing dependencies - the default is false so that it will only list the status of the dependencies and allow the build to continue.

Now, armed with a full list of the dependencies missing from your internal artifact repository, you can create your issue ticket and get the approvals once and get back to actual work faster.

Older posts are available in the archives.


Creative Commons License CoffeaElectronica.com content is copyright © 2016 Christopher J. Stehno and available under a Creative Commons Attribution-ShareAlike 4.0 International License.