ST-DDT
ST-DDT

Reputation: 2707

Return empty JSON from spring controller for void response

I'm using Java 8, Tomcat 8, Spring-WebMVC 4.2.2.RELEASE, FasterXML 2.6.3.

I have the following method in my controller

@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public void updateCurrentUserDetails(@RequestBody final UserDTO userDTO) {
    final UserWithId user = SecurityUtil.getCurrentUser();
    this.userAccountService.updateUserDetails(user.getUserId(), user.getUsername(), userDTO);
}

This method returns void which resolves in an empty (0 byte) response. However the clients connecting to the server always expect JSON reponses even, if its an empty response.

So I would like to configure Spring/Jackson to return {} (2 byte) in that case.

I already thought about returning new Object() everywhere in the calls that would return void otherwise but IMO this is a dirty soution and there must be something better.

Upvotes: 3

Views: 9710

Answers (2)

ST-DDT
ST-DDT

Reputation: 2707

Its quite easy.

Just add the following to your spring xml/java config

<mvc:interceptors>
    <bean class="de.st_ddt.util.VoidResponseHandlerInterceptor" />
</mvc:interceptors>

And add this class to your classpath

public class VoidResponseHandlerInterceptor extends HandlerInterceptorAdapter {

    private static final String voidResponse = "{}";

    @Override
    public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler,
            final ModelAndView modelAndView) throws IOException {
        // Returned void?
        if (!response.isCommitted()) {
            // Used ModelAndView?
            if (modelAndView != null) {
                return;
            }
            // Access static resource?
            if (DefaultServletHttpRequestHandler.class == handler.getClass()) {
                return;
            }
            response.setStatus(200);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json");
            try (final Writer writer = response.getWriter()) {
                writer.write(voidResponse);
            }
            response.flushBuffer();
        }
    }
}

Upvotes: 4

Dave L.
Dave L.

Reputation: 9791

There shouldn't be any need to do all that. You can just use a 204 response code, which is made for the situation you are describing. You don't even need the ResponseBody annotation, just use:

@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(HttpStatus.NO_CONTENT)
public void updateCurrentUserDetails(@RequestBody final UserDTO userDTO) {
    final UserWithId user = SecurityUtil.getCurrentUser();
    this.userAccountService.updateUserDetails(user.getUserId(), user.getUsername(), userDTO);
}

204 response code:

The 204 (No Content) status code indicates that the server has
successfully fulfilled the request and that there is no additional
content to send in the response payload body.

Upvotes: 11

Related Questions