Loading...

December 23, 2015

Ratpacked: Register Renderer For A List Of Objects

When we use the render method in our Ratpack application then Ratpack will use the type of the object we want to render to find an appropriate renderer. Some renderers are built-in, like a Promise or CharSequence renderer. We can write our own renderers by implementing the ratpack.render.Renderer interface. Next we must register our renderer in the Ratpack registry.

In our example application we have a very simple User class:

// File: src/main/groovy/com/mrhaki/ratpack/User.groovy
package com.mrhaki.ratpack

class User {
    String username
}

We define a renderer for a list of User objects:

// File: src/main/groovy/com/mrhaki/ratpack/UserListRenderer.grooovy
package com.mrhaki.ratpack

import com.google.inject.util.Types
import ratpack.handling.ByContentSpec
import ratpack.handling.Context
import ratpack.jackson.Jackson
import ratpack.render.Renderer

import static ratpack.groovy.Groovy.markupBuilder

class UserListRenderer implements Renderer<List<User>> {

    /**
     * Define that this renderer is used for List instance
     * with User instances.
     *
     * @return Type of List<User>
     */
    @Override
    Class<List<User>> getType() {
        Types.listOf(User).rawType
    }

    @Override
    void render(Context context, List<User> userList) throws Exception {
        // We return different responses based on the 
        // requested content type.
        context.byContent { ByContentSpec spec ->
            spec
                // Render JSON response.
                .json {
                    context.render(Jackson.json(userList))
                }
                // Render XML response
                .xml {
                    // Use markupBuilder method to create XML content.
                    context.render(markupBuilder('application/xml', 'UTF-8') {
                        users {
                            userList.each { singleUser ->
                                user {
                                    username(singleUser.username)
                                }
                            }
                        }
                    })
                }
        }
    }
}

Now we use the UserListRenderer in the configuration of our Ratpack application:

// File: src/ratpack/ratpack.groovy
import com.mrhaki.ratpack.UserListRenderer

import static ratpack.groovy.Groovy.ratpack

ratpack {
    bindings {
        // Add renderer for a list of users
        // to the registry.
        bind(UserListRenderer)
        
        // Create two sample users.
        bindInstance(['mrhaki', 'hubert'].collect { String name -> 
            new User(username: name)
        })
    }

    handlers {
        get('users') { List<User> users ->
            // Render the list of users
            // fetched from the registry.
            // Ratpack will use the 
            // UserListRenderer we have added
            // to the registry.
            render(users)
        }
    }
}

When we invoke the URL http://localhost:5050/users for both JSON and XML content we get the following results:

$ http localhost:5050/users Accept:application/json
HTTP/1.1 200 OK
connection: keep-alive
content-encoding: gzip
content-type: application/json
transfer-encoding: chunked

[
    {
        "username": "mrhaki"
    }, 
    {
        "username": "hubert"
    }
]

$ http localhost:5050/users Accept:application/xml
HTTP/1.1 200 OK
connection: keep-alive
content-encoding: gzip
content-type: application/xml
transfer-encoding: chunked

<users>
    <user>
        <username>mrhaki</username>
    </user>
    <user>
        <username>hubert</username>
    </user>
</users>

$

Written with Ratpack 1.1.1.