DamienMiheev
DamienMiheev

Reputation: 1047

How to change response statuc code when using CompletableFuture.exceptionaly() in Spring?

I have a simple controller:

@RestController
public class SimpleController() {

    public String get() {
        if (System.nanoTime() % 2 == 0)
            throw new IllegalArgumentException("oops");

        return "ok"
    }
}

Controller can throw simple exception, so i wrote controller advisor for it handling:

@ExceptionHandler(IllegalArgumentException.class)
@ResponseBody
public ResponseEntity<String> rejection(Rejection ex) {
    return new ResponseEntity<>("bad", HttpStatus.CONFLICT);
}

Now i want to make get method async. But i don't know the best way for handling exception.

I tried:

    public CompletableFuture<String> get() {
        CompletableFuture.supplyAsync(
            () -> {
                if (System.nanoTime() % 2 == 0)
                    throw new IllegalArgumentException("oops");

                return "ok";
            }).exceptionally(thr -> {
                //what should i do?
                if (thr instanceof IllegalArgumentException)
                    throw ((IllegalArgumentException) t);

                if (thr.getCause() instanceof IllegalArgumentException)
                    throw ((IllegalArgumentException) t.getCause());

                return null;
            }
    }

But controller advisor still does not catch the exception.

Also i tried to return ResponseEntity("message", HttpStatuc.CONFLICT); in exceptionally block. But in tests i still have MvcResult.getResponse().getStatus() == 200.

Any other idea? Maybe it's a wrong way at all?

UPDATE I don't know why, but it don't catch exceptions:

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    return new AsyncUncaughtExceptionHandler() {
        @Override
        public void handleUncaughtException(Throwable ex, Method method, Object... params) {
            System.out.println();
        }
    };

And even if it work, how to set http status to response?

Upvotes: 1

Views: 1182

Answers (2)

DamienMiheev
DamienMiheev

Reputation: 1047

Sorry guys, the problem not in code. I just wrote bad tests. Here the link for explaining:

https://sdqali.in/blog/2015/11/24/testing-async-responses-using-mockmvc/

Just use:

MvcResult result = mockMvc.perform(...).andReturn();
result = mockMvc.perform(asyncDispatch(result)).andReturn();

before you check the status or result response.

Upvotes: 0

Andrey Badaev
Andrey Badaev

Reputation: 96

Try to return a ResponseEntity instance:

return new ResponseEntity<>("bad", HttpStatus.CONFLICT);

out of exceptionally method.

Upvotes: 0

Related Questions