ConflictException thrown not being catched by ConflictExceptionMapper - java

I'm new to jersey, and I want to throw a ConflictException(Custom) in my Service,
and catch it to give a response.
Below is my code..
public class ConflictException extends ClientErrorException {
public ConflictException() {
super(Response.Status.CONFLICT); // 409
}
}
Then I want to use a ExceptionMapper to send a proper Response.
#Provider
public class ConflictExceptionMapper implements ExceptionMapper<ConflictException> {
#Override
public Response toResponse(ConflictException exception) {
return Response.status(Response.Status.CONFLICT).entity(new ResponseMessage( Collections.emptyList(), OperationResultStatus.Conflict,
exception.getMessage())).build();
}
}
Somehow this Mapper is not being triggered.
What am I doing wrong....
Update!!! Snipped of my main class included.
final ResourceConfig rc = new ResourceConfig().packages(packages)
// Now you can expect validation errors to be sent to the client.
.property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true)
// #ValidateOnExecution annotations on subclasses won't cause errors.
.property(ServerProperties.BV_DISABLE_VALIDATE_ON_EXECUTABLE_OVERRIDE_CHECK, true)
// Further configuration of ResourceConfig.
//.property(ServerProperties.PROCESSING_RESPONSE_ERRORS_ENABLED, true)
.register(new ClassBinder())
.register(json)
.register(ConstraintViolationExceptionMapper.class)
.register(ConflictExceptionMapper.class);

Related

Issue with ExceptionMapper in Jersey

I have two classes that implements ExceptionMapper interface.
IllegalArgumentExceptionMapper to handle IllegalArgumentException:
#Slf4j
#Provider
public class IllegalArgumentExceptionMapper implements ExceptionMapper<IllegalArgumentException> {
#Override
public Response toResponse(IllegalArgumentException exception) {
log.info("IllegalArgumentExceptionMapper!");
Error error =
Error.builder()
.statusCode(HttpStatus.SC_BAD_REQUEST)
.statusDescription(exception.getLocalizedMessage())
.errorMessage(exception.getMessage())
.build();
return Response.status(Response.Status.BAD_REQUEST)
.entity(error)
.type(MediaType.APPLICATION_JSON)
.build();
}
}
GenericExceptionMapper is an ExceptionMapper that I want to use as the default ExceptionMapper when an exception is not mapped to any of my other specific ExceptionMapper classes. Here it is:
#Slf4j
#Provider
public class GenericExceptionMapper implements ExceptionMapper<Throwable> {
#Override
public Response toResponse(Throwable ex) {
log.info("GenericExceptionMapper!");
Response.StatusType type = getStatusType(ex);
Error error = Error.builder()
.statusCode(type.getStatusCode())
.statusDescription(type.getReasonPhrase())
.errorMessage(ex.getLocalizedMessage())
.build();
return Response.status(error.getStatusCode())
.entity(error)
.type(MediaType.APPLICATION_JSON)
.build();
}
private Response.StatusType getStatusType(Throwable ex) {
if (ex instanceof WebApplicationException) {
return((WebApplicationException)ex).getResponse().getStatusInfo();
} else {
return Response.Status.INTERNAL_SERVER_ERROR;
}
}
}
However, when I try to throw an IllegalArgumentException, with:
throw new IllegalArgumentException("Just a normal IllegalArgumentException!");
I see that GenericExceptionMapper instead of IllegalArgumentExceptionMapper is being used.(I see "GenericExceptionMapper!" in the log).
Any idea what went wrong?
Some observations
If I delete GenericExceptionMapper, IllegalArgumentExceptionMapper is still not being called. So I think there is an issue for my IllegalArgumentExceptionMapper implementation.
If I modify IllegalArgumentExceptionMapper with public class IllegalArgumentExceptionMapper implements ExceptionMapper<RuntimeException> and throw new RuntimeException, then I see that IllegalArgumentExceptionMapper is being used.

Exception Handling in JAX-RS

java 8, spring, rest
I am trying to capture the Response that comes from exception mapper, and do something with it in the caller which throws the exception. Thanks.
#Provider
public class CustomerExceptionHandler implements ExceptionMapper<CustomerException>
{
#Override
public Response toResponse(CustomerException exception)
{
return Response.status(Status.BAD_REQUEST).entity(CustomerException.getMessage()).build();
}
}
public class CustomerException extends Exception implements Serializable
{
private static final long serialVersionUID = 1L;
public CustomerException() {
super();
}
public CustomerException(String msg) {
super(msg);
}
public CustomerException(String msg, Exception e) {
super(msg, e);
}
}
public class ExceptionDemo{
public void getExceptionResponse(){
//do something
throw new CustomerException("Something is wrong");// CustomerExceptionHandler is going to return me a Response, how can I capture the response here?
//capture response and do something with it
}
}
I'm not sure ExceptionMappers work in the way you think they do.
When some code in the endpoint throws an exception, and this exception percolates all the way out of the endpoint and back into the container itself (Spring in this case), then the registered ExceptionMappers are consulted to see if they match the thrown exception, and the relevant one's public Response toResponse(T e) {} method is called to transform it into a Response.
The ExceptionMapper doen't get called as part of your endpoint code, and you won't be able to take action based on its resultant Response because it hasn't yet been called. You just need to throw the exception out of the endpoint.

#Valid is not working with jax rs and springboot

I am getting NotFoundException while trying to implement custom exception handling in spring-boot rest application.
The code was working fine when I was using MVC (using #ControllerAdvice) annotations but not sure when I am sending a data which is violating the constraint mentioned in entity(pojo class) it is throwing only NotFoundException (for all validation failure) but not the MethodViolationException or ConstraintViolationException
I am not able to send the message for that particular violation.
Not sure where I am making this mistake. Please help
Code:
#POST
#Path("/customers/add")
public Response addCustomer(#Valid customer cust)
{
// Rest of the code
}
POJO:
#Entity
#Table(name="cust")
public class Customer
{
#NotNull
#Size(min=1,max=50,message ="invalid name")
String name;
}
Exception Handler:
#Provider
public class CustomHandler implements ExceptionMapper<Exception>
{
public Response toResponse(Exception ex)
{
if(ex instanceOf ConstraintViolationException)
{
Do something
}
}
**UPDATE 1
If I enable the send_error_in_response i am getting the message for this but not sure why my custom exception handler is not able to catch this exception and only throwing NotFoundException
Try Handling Exception Using:
#ControllerAdvice
#RestController
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler(StudentNotFoundException)
public final ResponseEntity<ErrorDetails> handleUserNotFoundException(StudentNotFoundException ex, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(),
request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}
For more information you might want to refer http://www.springboottutorial.com/spring-boot-validation-for-rest-services

Dropwizard custom ExceptionMapper for javax.validation.ConstraintViolationException

I'm using Dropwizard and would like to create a custom ExceptionMapper to handle javax.validation.ConstraintViolationException. I've created a customer mapper:
#Provider
public class MyExceptionMapper implements ExceptionMapper<Exception> {
public Response toResponse(Exception exception) {
return Response.status(500)
.entity(exception.getMessage())
.type(MediaType.TEXT_PLAIN)
.build();
}
}
and configured it in my Dropwizard app:
#Override
public void run(HelloWorldConfiguration configuration, Environment environment) {
ServerFactory serverFactory = configuration.getServerFactory();
if (serverFactory instanceof AbstractServerFactory) {
((AbstractServerFactory) serverFactory).setRegisterDefaultExceptionMappers(false);
}
environment.jersey().register(new MyExceptionMapper());
}
When a resource/controller throws a javax.validation.ConstraintViolationException exception it's not handled by my custom mapper, instead it goes through org.glassfish.jersey.server.validation.internal.ValidationExceptionMapper which returns a 400 which is not what I want.
Is it possible to override/remove Jersey's mapper? I would have thought setting setRegisterDefaultExceptionMappers(false); would do the trick but it seems that it doesn't.

Hystrix - how to register ExceptionMapper

My Hystrix/Feign app makes calls to other web services.
I would like to propagate error codes/messages from these web services.
I implemented ErrorDecoder, which correctly decodes exceptions returned and rethrow them.
Unfortunately these Exceptions are wrapped by HystrixRuntimeException and the JSON returned in not what I want (generic error message, always 500 http status).
Most likely I need an ExceptionMapper, I created one like this:
#Provider
public class GlobalExceptionHandler implements
ExceptionMapper<Throwable> {
#Override
public Response toResponse(Throwable e) {
System.out.println("ABCD 1");
if(e instanceof HystrixRuntimeException){
System.out.println("ABCD 2");
if(e.getCause() != null && e.getCause() instanceof HttpStatusCodeException)
{
System.out.println("ABCD 3");
HttpStatusCodeException exc = (HttpStatusCodeException)e.getCause();
return Response.status(exc.getStatusCode().value())
.entity(exc.getMessage())
.type(MediaType.APPLICATION_JSON).build();
}
}
return Response.status(500).entity("Internal server error").build();
}
}
Unfortunately this code is not being picked-up by my application (debug statements are not visible in logs).
How could I register it with my Application?
I couldn't make use of an ExceptionMapper.
I solved this problem using ResponseEntityExceptionHandler.
Here is the code:
#EnableWebMvc
#ControllerAdvice
public class ServiceExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler(HystrixRuntimeException.class)
#ResponseBody
ResponseEntity<String> handleControllerException(HttpServletRequest req, Throwable ex) {
if(ex instanceof HystrixRuntimeException) {
HttpStatusCodeException exc = (HttpStatusCodeException)ex.getCause();
return new ResponseEntity<>(exc.getResponseBodyAsString(), exc.getStatusCode());
}
return new ResponseEntity<String>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}

Categories