Generic Error page Angular JS + Spring MVC + Controller Advice - spring

similar or related question to this post.
I have written the multiple service calls using angular JS. psudo code here
$http.get('name').success(function(response){
$scope.name= response;
$log.info($scope.rate);
}).error(function() {
});
Now I would like to route to single error page let say error.html for any exception occurs
how would I route to error.html page in Angular JS instead of touching the hundreds of service calls.
I know I would have written/route in the error function below , but I DO NOT want to repeat in reset of my application or hundreds of service calls.
what is the alternate way. please respond
$http.get('indexrates').success(function(response){
$scope.rates= response;
$log.info($scope.rates);
}).error(function() {
$state.go('error');
});

Reference : https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
#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;
}
}

Related

How to apply #ControllerAdvice from a non-controller?

Is there a way in which we can generate the JSON response from within the code that an API endpoint would show when a controller is called.
I basically want the application to call one of its own controllers and generate the response as a JSON string but not by making an HTTP call.
Calling the controller method and applying an objectmapper on it gives back the results just fine, but when there are exceptions it throws it through. However, I want it to generate the error response that would have generated from #ControllerAdvice exception handlers.
Is it possible to apply the exception handlers defined in #ControllerAdvice to an exception caught in a variable from within the application (Not by making an HTTP call)?
I am building a bulk api so that instead of the user calling an api multiple times, they can just put a list of payloads to this new bulk api, and internally I want to save the responses of each subrequest within the bulk api's db entity itself, and for that I need the exact json responses for each subrequest as if the original api was called.
I can do an exception handling separately for this bulk api code but then that would duplicate the code I already have in my controller advice.
One solution I have come up with is given below. However, if I use it I'll have to remove all my current exception handlers and just use one single exception handler accepting Exception.
Controller Advice:
#ExceptionHandler(ConversionFailedException.class)
public ResponseEntity<ErrorResponse> handleConversionFailedException(final ConversionFailedException e) {
return buildResponseEntity(HttpStatus.BAD_REQUEST, e);
}
#ExceptionHandler(value = {ActionNotFoundException.class})
public ResponseEntity<ErrorResponse> handleActionNotFoundException(ActionNotFoundException e) {
return buildResponseEntity(HttpStatus.NOT_FOUND, e);
}
// someone just added it
#ExceptionHandler(value = {NewRuntimeException.class})
public ResponseEntity<ErrorResponse> handleNewRuntimeException(NewRuntimeException e) {
return buildResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR, e);
}
Bulk API code:
try {
}catch(ConversionFailedException e){
return buildResponseEntity(HttpStatus.BAD_REQUEST, e);
}catch(ActionNotFoundException e){
return buildResponseEntity(HttpStatus.NOT_FOUND, e);
}
// they forgot to add it here
My current solution:
Controller Advice:
#ExceptionHandler(Exception.class)
public ResponseEntity<String> handleAllExceptions(final Exception e) {
return ExceptionHandlerUtil.funcA(e);
}
ExceptionHandlerUtil class (New):
private ResponseEntity<ErrorResponse> funcA(Exception e) {
if (e instanceof ConversionFailedException) {
return buildResponseEntity(HttpStatus.BAD_REQUEST, e);
}
else if (e instanceof ActionNotFoundException) {
return buildResponseEntity(HttpStatus.NOT_FOUND, e);
}
// they can add any new exception here, and both the parts of the code will be able to handle it
}
Bulk API code:
try {
}catch(Exception e){
return ExceptionHandlerUtil.funcA(e);
}

Does spring boot automatically take care of error handling in the context of JpaRepository methods?

When using Spring Boot, I am unsure if error handling is already being taken care of by the Spring Framework, or if I have to implement it. For example, consider a controller method, which handles a DELETE request:
#DeleteMapping("/{studentId}")
public ResponseEntity<Long> deleteProfilePicture(#PathVariable Long studentId) {
return ResponseEntity.ok(profilePictureService.deleteprofilePictureByStudentId(studentId));
}
Is this fine, or should I instead wrap it inside a try-catch block:
#DeleteMapping("/{studentId}")
public ResponseEntity<Long> deleteProfilePicture(#PathVariable Long studentId) throws Exception {
try {
profilePictureService.deleteProfilePictureByStudentId(studentId));
} catch (DataAccessException e) {
throw new Exception("cannot delete profile picture of student: " + studentId);
}
}
Also: If I let my method deleteProfilePicture throw this Exception, who is handling the Exception? This must somehow be taken care of by Spring Boot, since it is possible to implement it without yielding any errors. Anyhow, what is the correct way of error handling in this scenario?
Spring Boot will turn the exception into an error response to the caller of the REST API. This does not mean that you shouldn't implement your own error handling logic, which you definitely should. As an example, you could use #ControllerAdvice to have a global exception handling for your application. Something along the following lines:
#ControllerAdvice
#Slf4j
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler(value = {Exception.class})
public ResponseEntity<Object> handleGenericExceptions(Exception exception, WebRequest webRequest) {
log.error("Handling: ", exception);
HttpStatus errorCode = HttpStatus.INTERNAL_SERVER_ERROR;
return this.handleExceptionInternal(exception, new ErrorInfo(errorCode.value(), "Unexpected Internal Server Error"), new HttpHeaders(), errorCode, webRequest);
}
}
You can read more about error handling in Spring Boot at https://www.baeldung.com/exception-handling-for-rest-with-spring.

Get Stack trace from HttpServletRequest in spring boot

I'm currently running a spring boot application.
I am putting this webpage live for multiple people to use. However, this is the first time launching it and I'm unsure if I've worked out all the bugs so I'm trying to find a way to alert myself when something happens.
I have created a custom error controller in Spring. I want this to display a custom error page that just simply tells the user that something is wrong and that we've been made aware of it. This part is working already.
Also with that, I want it to send me an email with the stack trace information. I would love the same page that the default error controller shows, to be sent to me via email. I'm using AWS SES.
Here's my code sample.
#GetMapping("/error")
public String handleError(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status != null) {
int statusCode = Integer.parseInt(status.toString());
if(statusCode == HttpStatus.NOT_FOUND.value()) {
return "404";
}
}
sesSender.sendErrorEmail("strack trace error");
return "error";
}
I found the following question provided 5 years ago Spring Boot Custom Error Page Stack Trace
I'm hoping that since then, they've allowed this functionality.
If you are using Spring Boot you can use this bean and this method ExceptionUtils.getStackTrace(). You will need to import the commons.lang dependency. The method from ExceptionUtils will get you the stack trace you are looking for to send to your email. But this will only work for Serverside Errors. If you want emails sent with a stack trace for front end errors you will need to create your own Dispatcher Servlet and handle it in the DoService Filter
#Bean
HandlerExceptionResolver errorHandler() {
return (request, response, handler, ex) -> {
Logger logger = LoggerFactory.getLogger(DispatcherServlet.class);
ModelAndView model = new ModelAndView("error/error");
model.addObject("exceptionType", ex);
model.addObject("handlerMethod", handler);
logger.error(ExceptionUtils.getMessage(ex));
System.out.println("" +
"\n" + ExceptionUtils.getStackTrace(ex));
try {
Utility.sendStackTraceToDeveloper(ex, request, javaMailSender);
} catch (MessagingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return model;
};
}

ajax Spring liferay

I'm using an architetture that has: AJAX, Liferay 6.2, Spring 4.3.18.RELEASE;
From AJAX i make a call to the backend, that pass throu liferay and reach my controller;
Now, I want to generete an exception in the controller in order to reach the the failure of the ajax call; I've googled a lot but I wasn't able to find the solution.
my controller:
#Controller("movemementCon")
#RequestMapping("VIEW")
public class movemementCon {
#ResourceMapping("getDis")
#ResponseBody
public ResponseEntity<BenException> getImp(ResourceRequest request, ResourceResponse response, Model model) throws BenException{
return new ResponseEntity<BenException>(HttpStatus.NOT_ACCEPTABLE);
}
But when i reach the code in javascript (the AJAX call) it ignored definitively that I've throw an exception;
The desidered behaviur is that i force to go to the error statment in the AJAX call.
In web browser you can't catch java errors on client side, because client doesn't know anything about backend. You have to catch that error in spring controller method and then return ResponseEntity with some status, response body, custom response headers, so you can notify client that something went wrong and handle it correctly there.
#Controller("movemementCon")
#RequestMapping("VIEW")
public class movemementCon {
#ResourceMapping("getDis")
#ResponseBody
public ResponseEntity<SomeClass> getImp(ResourceRequest request, ResourceResponse response, Model model) {
try{
deleteFromDatabase(model);
} catch(BenException e) {
return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE);
}
return new ResponseEntity<>(HttpStatus.OK);
}
}
Then in your JS read the status and execute right action.

Prevent spring errors on webpage

I am using spring MVC 3.
I validate various users input and show errors as applicable.
But this often to show the spring errors like org.springframework.core.convert.ConversionFailedException etc being shown on UI. How can i prevent the output of these errors on webpage ?
Note:
I understand that for topic starter my answer may be no longer
relevant. But it can be useful for those who have visited this page to
search for solutions to similar problems.
Answer:
In order to prevent the output of errors on web page, you may handle them. There are several types of error handling, that you may use for this in Spring MVC 3.x and above:
Controller-based exception handling
Global exception handling
Other methods, that are bit more complicated
Controller-based exception handling
You can add an #ExceptionHandler annotation on methods inside a controller. Such methods will function as error handlers for exceptions thrown from methods annotated as #RequestMapping in the same controller.
#ExceptionHandler(Exception.class)
public ModelAndView handleError(HttpServletRequest req, Exception e) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("exception", e);
modelAndView.addObject("url", req.getRequestURL());
modelAndView.setViewName("error");
return modelAndView;
}
Global exception handling
A controller advice allows you to apply exception handling across the whole application, not just to an individual controller. In other words, handling will apply to exceptions thrown from any controller.
#ControllerAdvice
class GlobalControllerExceptionHandler {
public static final String DEFAULT_ERROR_VIEW = "error";
#ExceptionHandler(Exception.class)
public void handleError(HttpServletRequest req, Exception e) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("exception", e);
modelAndView.addObject("url", req.getRequestURL());
modelAndView.setViewName(DEFAULT_ERROR_VIEW);
return modelAndView;
}
}
For more info:
Exception Handling in Spring MVC

Resources