spring boot application exception handler which don't have controller - spring-boot

My Spring boot app is standalone application which don't have controller. I am calling service layer from main method of spring boot application.
I have tried to use #ExceptionHandler #ControllerAdvice annotations in my class as below. but control never comes to My Exception Handler method
package com.test.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
#ControllerAdvice
public class MyExceptionHandler {
#ExceptionHandler(NullPointerException.class)
public void handleNullpointerExcetion() {
System.out.println("Handling Null pointer exception");
}
}
Tried with package name as well which i need to scan in #ControllerAdvice but it is not working
#ControllerAdvice("com.test.utility")
public class MyExceptionHandler {
#ExceptionHandler(NullPointerException.class)
public void handleNullpointerExcetion() {
System.out.println("Handling Null pointer exception");
}
}
Are we not able to handle exception at centralized place if i we don't have controller class which we annotate with #RestContoller or #Controller

I don't think so.
ControllerAdvice is only used whenever a controller would return an exception,
It is a layer that exists after your endpoint in the controller returns and before actually returning the response, to interject and globally handle the exception and is meant to be global only for controllers.
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html
since you don't have a controller, I'd imagine the ControllerAdvice will not help you there.
If you want a centralized error handling mechanism, you'd have to implement something similar to the controller advice yourself around your "Main" function, to which you can have unified exception handling responses.

Related

How can I redirect to a html file inside a exception?

I have a method that can execute a Exception, I dont now how to redirect to a web page inside templates. If it happen the exception
#ResponseStatus(HttpStatus.NOT_FOUND)
public class NoCordInRouteFoundException extends RuntimeException {
}
Rather than using annotations directly on top of the exception, you can define an exception handler by using the #ExceptionHandler annotation:
#ResponseStatus(HttpStatus.NOT_FOUND)
#ExceptionHandler(NoCordInRouteFoundException.class)
public String noCordInRouteFound(NoCordInRouteFoundException ex) {
return "template";
}
Add this method to a specific controller to be able to use a specific template when an exception is thrown in any of the other methods within the controller, or add the method within a separate class annotated with #ControllerAdvice so that it will be applied for all controllers.

Exception is not thrown for page doesn't exist

I have defined ExceptionHandler with #ControllerAdvice and catches the following
Exception.class, Throwable.class, SQLException.class
When a user enters a page which doesn't exist or not available in the server. circular view page error is being displayed in the log and ExceptionHandler is not getting called.
What are the usual checkpoints to make the API error to get caught in CustomExceptionHandler. Not sure whether any tomcat hooks to be defined.
Using Spring Boot 2.0 and Spring version 5.0
Thanks.
In case : user enters a page/resource which does not exist, no exception is thrown. So your code does not work (I believe your code is similar to following code)
#ControllerAdvice
public class ErrorHandler {
#ExceptionHandler(Exception.class)
public String handle() {
....
return "error"
}
}
In order to make it work you need to extend yourhandler class from ResponseEntityExceptionHandler as
#ControllerAdvice
public class ErrorHandler extends ResponseEntityExceptionHandler {
...
}
And You need to override the following method
handleHttpMediaTypeNotSupported
handleHttpMediaTypeNotSupported
Detailed guide can be found from
- https://blog.jayway.com/2013/02/03/improve-your-spring-rest-api-part-iii/
- http://www.baeldung.com/global-error-handler-in-a-spring-rest-api
Another way, You can override /error if there is fixed message in all general cases.

How does ExceptionMapper workes in EVERREST with JAX-RS?

I want to understand the logic of JAX-RS with ExceptionMapper
lets assume that I have class
#Provider
#Singleton
public class MyExceptionMapper implements ExceptionMapper<ApiException> {
/**
* check the exception type and build Response with the status body and the type of the error
*/
#Override
public Response toResponse(ApiException exception) {
........
}
}
How is call this class ?
I saw that there is class ApplicationPrivderBinder that has method getExceptionMapper
Does it is the logic?
Who call to this method ? where is the call to the method toResponse from the
interface ExceptionMapper
The JAX-RS framework does automatically call this when an exception of the specified type (here: ApiException) propagates out of a resource method.

Spring REST API custom exceptions handling

I have a Spring 3.2 application and I've created a REST API based on Spring MVC. I am using #ControllerAdvice annotation for custom exceptions handling. For example:
#ControllerAdvice
public class RestResponseEntityExceptionHandler {
#ExceptionHandler(MyCustomException.class)
#ResponseStatus(HttpStatus.CONFLICT)
#ResponseBody
public ExceptionMessage handleMyCustomException(MyCustomException ex){
return new ExceptionMessage(ex.getClass().getName(), ex.getMessage(), ex.getExceptionCode());
}
}
The issue is that I see how my custom exception is thrown but the exception handler method is actually not being executed and hence my exception message is not returned to the client. Instead, I noticed in the logs how the DefaultHandlerExceptionResolver handles the exception (with a Spring generic one, ServletRequestBindingException in a GET method). How can I get rid of this issue?
Thanks!
The ServletRequestBindingException is a hint that something went wrong before the handler method of the controller. In this case some binding issue.
Exception handlers annotated with #ExceptionHandler are only called when an exception is thrown within a controller handler method (#RequestMapping).

Exception handler in Spring MVC

I want to create an exception handler which will intercept all controllers in my project. Is that possible to do? Looks like I have to put a handler method in each controller. Thanks for your help. I have a spring controller that sends Json response. So if an exception happens I want to send an error response which can be controlled from one place.
(I found a way to implement it in Spring 3.1, this is described in the second part of this answer)
See chapter 16.11 Handling exceptions of Spring Reference
There are some more ways than using #ExceptionHandler (see gouki's answer)
You could implement a HandlerExceptionResolver (use the servlet not the portlet package) - that is some kind of global #ExceptionHandler
If you do not have a specific logic for the exception, but only specifc view then you could use the SimpleMappingExceptionResolver, which is at least an implementation of the HandlerExceptionResolver where you can specify an Exception name pattern and the view (jsp) which is shown when the exception is thrown. For example:
<bean
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"
p:defaultErrorView="uncaughtException">
<property name="exceptionMappings">
<props>
<prop key=".DataAccessException">dataAccessFailure</prop>
<prop key=".TypeMismatchException">resourceNotFound</prop>
<prop key=".AccessDeniedException">accessDenied</prop>
</props>
</property>
</bean>
In Spring 3.2+ one can annotate a class with #ControllerAdvice, all #ExceptionHandler methods in this class work in a global way.
In Spring 3.1 there is no #ControllerAdvice. But with a little hack one could have a similar feature.
The key is the understanding of the way #ExceptionHandler works. In Spring 3.1 there is a class ExceptionHandlerExceptionResolver. This class implements (with help of its superclasses) the interface HandlerExceptionResolver and is responsible invoking the #ExceptionHandler methods.
The HandlerExceptionResolver interface has only one Method:
ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex);`.
When the request was handled by a Spring 3.x Controller Method, then this method (represented by org.springframework.web.method.HandlerMethod) is the handler parameter.
The ExceptionHandlerExceptionResolver uses the handler (HandlerMethod) to obtain the Controller class and scan it for methods annotated with #ExceptionHandler. If one of this methods matches the exception (ex) then this methods get invoked in order to handle the exception. (else null get returned in order to signal that this exception resolver feels no responsible).
The first idea would be to implement an own HandlerExceptionResolver that behaves like ExceptionHandlerExceptionResolver, but instead of search for #ExceptionHandler in the controller class, it should search for them in one special bean. The drawback would be, that one has to (copy (or subclass ExceptionHandlerExceptionResolver) and must) configure all nice message converters, argument resolvers and return value handlers by hand (the configuration of the real one and only ExceptionHandlerExceptionResolver is done by spring automatically). So I came up with another idea:
Implement a simple HandlerExceptionResolver that "forwards" the exception to THE (already configured) ExceptionHandlerExceptionResolver, BUT with an modified handler which points to the bean that contains the global Exception handlers (I call them global, because they do the work for all controllers).
And this is the implementation: GlobalMethodHandlerExeptionResolver
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
public class GlobalMethodHandlerExeptionResolver
implements HandlerExceptionResolver, Ordered {
#Override
public int getOrder() {
return -1; //
}
private ExceptionHandlerExceptionResolver realExceptionResolver;
private List<GlobalMethodExceptionResolverContainer> containers;
#Autowired
public GlobalMethodHandlerExeptionResolver(
ExceptionHandlerExceptionResolver realExceptionResolver,
List<GlobalMethodExceptionResolverContainer> containers) {
this.realExceptionResolver = realExceptionResolver;
this.containers = containers;
}
#Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
for (GlobalMethodExceptionResolverContainer container : this.containers) {
ModelAndView result = this.realExceptionResolver.resolveException(
request,
response,
handlerMethodPointingGlobalExceptionContainerBean(container),
ex);
if (result != null)
return result;
}
// we feel not responsible
return null;
}
protected HandlerMethod handlerMethodPointingGlobalExceptionContainerBean(
GlobalMethodExceptionResolverContainer container) {
try {
return new HandlerMethod(container,
GlobalMethodExceptionResolverContainer.class.
getMethod("fakeHanderMethod"));
} catch (NoSuchMethodException | SecurityException e) {
throw new RuntimeException(e);
}
}
}
The global Handler has to implement this interface (in order to get found and to implement the fakeHanderMethod used for the handler
public interface GlobalMethodExceptionResolverContainer {
void fakeHanderMethod();
}
And example for an global Handler:
#Component
public class JsonGlobalExceptionResolver
implements GlobalMethodExceptionResolverContainer {
#Override
public void fakeHanderMethod() {
}
#ExceptionHandler(MethodArgumentNotValidException.class)
#ResponseStatus(HttpStatus.BAD_REQUEST)
#ResponseBody
public ValidationErrorDto handleMethodArgumentNotValidException(
MethodArgumentNotValidException validationException,
Locale locale) {
...
/* map validationException.getBindingResult().getFieldErrors()
* to ValidationErrorDto (custom class) */
return validationErrorDto;
}
}
BTW: You do not need to register the GlobalMethodHandlerExeptionResolver because spring automatically register all beans that implements HandlerExceptionResolver for exception resolvers. So a simple <bean class="GlobalMethodHandlerExeptionResolver"/> is enough.
Since Spring 3.2 you can use #ControllerAdvice annotation.
You can declare an #ExceptionHandler method within an #ControllerAdvice class
in which case it handles exceptions from #RequestMapping methods from all controllers.
#ControllerAdvice
public class MyGlobalExceptionHandler {
#ExceptionHandler(value=IOException.class)
public #ResponseBody String iOExceptionHandler(Exception ex){
//
//
}
// other exception handler methods
// ...
}
An abstract class where you define the exception handlers will do. And then make your controllers inherit it.

Resources