Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
258 views
in Technique[技术] by (71.8m points)

java - what is the right way to handle errors in spring-webflux

I've been doing some research using spring-webflux and I like to understand what should be the right way to handle errors using Router Functions.

I've created an small project to test a couple of scenarios, and I like to get feedback about it, and see what other people is doing.

So far what I doing is.

Giving the following routing function:

@Component
public class HelloRouter {
    @Bean
    RouterFunction<?> helloRouterFunction() {
        HelloHandler handler = new HelloHandler();
        ErrorHandler error = new ErrorHandler();

        return nest(path("/hello"),
                nest(accept(APPLICATION_JSON),
                        route(GET("/"), handler::defaultHello)
                                .andRoute(POST("/"), handler::postHello)
                                .andRoute(GET("/{name}"), handler::getHello)
                )).andOther(route(RequestPredicates.all(), error::notFound));
    }
}

I've do this on my handler

class HelloHandler {

    private ErrorHandler error;

    private static final String DEFAULT_VALUE = "world";

    HelloHandler() {
        error = new ErrorHandler();
    }

    private Mono<ServerResponse> getResponse(String value) {
        if (value.equals("")) {
            return Mono.error(new InvalidParametersException("bad parameters"));
        }
        return ServerResponse.ok().body(Mono.just(new HelloResponse(value)), HelloResponse.class);
    }

    Mono<ServerResponse> defaultHello(ServerRequest request) {
        return getResponse(DEFAULT_VALUE);
    }

    Mono<ServerResponse> getHello(ServerRequest request) {
        return getResponse(request.pathVariable("name"));
    }

    Mono<ServerResponse> postHello(ServerRequest request) {
        return request.bodyToMono(HelloRequest.class).flatMap(helloRequest -> getResponse(helloRequest.getName()))
                .onErrorResume(error::badRequest);
    }
}

Them my error handler do:

class ErrorHandler {

    private static Logger logger = LoggerFactory.getLogger(ErrorHandler.class);

    private static BiFunction<HttpStatus,String,Mono<ServerResponse>> response =
    (status,value)-> ServerResponse.status(status).body(Mono.just(new ErrorResponse(value)),
            ErrorResponse.class);

    Mono<ServerResponse> notFound(ServerRequest request){
        return response.apply(HttpStatus.NOT_FOUND, "not found");
    }

    Mono<ServerResponse> badRequest(Throwable error){
        logger.error("error raised", error);
        return response.apply(HttpStatus.BAD_REQUEST, error.getMessage());
    }
}

Here is the full sample repo:

https://github.com/LearningByExample/reactive-ms-example

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If you think, router functions are not the right place to handle exceptions, you throw HTTP Exceptions, that will result in the correct HTTP Error codes. For Spring-Boot (also webflux) this is:

  import org.springframework.http.HttpStatus;
  import org.springframework.web.server.ResponseStatusException;
  .
  .
  . 

  new ResponseStatusException(HttpStatus.NOT_FOUND,  "Collection not found");})

spring securities AccessDeniedException will be handled correctly, too (403/401 response codes).

If you have a microservice, and want to use REST for it, this can be a good option, since those http exceptions are quite close to business logic, and should be placed near the business logic in this case. And since in a microservice you shouldn't have to much businesslogic and exceptions, it shouldn't clutter your code, too... (but of course, it all depends).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.9k users

...