Guillaume F. Guillaume F. - 5 months ago 13
Javascript Question

Rest types, JSON or HTML forms with the same URL

I am trying to create a RESTful service and encounter a type conflict within the application. Right now, I deal with this problem by using two different URLs, but this leads to other problems and doesn't feel right.

// Controller to get a JSON
@RequestMapping(value = "/stuff/{stuffId}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public stuffDto getStuff(@PathVariable String stuffId) {
return //JSON DTO//
}

// Controller to get an HTML Form
@RequestMapping(value = "/stuff/{stuffId}/form", // <- nasty '/form' here
method = RequestMethod.GET)
public String getStuffForm(@PathVariable String stuffId, ModelMap model) {
// Prepares the model
return "JSP_Form";
}


And on the JavaScript side:

function loadStuffForm(url) {
$.ajax({
type : 'GET',
url : url,
success : function(response) {
showStuffForm(response);
}
});
}


How can I merge both controllers so it will return the right type of data based on what the client accepts? By default it would return a JSON. I want to add 'text/html' somewhere in the ajax query to get the Form instead. Any idea?

Answer

You can use Content Negotiation to communicate to the server and tell it what kind of response you expect form it. In your particular scenario, you as a client using an Accept header tell the server to serve a text/html or application/json. In order to implement this, use two different produces with that same URL:

// Controller to get a JSON
@ResponseBody
@RequestMapping(value = "/stuff/{stuffId}", method = GET, produces = "application/json")
public stuffDto getStuff( ... ) { ... }

// Controller to get an HTML Form
@RequestMapping(value = "/stuff/{stuffId}", method = GET, produces = "text/html")
public String getStuffForm( ... ) { ... }

In your requests to /stuff/{id} endpoint, if you send Accept: text/html in headers, the HTML form would return. Likewise, you would get the JSON response by sending Accept: application/json header.

I'm not a JQuery expert but you can check this answer out on how to send an Accept header in $.ajax requests.