@Override
  public void handleReturnValue(
      Object returnValue,
      MethodParameter returnType,
      ModelAndViewContainer mavContainer,
      NativeWebRequest webRequest)
      throws Exception {

    if (returnValue == null) {
      mavContainer.setRequestHandled(true);
      return;
    }

    HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
    ServerHttpResponse outputMessage = new ServletServerHttpResponse(response);

    if (ResponseEntity.class.isAssignableFrom(returnValue.getClass())) {
      ResponseEntity<?> responseEntity = (ResponseEntity<?>) returnValue;
      outputMessage.setStatusCode(responseEntity.getStatusCode());
      outputMessage.getHeaders().putAll(responseEntity.getHeaders());
      returnValue = responseEntity.getBody();
      if (returnValue == null) {
        mavContainer.setRequestHandled(true);
        return;
      }
    }

    ServletRequest request = webRequest.getNativeRequest(ServletRequest.class);
    ShallowEtagHeaderFilter.disableContentCaching(request);

    Assert.isInstanceOf(ResponseBodyEmitter.class, returnValue);
    ResponseBodyEmitter emitter = (ResponseBodyEmitter) returnValue;
    emitter.extendResponse(outputMessage);

    // Commit the response and wrap to ignore further header changes
    outputMessage.getBody();
    outputMessage = new StreamingServletServerHttpResponse(outputMessage);

    DeferredResult<?> deferredResult = new DeferredResult<Object>(emitter.getTimeout());
    WebAsyncUtils.getAsyncManager(webRequest)
        .startDeferredResultProcessing(deferredResult, mavContainer);

    HttpMessageConvertingHandler handler =
        new HttpMessageConvertingHandler(outputMessage, deferredResult);
    emitter.initialize(handler);
  }