Skip to content
Advertisement

Spring Webflux – Proper way to throw checked custom exception (not RuntimeException)

May I ask what is the proper way to throw checked custom exception in Spring webflux please? I would like to insist, it is about checked custom exception, like MyException.java, not something like RuntimeException, and it is about throwing exception, not handling exception.

I tried the following :

@Controller
@SpringBootApplication
public class QuestionHowToThrowException {

    public static void main(String[] args) {
        SpringApplication.run(QuestionHowToThrowException.class);
    }

    @PostMapping(path = "/question", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public Mono<ResponseEntity<QuestionResponse>> question(@RequestBody QuestionRequest questionRequest) {
        Mono<FirstStep> firstStepMono = WebClient.create().post().uri("http://firstWebService:8111/getFirstStep")
                .body(questionRequest.getThing(), String.class).retrieve().bodyToMono(FirstStep.class);
        Mono<SecondStep> secondStepMono = firstStepMono.map(oneFirstStep -> getSecondStepFromFirstStepAfterCheck(oneFirstStep));
        return secondStepMono.map(oneSecondStep -> ResponseEntity.ok(new QuestionResponse(oneSecondStep.getSecondThing())));
    }

    private SecondStep getSecondStepFromFirstStepAfterCheck(FirstStep firstStep) throws MyException {
        if (firstStep.getThingNeedsToCheckCanThrowException().equals("exception")) {
            throw new MyException("exception");
        } else {
            return new SecondStep(firstStep.getThingNeedsToCheckCanThrowException() + "good");
        }
    }

    public class QuestionRequest {
        private String thing;
        public String getThing() {
            return thing;
        }
    }

    public class QuestionResponse {
        private String response;
        public QuestionResponse(String response) {
            this.response = response;
        }
    }

    public class FirstStep {
        private String thingNeedsToCheckCanThrowException;
        public String getThingNeedsToCheckCanThrowException() {
            return thingNeedsToCheckCanThrowException;
        }
    }

    public class SecondStep {
        private String secondThing;
        public SecondStep(String secondThing) {
            this.secondThing = secondThing;
        }
        public String getSecondThing() {
            return secondThing;
        }
    }

}


This is not possible, since there in an unhandled exception in getSecondStepFromFirstStepAfterCheck method.

If I throw and propagate, private SecondStep getSecondStepFromFirstStepAfterCheck(FirstStep firstStep) throws MyException the lambda caller method is not happy.

What is the cleanest and proper way to throw custom exception in webflux please?

Thank you

Advertisement

Answer

Reading through your sample code, it looks like you are trying to introduce some error handling with on your Mono.

You can create an unchecked exception by extending the RuntimeException class. If you want a checked exception that enforces handling, you can simply extend Exception.

public class MyException extends RuntimeException {
    public MyException(String msg) {
       super(s);
    }
}

The cleanest way to throw an exception with the Reactor project is really just to throw it. There are error handling functions that allow you to provide different flows to certain error cases.

The good news is you have several options that provides some flow control for error handling.

Project Reactor provides several of these methods on the Mono object.

doOnError(),onErrorContinue(),onErrorReturn(),onErrorStop(),onErrorMap()

I am not entirely sure what you are trying to achieve with the following sample code.

 return Mono.error(new MyException("exception"));
        } else {
 return Mono.just(new SecondStep(firstStep.getThingNeedsToCheckCanThrowException() + "good"));

But this looks like a good case for a onErrorMap() since it looks like you are trying to translate some exception here

return Mono.just(new SecondStep(firstStep.getThingNeedsToCheckCanThrowException() + "good")
   .onErrorMap(e -> "translated result");

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement