Grails 2.3 with asynchronous APIs and server-side REST improvements

Grails 2.3 has been released recently. This time, it is a release with a lot of new features.
IMHO, The most outstanding features are the REST improvements (including scaffolding of REST controllers) and the new support for an asynchronous programming model using promises.

Server-Side REST Improvements

Mapping to REST resources

You can now easily create RESTful URL mappings that map onto controllers. In the UrlMappings.groovy file, you can define which URL should be mapped to which restful controller.

"/api/books"(resources:'book')

This will map the HTTP operations to controller actions, e.g. GET on the URL /books will map to the index action, POST on this URL will map to the save action etc.

Scaffolding of REST controllers

This is a big one. All controllers scaffolded by Grails are REST controllers, so you can not only see the HTML representation of your data in the browser, but you can also retrieve the data in the form of XML or JSON.
What does that mean? You could instantly start to write, e.g., a mobile client for your app, you could connect your application to other applications or you could build a single page application that communicates with your controllers via JSON.
To achieve this, the respond() and withFormat() methods are used. respond() attempts to return the most appropriate type for the requested content type. A caller can specify the requested content type by either using a format=… request parameter, or by using a file extension (e.g. /book/show/1.json) or by using an accept header (which is the most natural way IMHO).

You have to explicitly enable content negotiation with accept headers in Config.groovy:

grails.mime.use.accept.header = true

The withFormat() method lets you decide what to render based on the requested content type.
Here is an example of two scaffolded controller actions:

def show(Book bookInstance) {
    respond bookInstance
}

@Transactional
def update(Book bookInstance) {
    // ...
    if (bookInstance.hasErrors()) {
        respond bookInstance.errors, view:'edit'
        return
    }

    bookInstance.save flush:true

    request.withFormat {
        form {
            flash.message = message(code: 'default.updated.message', args: [message(code: 'Book.label', default: 'Book'), bookInstance.id])
            redirect bookInstance
        }
        '*'{ respond bookInstance, [status: OK] }
    }
}

Async support

Grails 2.3 supports a new asynchronous programming API based on promises.

import static grails.async.Promises.*

def p1 = task { 2 * 2 }
def p2 = task { 4 * 4 }
def p3 = task { 8 * 8 }

onComplete([p1,p2,p3]) { List results ->
   assert [4,16,64] == results
}


def promiseList = tasks { 2 * 2 }, { 4 * 4}, { 8 * 8 }
assert [4,16,64] == promiseList.get()

GORM also supports async features, so you can execute database queries in parallel:

import static grails.async.Promises.*
// ...
def index() {
   tasks books: Book.async.list(),
         totalBooks: Book.async.count()
}

Controller Exception Handling and namespaced controllers

Prior Grails versions allowed to define a central Exception handler. Grails 2.3 allows to specify exception handling logic on a per controller level:

class DemoController {
    // ...

    def handleSQLException(SQLException e) {
        render 'An SQLException occurred'
    }

    def handleBatchUpdateException(BatchUpdateException e) {
        redirect controller: 'logging', action: 'batchProblem'
    }
}

The new version also allows multiple controllers with the same name (in different packages) by specifying a static namespace field in the controller class.
You can then define a corresponding URL mapping:

class UrlMappings {
    static mappings = {
        '/userAdmin' {
            controller = 'admin'
            namespace = 'users'
        }

        '/reportAdmin' {
            controller = 'admin'
            namespace = 'reports'
        }
    }
}

Default dependency resolution engine switched to Aether

Grails 2.3 tries to solve a lot of dependency management problems (which a lot of Grails users experienced) by adding support for the dependency manager Aether. Prior Grails 2.3, Grails used Ivy which seems to be responsible for a lot of trouble (e.g. problematic snapshot handling). Aether is the dependency manager used by Maven and should solve most issues users experienced when using Ivy.

Improved Data Binding

The new Grails version improves data binding by allowing finer grained control of the binding.
In Grails 2.3, you can customize the binding logic on a per class or per field level using the BindUsing annotation. Alternatively, you can implement your own ValueConverters. Date conversions can be customized with the BindingFormat annotation.

Improvements to Command Objects

You can now use domain classes as command objects.
If an id parameter is included in the request, the corresponding database record will be retrieved automatically.

def update(Book bookInstance) {
    // ...
}

You can now bind the request body to command objects. Grails will automatically parse the body of incoming requests. E.g. when it contains JSON or XML data, it will be automatically parsed and bound to a command object.

For more information, see the What’s new in Grails 2.3? section in the user guide.

Short URL for this post: https://wp.me/p4nxik-1E1
This entry was posted in Groovy and Grails and tagged , , , , , , , , , , . Bookmark the permalink.

Leave a Reply