1

How configure spring to work with CompletionStage return types? Consider a code:

@RequestMapping(path = "/", params = "p", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public CompletionStage<List<MyResult>> search(@RequestParam("p") String p) {
    CompletionStage<List<MyResult>> results = ...
    return results;
}

I got 404, but I see in log that method is triggered. If I change signature like that:

@RequestMapping(path = "/", params = "p", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public List<MyResult> search(@RequestParam("p") String p) {
    CompletionStage<List<MyResult>> results = ...
    return results.get();
}

I see successfull json array.

How to make CompletionStage works with spring (4.2.RELEASE)?

UPDATED

For test I wrote following methods:

@RequestMapping(path = "/async")
@ResponseBody
public CompletableFuture<List<MyResult>> async() {
    return CompletableFuture.completedFuture(Arrays.asList(new MyResult("John"), new MyResult("Bob")));
}

And it works. Oo

I have test this version of future:

@RequestMapping(path = "/async2")
@ResponseBody
public CompletableFuture<List<MyResult>> async2() {
    AsyncRestTemplate template = new AsyncRestTemplate();
    //simulate delay future with execution delay, you can change url to another one
    return toCompletable(template.getForEntity("https://www.google.ru/?gws_rd=ssl#q=1234567890-", String.class))
            .thenApply(
                    resp -> template.getForEntity("https://www.google.ru/?gws_rd=ssl#q=1234567890-", String.class))
            .thenApply(
                    resp -> template.getForEntity("https://www.google.ru/?gws_rd=ssl#q=1234567890-", String.class))
            .thenApply(
                    resp -> template.getForEntity("https://www.google.ru/?gws_rd=ssl#q=1234567890-", String.class))
            .thenApply(
                    resp -> template.getForEntity("https://www.google.ru/?gws_rd=ssl#q=1234567890-", String.class))
            .thenApply(
                    resp -> template.getForEntity("https://www.google.ru/?gws_rd=ssl#q=1234567890-", String.class))
            .thenApply(resp -> Arrays.asList(new MyResult("John"), new MyResult("Bob")));
}

A bit agly, but ... works!

So my original method has the following logic:

  1. Iterate over Collection
  2. Make async call via AsyncRestTemplate for each collection element
  3. Make call to each CompletableFuture in collection
    • thenApply (transform result)
    • thenCompose (make new async call with AsyncRestTemplate)
    • thenApply (transform result)
    • At the end I call transform List to Completable as described here.

It seem that Future transformation is wrong. Can it be that future chain eecutes too long? Any ideas?

Community
  • 1
  • 1
Cherry
  • 31,309
  • 66
  • 224
  • 364
  • That should be available by default. Post the error / logs you get on the server. (As an edit not as comments!). – M. Deinum Sep 14 '15 at 11:23
  • Updated. There are no erros in logs, but I have done some experiments, may it helps. – Cherry Sep 14 '15 at 13:13

1 Answers1

0

The problem was in that line:

@RequestMapping(path = "/" ...

When changed it to

@RequestMapping(path = "/1" ...

Future completion suddenly become working.

P.S. I had broken all my mind before found that the problem actually in the mapping. May helps for someone O:-)

Cherry
  • 31,309
  • 66
  • 224
  • 364