How can we handle exceptions globally when using reactive programming in Spring boot rest controller?
I would assume that @ControllerAdvice
will not work because I have tried this and it was unsuccessful.
My other try is currently this option, using custom attributes:
@Component
public class OsvcErrorAttributes extends DefaultErrorAttributes {
public OsvcErrorAttributes() {
super(true);
}
@Override
public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
return assembleError(request);
}
private Map<String, Object> assembleError(ServerRequest request) {
ServerException serverException = (ServerException)getError(request);
Map<String, Object> errorAttributes = new HashMap<>();
errorAttributes.put("message", serverException.getMessage());
errorAttributes.put("errors", serverException.getErrorMap());
return errorAttributes;
}
}
and WebExceptionHandler like this:
@Component
@Order(-2)
public class OsvcErrorHandler extends AbstractErrorWebExceptionHandler {
public OsvcErrorHandler(ErrorAttributes errorAttributes,
ResourceProperties resourceProperties,
ApplicationContext applicationContext) {
super(errorAttributes, resourceProperties, applicationContext);
// TODO: 25.06.2019 temporary workaround
ServerCodecConfigurer serverCodecConfigurer = new DefaultServerCodecConfigurer();
setMessageWriters(serverCodecConfigurer.getWriters());
setMessageReaders(serverCodecConfigurer.getReaders());
}
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
}
private Mono<ServerResponse> renderErrorResponse(ServerRequest serverRequest) {
final Map<String, Object> errorAttributes = getErrorAttributes(serverRequest, true);
return ServerResponse.status(HttpStatus.BAD_REQUEST)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.body(BodyInserters.fromObject(errorAttributes));
}
}
Code that generates an error:
@Data
@Service
public class ContactService {
private final ContactRepository contactRepository;
public Mono<Business> saveNewContact(Business business) {
return contactRepository.save(business)
.onErrorMap(throwable ->
ServerException.create(throwable.getMessage())
.persistError("ico", business.getIco(), "ICO is probably duplicate"));
}
}
Problem is that this does not work either. I did follow this tutorial and I cannot see if I am wrong with something or not.
@Data
in yourContactService
. In lombok that means that there is a getter and setter provided, but theContactRepository
needs to be@Autowired
– Wilds