Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to switch a Spring Roo or Grails project from typical MVC to AJAX/JSON/REST

This might seem like an odd question, but I am trying to get a handle on what the "best practice" is for converting an application that is set up to use something like Roo's or Grails' generation of controllers (which provides basic CRUD functionality) to something that returns a JSON response body instead for use in a JavaScript application.

The ambiguity of technology here is because I haven't actually started the project yet. I am still trying to decide which (Java-based) technology to use, and to see what kind of productivity tools I should learn/use in the process. It will be a web application, and it will use a database persistence layer. All other details are up in the air.

Perhaps the easiest way to accomplish my goal is to develop using some sort of AJAX plugin to start with, but most of the tutorials and descriptions out there say to start with a normal MVC architecture. Roo seems to make conversion of the controllers it generates to JSON-friendly return types difficult, and I'm not familiar enough with Groovy/Grails to know what it takes to do that.

This is mostly a learning experience for me, and I am open to any criticism or advice, but being a Q/A forum, I realize I need to incorporate an objective question of some sort. To fill that need, I ask:

What is the best way to set up an AJAX/RESTful interface for my entities in Roo and/or Grails?

like image 422
Andy Avatar asked Jan 18 '12 16:01

Andy


1 Answers

I recently did exactly this with a Grails application and found it surprisingly easy to take the generated controllers and get them to output JSON or XML or the HTML from the view depending on the content negotiation.

The places in the Grails manual to look into are the section(s) on Content Negotiation and, if you need to deal with JSON or XML input, marshaling.


To get JSON and XML output, in the default list() method, changed it to this (I have a Session object, in this case...one of my domain classes):

def list() {
    params.max = Math.min(params.max ? params.int('max') : 10, 100)
    def response = [sessionInstanceList: Session.list(params), sessionInstanceTotal: Session.count()]
    withFormat {
        html response
        json {render response as JSON}
        xml {render response as XML}
    }
}

Anywhere you are returning just an object by default, you will want to replace the returned value with the withFormat block.

You also may need to update your Config.groovy file where it deals with mime types. Here's what I have:

grails.mime.file.extensions = true // enables the parsing of file extensions from URLs into the request format
grails.mime.use.accept.header = true
grails.mime.types = [ html: ['text/html','application/xhtml+xml'],
                      xml: ['text/xml', 'application/xml'],
                      text: 'text/plain',
                      js: 'text/javascript',
                      rss: 'application/rss+xml',
                      atom: 'application/atom+xml',
                      css: 'text/css',
                      csv: 'text/csv',
                      all: '*/*',
                      json: ['application/json','text/json'],
                      form: 'application/x-www-form-urlencoded',
                      multipartForm: 'multipart/form-data'
                    ]

As input (to an update() or save() action, for example) JSON and XML payloads will automatically be unmarshaled and will be bound just like a form input would be, but I've found that the unmarshaling process is a bit picky (especially with JSON).

I found that, in order for JSON to be handled correctly in the update() method, the class attribute had to be present and correct on the inbound JSON object. Since the library I was using in my client application didn't make this an easy issue to deal with, I switched to using XML instead.

like image 86
cdeszaq Avatar answered Oct 13 '22 18:10

cdeszaq