0

I am using Spring Boot 2.0 and have an endpoint in an @RestController that returns a DeferredResult and in some cases (e.g. if the wanted value does not need to be computed) it sets the result on that DeferredResult directly like so:

  @RequestMapping(value = "test")
  public DeferredResult<String> test() {
    DeferredResult<String> returnValue = new DeferredResult<>();
    returnValue.setResult("Hello, World");
    return returnValue;
  }

Unfortunately, the HTTP body that is returned is empty. The status code 200 shows that the request did not time out and if I add a completion handler to the deferred result, the handler is also called.

The issue also is not fixed when I explicitly create a new Thread and set the result on that after a small sleep period.

What do I have to change to let the DeferredResult actually be serialised correctly?

Edit:

As suggested in the comments, I turned on debug logging for Spring MVC and found the following log messages:

DEBUG org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor - Written [ok] as "text/plain" using [org.springframework.http.converter.StringHttpMessageConverter@6b634d28]
DEBUG org.springframework.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
DEBUG org.springframework.web.servlet.DispatcherServlet - Successfully completed request

The result seems to be written correctly at first but then a null ModelAndView is returned to the servlet for some reason.

What could cause this?

rodalfus
  • 166
  • 2
  • 14
  • By not using `DeferredResult`, why would you want to use an async result type for something that isn't asynchronous? I suspect this is due to the async handling not really being async as it is being handled by the same thread... But that is just a hunch. Have you checked the result of the call to `setResult` it returns a `boolean` it should return `true` if the value was set. You might want to enable DEBUG logging for `org.springframework.web` to see what happens with the async request in this case. – M. Deinum Sep 24 '18 at 14:13
  • This is simply a very condensed example of what is going on, we do need the asynchronous return type in some cases where we need to actually compute the value first (not shown in the example). Indeed, the above code works in another project I have, so I suspect some kind of configuration issue. Will definitely try with DEBUG logging. – rodalfus Sep 24 '18 at 15:03
  • Why would you need the async return value for something that isn't async (that is the part I don't get). It feels like we want to unify the return types of the controller methods regardless of what the actual result it. – M. Deinum Sep 24 '18 at 17:12
  • I've copied and pasted your code in a controller that I created and annotated with @RestController annotation and it returns the response "Hello, World" whenever I send a request. Please provide more information about the configurations and annotations you use, and make sure that your client accepts response type of "text/plain" – Mohamed Ibrahim Elsayed Nov 03 '18 at 04:27

2 Answers2

3

Do you have etags in use? We had this happen and adding

ShallowEtagHeaderFilter.disableContentCaching(request); 

to the controller method seemed to fix the issue.

Lucas Holt
  • 3,826
  • 1
  • 32
  • 41
0

I believe you have to add @ResponseBody to your method:

@RequestMapping(value = "test")
public @ResponseBody DeferredResult<String> test() {
  DeferredResult<String> returnValue = new DeferredResult<>();
  returnValue.setResult("Hello, World");
  return returnValue;
}

The @ResponseBody annotation tells a controller that the object returned is automatically serialized into JSON and passed back into the HttpResponse object.

https://www.baeldung.com/spring-request-response-body

locus2k
  • 2,802
  • 1
  • 14
  • 21
  • I am using the `@RestController` in the controller, so that annotation is added automatically. Even using the annotation, it does not work unfortunately. I edited my question to more correctly this. – rodalfus Sep 24 '18 at 12:41
  • Do you have @EnableAsync in configuration? – Huy Nguyen Sep 24 '18 at 15:03