Dynamic message for custom exception annotated as ResponseStatus - spring

I'm trying to provide dynamic message for my custom Exception like in code snippet below:
#ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Entity not found")
public class EntityNotFoundException extends RuntimeException {
public EntityNotFoundException(String msg) {
super(msg);
}
}
But always when I throw it like shown below:
throw new EntityNotFoundException("User entity not found");
in the browser, I get the message "Entity not found" instead of "User entity not found".
How to achieve this?

I was stuck on this, But I just removed the reason side of the #ResponseStatus and It works, so your code should be like this:
#ResponseStatus(value = HttpStatus.NOT_FOUND)
public class EntityNotFoundException extends RuntimeException {
public EntityNotFoundException(String msg) {
super(msg);
}
}
And now you can set custom message by the constructor

Related

Override exception message of SendFailedException getInvalidAddresses()

I use javax.mail dependency spring-boot-starter-mail and i want to override the error message that user get when they provide wrong email or email with domain that dose not exist. How can i override the error message of javax.mail.SendFailedException from the method getInvalidAddresses?
I want to override and pass the user a nice error message. I have my own GlobalExceptionClass which i use for all diffrent Exceptions inside my app:
#ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler({SendFailedException.class})
private ResponseEntity<MessageResponse> handleSendFailException(SendFailedException sfe){
if (sfe.getInvalidAddresses() != null) {
System.out.println("INVALID ADRESSS");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new
MessageResponse("adress is inavlid"));
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new
MessageResponse("invalidadress"));
}
}
My Controller Class
#PostMapping("/offers")
public ResponseEntity<MessageResponse> mailOffer(#Valid #RequestBody OffersDto offersDto) throws
MessagingException {
String succMessage = "success.";
offersService.addOffer(offersDto);
offersService.sendMail(offersDto);
return ResponseEntity.ok(new MessageResponse(succMessage));
}
Services class
public Offers sendMail(OffersDto offersDto) throws MessagingException {
///messaging methods, attributes
}
i just replicated this exception handling the same as for other methods, but above code dose not overrides the exception message
You have to try/catch checked exception and in catch or finally block throw new unchecked custom exception, after that handle your Custom exception(you must add attributes of MessagingException to your custom exception for checking statements)
#ExceptionHandler({CustomException.class})

Returning proper value from #AfterThrowing

I am new to String, SpringBoot.
Can we suppress thrown exception in a method annotated with #AfterThrowing?
I mean when an exception is thrown, it will suppress that and will return a default value on behalf of the invoking method?
Say, I have a controller -
#RestController
public class MyRestController implements IRestController{
#Override
#GetMapping("hello-throw")
public String mustThrowException(#RequestParam(value = "name")final String name) throws RuntimeException {
System.out.println("---> mustThrowException");
if("Bakasur".equals(name)) {
throw new RuntimeException("You are not welcome here!");
}
return name + " : Welcome to the club!!!";
}
}
I have created a #AspectJ, as follows -
#Aspect
#Component
public class MyAspect {
#Pointcut("execution(* com.crsardar.handson.java.springboot.controller.IRestController.*(..))")
public void executionPointcut(){
}
#AfterThrowing(pointcut="executionPointcut()",
throwing="th")
public String afterThrowing(JoinPoint joinPoint, Throwable th){
System.out.println("\n\n\tMyAspect : afterThrowing \n\n");
return "Exception handeled on behalf of you!";
}
}
If I run this & hit a ULR like - http://localhost:8080/hello-throw?name=Bakasur
I will get RuntimeException, but, I want to return a default message like - Exception handeled on behalf of you!, can we do it using #AfterThrowing?
I know it can be done using #Around, but around will be called on every hit of the url, that I do not want
What you want to do is Exception Handling on the controller. You don't need to build it yourself, Spring already supports you with some annotations like #ExceptionHandler and #ControllerAdvice. Best would be to follow this example: https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc#using-controlleradvice-classes
#ControllerAdvice
class GlobalControllerExceptionHandler {
#ResponseStatus(HttpStatus.CONFLICT) // 409
#ExceptionHandler(DataIntegrityViolationException.class)
public void handleConflict() {
// Nothing to do
}
}
#ControllerAdvice
class GlobalDefaultExceptionHandler {
public static final String DEFAULT_ERROR_VIEW = "error";
#ExceptionHandler(value = Exception.class)
public ModelAndView
defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
// If the exception is annotated with #ResponseStatus rethrow it and let
// the framework handle it - like the OrderNotFoundException example
// at the start of this post.
// AnnotationUtils is a Spring Framework utility class.
if (AnnotationUtils.findAnnotation
(e.getClass(), ResponseStatus.class) != null)
throw e;
// Otherwise setup and send the user to a default error-view.
ModelAndView mav = new ModelAndView();
mav.addObject("exception", e);
mav.addObject("url", req.getRequestURL());
mav.setViewName(DEFAULT_ERROR_VIEW);
return mav;
}
}
You should use the fully qualified name of the class before method's name when you're referring to a pointcut. So, you should change #AfterThrowing something like this.
#AfterThrowing(pointcut="packageName.MyAspect.executionPointcut()",
throwing="th")
Please note that packageName is full package name of MyAspect.

Spring Boot Exception(Error) Handling for RESTful Services

I have the following RESTful Services method :
#PostMapping("/ajouterNewField")
public String ajouterField(#Valid #ModelAttribute("field") Fields field, Model model) throws IOException {
fieldDao.save(field);
// SOME CODE
return displayListeChamps( model);
}
The method is working fine and my question is how to handle any error (database not connected ...) or every issue that can happen durring the execution of this RESTful Services method.
You can use #ControllerAdvice
Refer to the code below
#ControllerAdvice
public String NyExceptionHandlerAdvice {
private final Logger logger = ...;
#ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
#ExceptionHandler({MyRunTimeException.class})
public void handleMyRunTimeException(Exception e) {
logger.error("Exception : ", e);
}
return MY_ERROR_STRING;
}
Best Practice is:
You can have your code throw RunTimeExceptions and handle all of them together or separately in handler methods similar to handleMyRunTimeException above.
You can decide what status code your request should return upon exception.
Basically you'll have to a sort of exception handler for any kind of exception your method might throw:
public class FooController{
// ...
#ExceptionHandler({ CustomException1.class, CustomException2.class })
public void handleException() {
//
}
}
Here's a nice article about that: https://www.baeldung.com/exception-handling-for-rest-with-spring

Spring Boot. Different errors hanldilng for #Ccontroller and #RestController in one app

I have normal #Controller and #RestController in one App.
How it possible to handle erros in Json for REST, and redirect to error page for normal #Controller?
You can make use of the Spring Annotation #ExceptionHandler in your controller and throw Exceptions in your controller logic. For an short example I will use Java's RuntimeException. You could define your own exception and throw them
// your controller classes
#Controller
public class MyController {
#ExceptionHanlder(RuntimeException.class)
public String errorInController(){
// for your custom page
return "yourDefineErrorTemplatePage";
// if you want to redirect to the default spring page
// return "redirect:/error";
}
#RequestMapping("yourFirstEndpoint")
public String getPage(){
if(yourLogicHere){
throw new RuntimeException("Display error page");
}
return "myPage";
}
}
Your #RestController could look like the following:
#RestController
public class RestControllerClass{
#ExceptionHandler(RuntimeException.class)
public ResponseEntity<Error> errorOccured(){
// you can return just a String or define your own 'error object'
Error error = new Error("Some error occured");
return new ResponseEntity<Error>(error, Http.Status.NOT_FOUND);
}
#RequestMapping("yourSecondEndpoint")
public ResponseEntity<YourEntity> getPage(){
// the entity you want do return as json
YourEntity yourEntity = new YourEntity();
if(yourLogicHere){
throw new RuntimeException("Display error page");
}
return new ResponseEntity<YourEntity>(yourEntity, HttpStatus.OK);
}
}
Example for the Error Object:
public class Error{
private String errorMessage;
public Error(String errorMessage){
this.errorMessage = errorMessage;
}
}
I hope this small example can solve your Problem.
For more details visit: https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc

Map UnsupportedMediaTypeException using ExceptionMapper

Is there a place where it is clearly documented that I cannot map UnsupportedMediaTypeException (because it's a rest easy exception and not custom application exception) using the javax.ws.rs.ext.ExceptionMapper?
I want to prove that to my client. Or another thing I would like to do is map this exception to a Response that can be fetched at the client to show the error. Right now when this exception is thrown it provides no information to the client as the application ends abruptly.
Any help would be appreciated.
Thanks
You can map this exception. Why not? Do you get an error?
This code should do the job
#Provider
public class EJBExceptionMapper implements ExceptionMapper<org.jboss.resteasy.spi.UnsupportedMediaTypeException>{
Response toResponse(org.jboss.resteasy.spi.UnsupportedMediaTypeException exception) {
return Response.status(415).build();
}
}
Don't forget to declare that provider in Spring configuration file.
If you want to provide more information to the client create class
#XmlRootElement
public class Error{
private String message;
//getter and setter for message field
}
and then you can
#Provider
public class EJBExceptionMapper implements ExceptionMapper<org.jboss.resteasy.spi.UnsupportedMediaTypeException>{
Response toResponse(org.jboss.resteasy.spi.UnsupportedMediaTypeException exception) {
Error error = new Error();
error.setMessage("Whatever message you want to send to user");
return Response.entity(error).status(415).build();
}
}
If you don't want to use Error entity simply pass a string to Response.entity() call.
If you want to catch whatever is thrown in you application create generic exception mapper:
#Provider
public class ThrowableMapper implements ExceptionMapper<Throwable> {
public Response toResponse(Throwable t) {
ErrorDTO errorDTO = new ErrorDTO(code);
return Response.status(500).build();
}
}

Resources