Tuesday, November 18, 2014

Example Using Grails Promises

I was recently playing around with the Asynchronous Programming features in Grails using Promises, and wanted to share an example that went a little beyond a simple example. In case you are using an older version of Grails, the asynchronous features where added in Grails 2.3. While there are a lot of useful asynchronous features in Grails, for this article I'll only focus on using Promises. Promises are a common concept being introduced in many concurrency frameworks. They are similar to Java's java.util.concurrent.Future class, but like all things with Grails/Groovy, Grails has made them easier to use.

First, before showing you an example, go ahead and run grails console under an existing grails project. If you don't have one, install grails (see GVM) and run grails create-app. Using the grails console will allow you to quickly run these examples and experiment on your own.

Basic Example

import static grails.async.Promises.task
import static grails.async.Promises.waitAll

def task1 = task {
    println "task1 - starting"
    Thread.sleep(5000)
    println "task1 - ending"
}

def task2 = task {
    println "task2 - starting"
    Thread.sleep(1000)
    println "task2 - ending"
}

waitAll(task1, task2)
This would output:
task1 - starting
task2 - starting
task2 - ending
task1 - ending

More Complex Example
Let's say you wanted to list the states of 5 zip codes. Here is what that would look like if we did it synchronously:

["74172", "64840", "67202", "68508", "37201"].each { z ->
    println "getting state for zip code: $z"
    def response = new URL("http://zip.getziptastic.com/v2/US/$z").content.text
    def json = grails.converters.JSON.parse(response)
    println "zip code $z is in state $json.state"
}



And the output for that would look like:
getting state for zip code: 74172
zip code 74172 is in state Oklahoma
getting state for zip code: 64840
zip code 64840 is in state Missouri
getting state for zip code: 67202
zip code 67202 is in state Kansas
getting state for zip code: 68508
zip code 68508 is in state Nebraska
getting state for zip code: 37201
zip code 37201 is in state Tennessee

And here is what it would look like using Grails Promises to make it asynchronous:

import static grails.async.Promises.task
import static grails.async.Promises.waitAll

def tasks = ["74172", "64840", "67202", "68508", "37201"].collect { z ->
    task {
        println "getting state for zip code: $z"
        def response = new URL("http://zip.getziptastic.com/v2/US/$z").content.text
        def json = grails.converters.JSON.parse(response)
        println "zip code $z is in state $json.state"
    }
}

waitAll(tasks)

The asynchronous output would look like this:
getting state for zip code: 37201
getting state for zip code: 68508
getting state for zip code: 67202
getting state for zip code: 64840
getting state for zip code: 74172
zip code 74172 is in state Oklahoma
zip code 37201 is in state Tennessee
zip code 64840 is in state Missouri
zip code 68508 is in state Nebraska
zip code 67202 is in state Kansas

Each time you run the asynchronous version it will output a different order because the tasks are running asynchronously. The waitAll() method will block until all tasks complete.

Thanks to jeremydanderson for helping me figure out how best to use the collect method.

Tuesday, November 11, 2014

Groovy Spring Bean for Static Factory

I started playing around with Grails again recently and ran into a problem trying to create a bean in the Grails resources.groovy file for a static factory. After several frustrating hours trying to find the right combination, I eventually stumbled upon an answer.

The factory I was trying to create a bean from was the JAX-RS Client API class ClientBuilder.newClient() which returns a Client object.

Here is what the bean definition looks like in my Grails resources.groovy file:

import javax.ws.rs.client.ClientBuilder

beans = {
    httpClient(ClientBuilder) { bean ->
        bean.factoryMethod = 'newClient'
        bean.destroyMethod = 'close'
    }
}

Then in your Grails service or controller you can autowire or inject the bean by doing the following:
class FooService {
    def httpClient

    def get(url) {
        return httpClient.target(url).request().get()
    }
}

Hope it helps the next person.

Monday, July 21, 2014

Disable Spring Boot Production Ready Services

For the past two months I've had the pleasure of working with The Lampo Group developing Hypermedia-Driven REST services using Spring Boot. Spring Boot makes it super simple to get started writing REST services. One of its biggest advantages is by default it embeds tomcat as the servlet container, allowing the developer to focus on other important things. Another great thing about Spring Boot is it includes the ability to easily enable what they call Production-Ready or Production-Grade Services. These services allow you to monitor and manage your application when its pushed to production and it's as easy as adding a dependency to your project. Unfortunately, it wasn't well documented on how to disable some of these services. But before I show you how to disable them, let me first show you how to enable them.

Enabling Spring Boot's Production-Ready Services
One of the reasons we wanted to enable some of the production-ready services was our target production environment was Amazon Web Services (AWS). As a part of that they support Elastic Load Balancing which allows one to configure a health check endpoint. It's basically an endpoint you configure in AWS that gets pinged to make sure the EC2 instance is up and running. As luck would have it, one of the services included in Spring Boot's production-ready services was a health endpoint.

To enable the production-ready services all you have to do is add a dependency to your project. If you are using maven all you have to do is add the following to your pom.xml.

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-actuator</artifactid>
    <version>1.1.4.RELEASE</version>
</dependency>


After you make the change to your pom.xml, just rebuild your project and you should be able to access http://localhost:8080/health and see something like this:



Not only does it add a health endpoint, but it also adds: autoconfig, beans, configprops, dump, env, info, metrics, mappings, shutdown (not enabled by default over HTTP), and trace. Like us, you might not want to expose all these endpoints in a production environment. In fact, all we wanted to enable was the health and info endpoints. The following will show you how to disable each service individually and how to re-enable them dynamically at runtime.

Disabling Spring Boot's Production-Ready Services
When you include the spring-boot-starter-actuator dependency in your project, it automatically exposes 11 different endpoints in your project. What I wanted to be able to do was disable all endpoints except health and info, but also have the ability to enable the other services at runtime via environment variables.

To disable some of the production-ready services add the following to your /src/main/resources file. These will be your default settings for your project.

endpoints.autoconfig.enabled=false
endpoints.beans.enabled=false
endpoints.configprops.enabled=false
endpoints.dump.enabled=false
endpoints.env.enabled=false
endpoints.health.enabled=true
endpoints.info.enabled=true
endpoints.metrics.enabled=false
endpoints.mappings.enabled=false
endpoints.shutdown.enabled=false
endpoints.trace.enabled=false


To enable/disable endpoints externally at runtime you can follow any one of these steps. Since our project is following the 12-factor app rules we needed the ability to enable/disable endpoints by setting environment variables. So for example, if I wanted to enable the metrics endpoint at runtime, I would set the following environment variable.

export ENDPOINTS_METRICS_ENABLED=true


After restarting Sprint Boot you can access the metrics endpoint at http://localhost:8080/metrics. Note, that as of version 1.0.1.RELEASE, you are unable to disable the mappings endpoint, but this was quickly fixed in 1.1.3.RELEASE.

In summary, I've been very impressed with how easy it is to work with Spring Boot and the production-ready services. In another article I'll cover how to use maven filtering, along with the git-commit-id-plugin, to display project information in the info endpoint.