Loading...

January 16, 2017

Groovy Goodness: Uncapitalize Strings

Since Groovy 2.4.8 we can use the uncapitalize method on CharSequence objects. The capitalize method was already available for a long time, but now we have the opposite as well.

In the following example we see that the uncapitalize method only replaces the first letter of a String value to lower case:

assert 'Groovy'.uncapitalize() == 'groovy'
assert 'MrHaki'.uncapitalize() == 'mrHaki'

String message = 'Groovy Rocks!'
assert message.uncapitalize() == 'groovy Rocks!'

Written with Groovy 2.4.8.

January 2, 2017

Awesome Asciidoctor: Using Filename Starting With Dot As Block Title

Adding a block title in Asciidoctor is easily done by adding a line at the top of the block that starts with a dot (.). The text following the dot is then used as the title of the block. But if the text of the title itself starts with a dot (.) Asciidoctor get's confused. For example if we want to use a filename that starts with a dot (.filename) we must use different syntax to set the block title with the filename.

In the next Ascciidoc markup sample we use different ways to set the block title for a code block with a filename that starts with a dot. First we use the title attribute for the block. Another solution is to use the Unicode value for the dot. Next we enclose the filename in back ticks (`) which also formats the filename with a monotype font. And finally we can define the filename via a document attribute and reference the document attribute in the block title:

= Filenames starting with dot (.)

Several samples showing how to set block title when title starts with dot (`.`).

Code block title is filename that starts with dot (`.`), which confuses the parser:

[source,json]
// Title cannot be parsed correctly
// because of the 2 dots.
..eslintrc
----
{
    "key": "value"
}
----

Using explicit title attribute:

// Instead of using . notation
// for block title, we use the
// explicit block attribute
// title definition.
[source,json,title='.eslintrc']
----
{
    "key": "value"
}
----

Use Unicode value for dot:

[source,json]
// Use hexadecimal Unicode replacement for
// starting dot (.) in filename.
..eslintrc
// (Or with decimals: ..eslintrc)
----
{
    "key": "value"
}
----

Format filename as code:

[source,json]
// Put filename between back ticks (`)
// and title is recognized again and
// nicely formatted with monotype font.
.`.eslintrc`
----
{
    "key": "value"
}
----

Using document attribute to set filename:

[source,json]
// Section title is also parsed correctly
// if we use a document attribute
// with the filename.
:snippetFilename: .eslintrc
.{snippetFilename}
----
{
    "key": "value"
}
----

[source,json]
// We can re-use the same document attribute
// for other code sections.
:snippetFilename: .jslintrc
.{snippetFilename}
----
{
    "key": "value"
}
----

When we generate a HTML version of this markup we get the following result:

Written with Asciidoctor 1.5.4

December 20, 2016

Gradle Goodness: Run Task Ignoring Up-to-date Checks

Gradle builds are fast because Gradle supports incremental tasks. This means Gradle can determine if input or output of task has changed, before running the task. If nothing has changed a task is marked a up-to-date and the task is not executed, otherwise the task is executed. If we want execute a task even if it is up-to-date we must use the command line option --rerun-tasks.

In the following example we run the assemble task for a simple Java project, and we see all tasks are executed. When we invoke the assemble task again we see the tasks are all up-to-date:

$ gradle assemble

:compileJava
:processResources
:classes
:jar
:assemble

BUILD SUCCESSFUL

Total time: 1.765 secs
$ gradle assemble

:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar UP-TO-DATE
:assemble UP-TO-DATE

BUILD SUCCESSFUL

Total time: 0.715 secs
$

To run all tasks without an up-to-date check we use the option --rerun-tasks:

$ gradle --rerun-tasks assemble
:compileJava
:processResources
:classes
:jar
:assemble

BUILD SUCCESSFUL

Total time: 1.037 secs
$

Written with Gradle 3.2.1.

December 19, 2016

Spring Sweets: Add (Extra) Build Information To Info Endpoint

With Spring Boot Actuator we get some useful endpoints in our application to check on our application when it is running. One of the endpoints is the /info endpoint. We can add information about our application if Spring Boot finds a file META-INF/build-info.properties in the classpath of our application. With the Gradle Spring Boot plugin we can generate the build-info.properties file. When we apply the Gradle Spring Boot plugin to our project we get a Gradle extension springBoot in our build file. With this extension we can configure Spring Boot for our project. To generate project information that is used by the /info endpoint we must add the method statement buildInfo() inside the springBoot extension. With this method statement the Gradle Spring Boot plugin generates a file build/main/resources/META-INF/build-info.properties..

// File: build.gradle
plugins {
    id 'org.springframework.boot' version '1.4.2.RELEASE'
}
...
springBoot {
    // This statement tells the Gradle Spring Boot plugin
    // to generate a file 
    // build/resources/main/META-INF/build-info.properties
    // that is picked up by Spring Boot to display
    // via /info endpoint.
    buildInfo()
}
...

Let's run our application and send a request for /info:

$ http -b localhost:8080/info
{
    "build": {
        "artifact": "spring-boot-sample",
        "group": "mrhaki.spring",
        "name": "sample-mrhaki",
        "time": 1482139076000,
        "version": "0.3.0"
    }
}
$

To override the default properties or to add new properties we must provide a configuration closure to the buildInfo method. If we a built-in key as the name of the property it is overridden with a new value, otherwise the key is added as a new property. In the following example we add some extra properties and override the properties time and name:

// File: build.gradle
...
springBoot {
    buildInfo {
        // Generate extra build info.
        additionalProperties = [
                by: System.properties['user.name'],
                operatingSystem: "${System.properties['os.name']} (${System.properties['os.version']})",
                continuousIntegration: System.getenv('CI') ? true: false,
                machine: InetAddress.localHost.hostName,
                // Override buildInfo property time
                time: buildTime(),
                // Override name property
                name: 'sample-springboot-app'
        ]
    }
}

def buildTime() {
    final dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ")
    dateFormat.timeZone = TimeZone.getTimeZone('GMT')
    dateFormat.format(new Date())
}
...

We restart the application and invoke the /info endpoint to get more results for the build:

$ http -b localhost:8080/info
{
    "build": {
        "artifact": "spring-boot-sample",
        "by": "mrhaki",
        "continuousIntegration": "false",
        "group": "mrhaki.spring",
        "machine": "mrhaki-laptop-2015.local",
        "name": "sample-springboot-app",
        "operatingSystem": "Mac OS X (10.12.2)",
        "time": "2016-12-19 09:16:50+0000",
        "version": "0.3.0"
    }
}
$

Written with Spring Boot 1.4.2.RELEASE.

Spring Sweets: Add Git Info To Info Endpoint

With Spring Boot Actuator we get some endpoints that display information about our application. One of the endpoints is the /info endpoint. If our project uses Git we can add information about Git to the /info endpoint. By default Spring Boot will look for a file git.properties in the classpath of our application. The file is a Java properties file with keys that start with git. and have values like the branch name, commit identifier and commit message. Spring Boot uses this information and when we request the /info endpoint we get a response with the information. This can be very useful to check the Git information that was used to build the application. To create the git.properties file we can use a Gradle (or Maven) plugin that will do the work for us.

In the following example we use the Gradle plugin to generate the git.properties file for our project. The Gradle Git properties plugin is added in the plugins configuration block. The plugin adds a Gradle extension gitProperties that can be used to customize the output in git.properties. We could even change the location, but we keep it to the default location which is build/resources/main/git.properties.

// File: build.gradle
plugins {
    id 'org.springframework.boot' version '1.4.2.RELEASE'
    // Add Git properties plugin.
    id 'com.gorylenko.gradle-git-properties' version '1.4.17'
}

// Customize Git properties plugin.
gitProperties {
    // Change date format in git.properties file.
    dateFormat = "yyyy-MM-dd HH:mm:ssZ"
    dateFormatTimeZone = 'GMT'
}

That is all we need to do. The Git properties plugin generates the git.properties file that is need by Spring Boot. Let's run our application and send a request for the /info endpoint:

$ http -b localhost:8080/info
{
    "git": {
        "branch": "feature/dsl-hapi",
        "commit": {
            "id": "511d269",
            "time": "2016-12-15 12:28:20+0000"
        }
    }
}
$

We can even show more information by changing the Spring Boot configuration property management.git.info.mode. The default value is SIMPLE, but we can also use the value FULL. Then we get the Git commit message and user details. We can set the configuration property in different ways for our Spring Boot application. For example in application.yml, Java system property or environment variable. In our example we add a Java system property to the Gradle bootRun task:

// File: build.gradle
...
bootRun {
    systemProperty 'management.info.git.mode', 'FULL'
}
...

We execute the bootRun task and send a new request for the /info endpoint:

$ http -b localhost:8080/info
{
    "git": {
        "branch": "feature/dsl-hapi",
        "commit": {
            "id": "511d2693cbabc34449f838bf856fa2b9989cbca6",
            "id.abbrev": "511d269",
            "message": {
                "full": "Enable Codenarc checks for integration test code",
                "short": "Enable Codenarc checks for integration test code"
            },
            "time": "2016-12-15 12:28:20+0000",
            "user": {
                "email": "mrhaki@server",
                "name": "Hubert Klein Ikkink"
            }
        }
    }
}
$

This time we see more information about Git.

Written with Spring Boot 1.4.2.RELEASE

December 16, 2016

PlantUML Pleasantness: Get PlantUML Definition From PNG

When we generate a PNG version of our PlantUML definition the original definition is stored in the PNG image. We can extract the definition using the command line option -metadata. We need to provide the PNG file and in the output we see the original PlantUML definition.

The following PNG image (activity.png) is created with PlantUML:

Next we run PlantUML from the command line using the option -metadata:

$ java -jar plantuml.jar -metadata activity.png
------------------------
activity.png

@startuml

' Make a dashed line, alternative syntax for ..>
(*) -[dashed]-> "Write outline"

' Make line bold and use color code
"Write outline" -[bold,#008000]-> "Find example"

' Only change the color
"Find example" -[#ff00ff]-> "Write blog"

' Order of line style and color can be reversed
"Write blog" -[#6666ff,dashed]-> "Publish"

' Use dotted line style
"Publish" -[dotted]-> (*)

@enduml

PlantUML version 8051(Thu Dec 01 18:52:05 CET 2016)
(GPL source distribution)
Java Runtime: Java(TM) SE Runtime Environment
JVM: Java HotSpot(TM) 64-Bit Server VM
Java Version: 1.8.0_112-b16
Operating System: Mac OS X
OS Version: 10.12.1
Default Encoding: UTF-8
Language: en
Country: US

------------------------
$

At the top we see the section @startuml..@enduml with the PlantUML syntax that was used to generate the PNG image.

Written with PlantUML 8051.

December 14, 2016

PlantUML Pleasantness: Change Line Style And Color

We can change the line style and color when we "draw" the line in our PlantUML definition. We must set the line style and color between square brackets ([]). We can choose the following line styles: bold, plain, dotted and dashed. The color is either a color name or a hexadecimal RGB code prefixed with a hash (#).

In the following example activity diagram we apply different styles and colors to the lines:

@startuml

' Make a dashed line, alternative syntax for ..>
(*) -[dashed]-> "Write outline"

' Make line bold and use color name
"Write outline" -[bold,#green]-> "Find example"

' Only change the color with hexadecimal RGB code
"Find example" -[#ff00ff]-> "Write blog"

' Order of line style and color can be reversed
"Write blog" -[#6666ff,dashed]-> "Publish"

' Use dotted line style
"Publish" -[dotted]-> (*)

@enduml

When we generate the activity diagram we see the different line styles and colors:

Written with PlantUML 8051.

December 13, 2016

Awesome Asciidoctor: Change Number Style For Ordered Lists

To write a (nested) ordered lists in Asciidoctor is easy. We need to start the line with a dot (.) followed by a space and the list item text. The number of dots reflects the levels of nesting. So with two dots (..) we have a nested list item. By default each nested level has a separate numbering style. The first level has arabic numbering, the second lower case alphanumeric, the third upper case alphanumeric, the fourth lower case roman and the fifth (which is maximum depth of nested levels in Asciidoctor) has style upper case roman. But we can change this by setting a block style for each nested level block. The name of the block style is arabic, loweralpha, upperalpha, lowerromann or upperroman. With the HTML5 backend we can also use decimal and lowergreek.

In the following example we have an ordered list where we set different block styles for the nested level:

= Nested numbering styles

. Services
[arabic]
.. Datastore
.. Mail

. Repositories
// Only HTML backend
[decimal]
.. PostgresDB
.. Redis

. Controllers
// Only HTML backend
[lowergreek]
.. API
.. Admin

. Software systems
// Or use upperalpha for upper case alphanumeric
[loweralpha]
.. OAuth

. Operatings systems
// Or use lowerroman for lower case roman
[upperroman]
.. Linux
[decimal]
... Server A
... Server B
.. macOS
.. Windows server

When we create the HTML output we have the following result:

Written with Asciidoctor 1.5.4.

Gradle Goodness: Passing Environment Variable Via Delegate Run Action In IntelliJ IDEA

IntelliJ IDEA 2016.3 introduced the option to delegate the run action to Gradle. This means when we have a run Configuration for our Java or Groovy classes we can use the Run action and IDEA will use Gradle to run the application. Actually IntelliJ IDEA creates a new task of type JavaExec dynamically for our specific run configuration with the main property set to the class we want to run.

In the Edit Configuration dialog window we can set the command line argument and Java system properties. These are passed on to the dynamically created JavaExec task and are accessible from within the class that runs. The environment variables that can be set in the Edit Configuration dialog windows are not passed to the JavaExec task configuration. But we can do it ourselves in the build script file of our project. We look for the dynamically created task and use the environment method to add a environment variable that can be access in the Java or Groovy class that is executed.

We start our example with a simple Groovy class that can be executed using JavaExec. We simply print out the given input arguments, all Java system properties that start with sampleApp and finally all environment variables that start with SAMPLE_APP:

// File: src/main/groovy/mrhaki/gradle/SampleApp.groovy
package mrhaki.gradle

class SampleApp {

    static void main(final String[] args) {
        final app = new SampleApp()
        app.printArgs(args)
        app.printSystemProperties()
        app.printEnv()
    }

    void printArgs(final String[] args) {
        printSection 'Command line arguments', args
    }

    void printSystemProperties() {
        printSection 'System properties', System.properties.findAll(findNameStartsWith('sampleApp'))
    }

    void printEnv() {
        printSection 'environment', System.getenv().findAll(findNameStartsWith('SAMPLE_APP'))
    }
    
    private void printSection(final String title, final values) {
        println "--- $title ---"
        println values
    }

    private Closure findNameStartsWith(final String search) {
        { name, value -> name.startsWith(search) }
    }
    
}

We create a new Run/Debug Configuration for our SampleApp class:

When we click on OK to save the configuration we are ready to use the Run 'SampleApp' action. When we look at the output we get the following result:

10:54:29: Executing external task 'run SampleApp'...
:compileJava UP-TO-DATE
:compileGroovy 
:processResources UP-TO-DATE
:classes 
:run SampleApp
--- Command line arguments ---
[Execute via IDEA delegate to Gradle]
--- System properties ---
[sampleApp:Gradle Galore]
--- environment ---
[:]

BUILD SUCCESSFUL

Total time: 3.539 secs
10:54:33: External task execution finished 'run SampleApp'.

Notice the Gradle tasks that are invoked and the dynamically created run SampleApp task. We see our Java system property is passed on, together with the program arguments. The environment variable is not passed on. We must add some extra configuration to the dynamically created task run Sample in our build.gradle file:

// File: build.gradle
...
setEnvVarRunConfiguration 'SampleApp', 'SAMPLE_APP', 'Gradle environment variable'

/**
 * Add environment variable to JavaExec task
 * configuration created by IntelliJ IDEA
 * from a Run/Debug configuration.
 * 
 * @param configuration Name of IntelliJ IDEA Run/Debug configuration
 * @param envName Name of environment variable
 * @param envValue Value for environment variable
 */
def setEnvVarRunConfiguration(
        final String configuration, 
        final String envName, 
        final String envValue) {

    // Find task by type JavaExec and matching 
    // task name for configuration name.
    final javaExecRunConfiguration = { task -> 
        task instanceof JavaExec && task.name == "run $configuration"
    }
    
    tasks.matching(javaExecRunConfiguration).all {
        // Add environment variable to JavaExec 
        // task configuration.
        environment envName, envValue
    }
}
...

Now we re-run our application and we get the following output:

11:29:19: Executing external task 'run SampleApp'...
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:run SampleApp
--- Command line arguments ---
[Execute via IDEA delegate to Gradle]
--- System properties ---
[sampleApp:Gradle Galore]
--- environment ---
[SAMPLE_APP:Gradle environment variable]

BUILD SUCCESSFUL

Total time: 0.599 secs
11:29:19: External task execution finished 'run SampleApp'.

Written with IntelliJ IDEA 2016.3 and Gradle 3.2.1.

December 12, 2016

PlantUML Pleasantness: Using Current Date

In PlantUML we can use the special variable %date% to get the current date and time. The default format shows day of the week, date, time and timezone. We can change the date format by specifying our format with the Java SimpleDateFromat symbols. For example to only get the hours and minutes we would write %date[HH:mm]%.

In the following example we use the %date% variable as is and with a custom format:

@startuml
' Use %date% to get date diagram is generated.
title Sample with date - %date%

' We can use Java SimpleDateFormat options
' to format the date. In this example we
' only want the day-month-year of the date.
footer Generated on %date[dd-MM-yyyy]%
@enduml

When we generate a graphical representation we get the following result:

Written with PlantUML 8051.