Having Gradle Note Your Build Info

Managing Java server code you’ll employ a lot of monitoring tools, standard and often custom. But in addition to runtime info, I often want to know the build information of a process. What version is it? What is it dependent on? Who built it? When? Things like that. Ideally you want this reported in a consistent format so your monitoring tools can incorporate it.

Working somewhere that doesn’t yet have a standard for this, I wrote a minimal gradle plugin that gathers base information and creates a JSON file containing it. So, each build, this info can be branded into the code and then retrieved programmatically. For example, my RESTful servers just hang the file off a standard end point.

At this point the file looks something like:

{
    "project.name": "super-server",
    "project.version": "1.0.5",
    "builder": "jenkins",
    "build.date": "2015-12-30T20:13:06+0000",
    "java.vendor": "Oracle Corporation",
    "java.version": "1.8.0_60",
    "source.compatibility": "1.8",
    "target.compatibility": "1.8",
    "dependencies": [
        "slf4j-jdk14-1.7.13.jar",
        "jetty-server-9.3.2.v20150730.jar",
        "jetty-webapp-9.3.2.v20150730.jar",
        "websocket-server-9.3.2.v20150730.jar",
        "websocket-servlet-9.3.2.v20150730.jar",
        "javax.servlet-api-3.1.0.jar",
        "jetty-http-9.3.2.v20150730.jar",
        "jetty-io-9.3.2.v20150730.jar"
    ]
    "custom": {
        "branch": "dev"
    }
}

The plugin is dead simple to use, I just make gradle’s processResources task depend on it. You can take a look at the project on Github.

Gradle, JUnit and AspectJ

I’m a believer in TDD, particularly when I’m writing challenging code. Recently I needed to write some Java annotations that acted as aspects around the methods they annotated.  But testing it proved to be a challenge. Try as I might, I could not get the AspectJ plugin to weave the aspects into the test code.  The weaving occurred on the main source but not the tests.

So here’s how I worked around it. Yes, my testing affected my implementation, which is a bad thing, but I think you’ll agree the impact was very minimal and the benefits where worth it.

I added a package “examples” to my source. In that package I put examples of each of the annotations working on example classes. My tests used those examples to test against. Then I made sure that that package was excluded from my resultant jar file.  Voila.

The relevant parts of my gradle.build is here:

buildscript {
    repositories {
        maven {
         url "https://maven.eveoh.nl/content/repositories/releases"
        }
    }
    dependencies {
        classpath "nl.eveoh:gradle-aspectj:1.6"
    }
}

project.ext {
    aspectjVersion = "1.8.7"
}

apply plugin: "aspectj"

jar {
    dependsOn classes
    from sourceSets.main.output
    exclude("**/examples") // Exclude the examples needed for tests
}

task javadocJar(type: Jar, dependsOn: javadoc) {
    from javadoc.destinationDir
    exclude("**/examples") // Exclude the examples needed for tests
    classifier = "javadoc"
}