Я пишу сложное приложение в качестве эксперимента с Spring 5 Webflux.Я планирую использовать много методов в этом приложении.Я знаком со «старым стилем» @RestController, но сейчас я пишу функциональные конечные точки.Например, бэкэнд службы регистрации компаний. Я был похож на @ControllerAdvice в «старом мире».Но я не смог найти ничего похожего в качестве реактивного эквивалента.(Или что-нибудь, что сработало для меня.)
У меня очень простая настройка.Функция маршрутизации, реактивный репозиторий Cassandra, обработчик и тестовый класс.Операция репозитория может вызвать исключение IllegalArgumentException, и я хотел бы обработать его, возвращая HTTP Status BadRequest клиенту.Просто в качестве примера я способен это сделать.:-) Об исключении заботится класс обработчика.Вот мой код.
RouterConfig
@Slf4j
@Configuration
@EnableWebFlux
public class RouterConfig {
@Bean
public RouterFunction<ServerResponse> route(@Autowired CompanyHandler handler) {
return RouterFunctions.route()
.nest(path("/company"), bc -> bc
.GET("/{id}", handler::handleGetCompanyDataRequest)
.before(request -> {
log.info("Request={} has been received.", request.toString());
return request;
})
.after((request, response) -> {
log.info("Response={} has been sent.", response.toString());
return response;
}))
.build();
}
}
CompanyHandler
@Slf4j
@Component
public class CompanyHandler {
@Autowired
private ReactiveCompanyRepository repository;
// Handle get single company data request
public Mono<ServerResponse> handleGetCompanyDataRequest(ServerRequest request) {
//Some validation ges here
return repository.findById(Mono.just(uuid))
.flatMap(this::ok)
.onErrorResume(IllegalArgumentException.class, e -> ServerResponse.badRequest().build())
.switchIfEmpty(ServerResponse.notFound().build());
}
private Mono<ServerResponse> ok (Company c) {
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromPublisher(Mono.just(c), Company.class));
}
}
ReactiveCompanyRepository
@Component
public interface ReactiveCompanyRepository extends ReactiveCassandraRepository<Company, UUID>{
Mono<Company> findByName(String name);
Mono<Company> findByEmail(String email);
}
Моя проблема в том, что .onErrorResume (IllegalArgumentException.class, e -> ServerResponse.badRequest (). Build ()) никогда не вызывается и в тестовом примере:
@SuppressWarnings("unchecked")
@Test
public void testGetCompanyExceptionDuringFind() {
Mockito.when(repository.findById(Mockito.any(Mono.class))).thenThrow(new IllegalArgumentException("Hahaha"));
WebTestClient.bindToRouterFunction(routerConfig.route(companyHandler))
.build()
.get().uri("/company/2b851f10-356e-11e9-a847-0f89e1aa5554")
.accept(MediaType.APPLICATION_JSON_UTF8)
.exchange()
.expectStatus().isBadRequest()
.returnResult(Company.class)
.getResponseBody();
}
Я всегда получаю HttpStatus 500 вместо 400. Так что это не помогает. Любая помощь будет оценена!