I have a rest application that returns json/xml. I use jackson and jaxb for conversion. Some methods need to accept a query_string. I've used @ModelAttribute to map the query_string into an object, but this forces the object into my view. I do not want the object to appear in the view.
I think I need to use something other than @ModelAttribute, but I can't figure out how to do the binding, but not modify the view. If I omit @ModelAttribute annotation, the object appears in the view as the variable name (eg: "sourceBundleRequest").
Example Url:
http://localhost:8080/rest/sourcebundles/?updateDate=20100501&label=urgent
Controller Method:
@RequestMapping(value = {"", "/"}, method = RequestMethod.GET)
public String getAll(@ModelAttribute("form") SourceBundleRequest sourceBundleRequest, BindingResult result, ModelMap model) throws ApiException {
// Detect and report errors.
if (result.hasErrors()) {
// (omitted for clarity)
}
// Fetch matching data.
PaginatedResponse<SourceBundle> sourceBundleResponse = null;
try {
int clientId = getRequestClientId();
sourceBundleResponse = sourceBundleService.get(clientId, sourceBundleRequest);
} catch (ApiServiceException e) {
throw new ApiException(ApiErrorType.INTERNAL_ERROR, "sourceBundle fetch failed");
}
// Return the response.
RestResponse<PaginatedResponse> restResponse = new RestResponse<PaginatedResponse>(200, "OK");
restResponse.setData(sourceBundleResponse);
model.addAttribute("resp", restResponse);
// XXX - how do I prevent "form" from appearing in the view?
return "restResponse";
}
Example Output:
"form": {
"label": "urgent",
"updateDate": 1272697200000,
"sort": null,
"results": 5,
"skip": 0
},
"resp": {
"code": 200,
"status": "OK",
"data": {
"totalAvailable": 0,
"resultList": [ ]
}
}
Desired Output:
"resp": {
"code": 200,
"status": "OK",
"data": {
"totalAvailable": 0,
"resultList": [ ]
}
}
Omitting @ModelAttribute("form")
If I simply omit @ModelAttribute("form"), I still get the undesirable response but the incoming form is named by the object name. The response looks like this:
"resp": {
"code": 200,
"status": "OK",
"data": {
"totalAvailable": 0,
"resultList": [ ]
}
},
"sourceBundleRequest": {
"label": "urgent",
"updateDate": 1272697200000,
"sort": null,
"results": 5,
"skip": 0
}
Somehow I missed the most obvious way to fix this. I was focused on the Attributes and forgot that I can just modify the underlying Map.
It might be a little more efficient to omit @ModelAttribute as Biju suggested and then remove the sourceBundleRequest object. I suspect @ModelAttribute has some additional overhead.
How about using @JsonIgnore?
Haven't tested this
You need not annotate the form with @ModelAttribute if you don't want the form to come back to the view, it will cleanly get bound to
SourceBundleRequest
even without the @ModelAttribute annotation.Now, a standard way to return a JSON/XML response using Spring MVC is to return the type directly (in your case the
PaginatedResponse
) and then annotate the method with@ResponseBody
, an underlyingHttpMessageConverter
would then transform the response into a XML/JSON based on the Accept header from the client.