@Component public class ProductHandler { @Autowired private ProductService productService; static Mono notFound = ServerResponse.notFound().build(); private final Validator validator = new ProductValidator(); public Mono getAllProducts(ServerRequest serverRequest) { return ServerResponse.ok() .contentType(MediaType.APPLICATION_JSON) .body(productService.getAllProducts(), Product.class); } public Mono getProduct(ServerRequest serverRequest) { String id = serverRequest.pathVariable("id"); return productService.getProduct(id) .flatMap(p -> ServerResponse.ok() .contentType(MediaType.APPLICATION_JSON) .body(Mono.just(p), Product.class)) .switchIfEmpty(ServerResponse.status(HttpStatus.NOT_FOUND) .contentType(MediaType.APPLICATION_JSON) .body(Mono.just(new ErrorResponse(404, "Product not found")), ErrorResponse.class)); } public Mono createProduct(ServerRequest serverRequest) { Mono productToSave = serverRequest.bodyToMono(Product.class) .doOnNext(this::validate); return productToSave.flatMap(product -> ServerResponse.status(HttpStatus.CREATED) .contentType(MediaType.APPLICATION_JSON) .body(productService.save(product), Product.class)); } private void validate(Product product) { Errors errors = new BeanPropertyBindingResult(product, "product"); validator.validate(product, errors); if (errors.hasErrors()) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, errors.getAllErrors().toString()); } } public Mono deleteProduct(ServerRequest serverRequest) { String id = serverRequest.pathVariable("id"); return productService.deleteProduct(id) .flatMap(product -> ServerResponse.noContent().build()); } public Mono updateProduct(ServerRequest serverRequest) { return productService.update(serverRequest.bodyToMono(Product.class)).flatMap(product -> ServerResponse.ok() .contentType(MediaType.APPLICATION_JSON) .body(fromObject(product))) .switchIfEmpty(notFound); } }