November 16, 2015

Ratpacked: Type Conversion For Path Tokens

In Ratpack we can use path token as variable parts of a request. We can access a path token via the PathBinding instance that is added to the context registry by Ratpack. There is a shorthand method getPathTokens to get the PathTokens object. To get the value for a token we use the get method or with the Groovy DSL we can use square brackets with the name of the token. If we expect a token value to be of a certain type, like a Long
or Boolean, we can use the asLong or asBoolean method. The value is then converted to the correct type and if the conversion fails an exception is thrown. The exception will be converted to a 500 status code in the response by the default error handler.

The PathTokens class has methods for converting to Long, Byte, Integer, Short and Boolean types with the methods asLong, asByte, asInteger, asShort and asBoolean

In the following sample Ratpack application we use a path token with the name id. We use the asLong method to convert it to a Long instance:

// File: src/ratpack/Ratpack.groovy
import static ratpack.groovy.Groovy.ratpack

ratpack {

    handlers {
        prefix('products') {
            // Define path with token id.
            path(':id') { 
                // Use asLong method to convert id
                // token directly to Long value.
                // If parsing fails a server 500
                // error is returned.
                final Long productId = pathTokens.asLong('id')
                // Use found productId. If we get here
                // the parsing went ok.
                render "Product($productId)"

With the following specification we can see that a valid value is converted correctly and an invalid value gives a 500 error response code:

// File: src/test/com/mrhaki/ratpack/pathbinding/TypeConversionSpec.groovy
package com.mrhaki.ratpack.pathbinding

import ratpack.groovy.test.GroovyRatpackMainApplicationUnderTest
import ratpack.http.Status
import spock.lang.AutoCleanup
import spock.lang.Shared
import spock.lang.Specification

class TokenConversionSpec extends Specification {
    GroovyRatpackMainApplicationUnderTest app =
            new GroovyRatpackMainApplicationUnderTest()
    def "number value for product id must be parsed correctly"() {
        def response = app.httpClient.get('products/1029')
        response.body.text == 'Product(1029)'
        response.status.code == 200
    def "non number value should give a 500 error response"() {
        def response = app.httpClient.get('products/product-name')
        response.status.code == 500

Written with Ratpack 1.1.1.