Best practice for wrapping the body of ResponseEntity ajax style?

时间:2015-10-31 00:07:09

标签: java spring-mvc generics

With ResponseEntity we have direct control over the HTTP response; we can set the headers, body and HTTP response code. And let's say on the client side we have a generic AJAX data service that is expecting three response status conditions: success, fail, and error - this status will be evaluated separately from the HTTP status code, which is of course taken care of by $.ajax. As a result, we need a generic object of some sort for the body of ResponseEntity, maybe something like the below, where data in JsonResponse is whatever piece of data the client requested; a list of users, a map of arbitrary data, anything (more on this in a second): ResponseEntityFactory.java public class ResponseEntityFactory { private enum ResponseStatus { SUCCESS, FAIL, ERROR } public static ResponseEntity success (String message, Object data) { return getResponseEntity(HttpStatus.OK, ResponseStatus.SUCCESS, message, data, null); } /* ADDITIONAL SUCCESS, FAIL, ERROR FACTORY METHODS */ private static ResponseEntity getResponseEntity(HttpStatus httpStatus, ResponseStatus responseStatus, String message, Object data, HttpHeaders headers) { if (httpStatus == null) throw new IllegalArgumentException("HttpStatus cannot be null"); if (responseStatus == null) throw new IllegalArgumentException("ResponseStatus cannot be null"); JsonResponse jsonResponse = new JsonResponse(responseStatus, message, data); return new ResponseEntity(jsonResponse, headers, httpStatus); } private static class JsonResponse { private ResponseStatus status; private String message; private Object data; public JsonResponse(ResponseStatus status, String message, Object data) { if (status == null) throw new IllegalArgumentException("ResponseStatus cannot be null"); this.status = status; this.message = message; this.data = data; } public ResponseStatus getStatus() { return status; } public void setStatus(ResponseStatus status) { this.status = status; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } } } ExampleController.java @Controller @RequestMapping(value = "/example") public class ExampleController { @Autowire private UserService userService; @RequestMapping(method = RequestMethod.GET) public ResponseEntity getUsers() { List<User> users = userService.getAllUsers(); return AjaxResponseFactory.success("Found users", userList); } @RequestMapping(value = "/active/{id}" method = RequestMethod.GET) public ResponseEntity isUserActive(long userId) { boolean = userService.isUserActive(userId); return AjaxResponseFactory.success(null, boolean); } } The ResponseEntityFactory simplifies the controller, but my entire concern for this question centers around the data variable (of type Object) in JsonResponse - it smells. From the testing I've done so far, everything is serializing correctly: single primitives, to simple lists of String or Long, to more complex domain objects. So my question is, is this okay? Is there an alternative? An opportunity to somehow use generics<T>? Again, the main goal is to be able to evaluate the HTTP response code separately from a response status code of success, fail, error - which in itself allows for greater granularity when reacting to the server's response. For instance, it's possible a fail condition to be returned with an HTTP 200 OK; the HTTP request was successful, it'd be inappropriate to set it otherwise, however there was a validation error (maybe a null username or something), which disallowed the action on the server. It could be argued that these types scenarios are technically of type 400 Bad Request, but I tend to agree with folks that, even with the latest RFC 400 definition, these statuses should be associated to legitimate malformed requests, and not an necessarily and arbitrary issue with business logic. So, what's the best way to ensure proper serialization of the data object if I'd like to respond to the browser with a JsonResponse type object within ResponseEntity? I'm open to any suggestions or alternatives - not tied to this at all, just seemed like a reasonable approach. But I'd be interested to see if solving this with generics would be feasible and/or more desirable.

0 个答案:

没有答案