How Runtime Exceptions are handled by Spring ExceptionHandler - spring

I am using spring's #ControllerAdvice and #ExceptionHandler for exception handling.
Any method throws custom exception from Controller and corresponding #ExceptionHandler handle it. If Runtime exception occurs(eg any HibernateException) then it will throw Runtime Exception and I dont have any #ExceptionHandler for RuntimeExceptions.
My question is how to handle any runtime exception? do I need to add #ExceptionHandler for every Exception that is thrown by controller?
I dont want create an Generic ExceptionHandler for Exception.class because I have to send different error code according to exception occured.
one way to do it add try catch block in Controller and then throw the custom exception from catch block?
or is there any another better way?
All #ExceptionHandlers are inside #ControllerAdvice class.

the alternative is don't catch Exception in Controller. catch all Exception in service layer and throw a custom Exception eg. if you persisting a record failed, throw DatabaseException with message. see below method:
Student persist(Student object){
try{
studentDao.insert(object);
}catch(HibernateException e){
throw new DatabaseException("database operation failed!");
}
return student;
}
from you exception handler method you can get the message. this way you can set different message on different Exception.

Related

is there a way to log exception for all #ExceptionHandler in one place

I have #ControllerAdvice with numerous #ExceptionHandler methods with their own logic. However, I do need a log an original Exception.
Is there a way to do it without adding explicit logging message to each #ExceptionHandler method?
No. You should define other Exception class and do not define it in #ControllerAdvice .
then you can use this Exception and put in log
catch (DefinedException ex) {
log.info("your log here");
throw ex;
}

Spring boot exception handler : throw an exception

Using this works fine
#ResponseStatus(value = HttpStatus.NOT_FOUND)
#ExceptionHandler(value = IoTException.class)
public void IoTError() {
}
But when I try to convert to another homemade exception
#ExceptionHandler(value = IoTException.class)
public void IoTError() {
throw new IoTConnectionException();
}
Exception handler is ignored, i.e. IoTException are sent to the view without being converted to IoTConnectionException. But placing a breakpoint showed me enter the IoTError method.
Any idea why ? Thanks :)
The docs about exception handling state:
If an exception occurs during request mapping or is thrown from a request handler such as an #Controller, the DispatcherServlet delegates to a chain of HandlerExceptionResolver beans to resolve the exception and provide alternative handling, which typically is an error response.
At the point where you are throwing the IoT exception, the delegation to the chain of HandlerExceptionResolver has already been taken place and it will not be executed again. If this exception would trigger another exception handling dispatch it could cause exception cycles. Imagine you would have defined another exception handler method for IoTConnectionException and this would throw IoTException. You would end with a StackOverflowException.
In this section Docs Exception handler methods all supported return values of an exception handler method are described.

spring transaction at service layer

In our application we are applying spring declarative transactions using annotations at service layer.
Here i am not getting any idea on how to handle exceptions properly.
What exactly my requirement is when dao layer throws any hibernate exception we are rolling back the transaction, but in one case i am getting InvalidDataAccessResourceUsageException because there is a unique index violation happening. So what i would like to do here is i want to catch InvalidDataAccessResourceUsageException exception at service class and have to rethrow the application specific exception to controller.
But whats happening here is as we have transaction demarcation at service layer class the session is flushing at service layer(ie when tx commits) after executing the method, as a result i cant catch it into the same method and it is directly propagating to the controller.
Please suggest me work around on this.
also seeking one more clarification, suppose i have a method like below
#Transactional(value="transactionManager",readOnly = false, propagation = Propagation.REQUIRED,rollbackFor = HibernateException.class)
public SomeDTO editObject(SomeDTO someDto, String user) throws EditException {
try{
/*
call to dao.edit();
another call to anotherDao.addEditsTOAnotherTable();
some business logic*/
} catch(HibernateException e){
} catch(InvalidDataAccessResourceUsageException ie){}
}
Can i catch exceptions as above. Note: I am not handling or throwing any exceptions from dao. Also there is no session cache mechanisms like FlushMode.ALWAYS etc at dao layer as it will flush during tx.commit().
By default #Transactional will rollback for any RuntimeException, and since HibernateException is a RuntimeException , roll back will be done automaticaly and you don't have to add rollbackFor = HibernateException.class
You can handle Exception this way:
try{
}catch(InvalidDataAccessResourceUsageException e){
throw new YourApplicationExceptionNotUniqueIndex();
}
and :
YourApplicationExceptionNotUniqueIndex shoud extends RuntimeException that way you wil have a rollback at your sevice layer and you can catch the exception at your Controller .
Better to handle check all the database constraints before editing into database

Linking Server Side Message/Exception with AJAX request

I am making an ajax submit using Primefaces but I am having trouble linking my server side message with my ajax request.
Supposed I have this button that calls an action.
In my managed bean, do I need to raise an exception? How do I pass this message into my ajax request
public void checkout(ActionEvent event){
if(expression){
throw new CustomException("Account balance is not enough!");
}
}
public class CustomException extends RuntimeException {
public CustomException(String message) {
super(message);
}
}
How do I handle this case? Will my onerror javascript method be able to handle this?
Also, in one case supposed DB is down then how do I handle the exception? Do I have accessed to the error message
in my javascript function?
public void checkout(ActionEvent event){
try{
//DB is down
if(expression){
throw new CustomException("Account balance is not enough!");
}
}catch(Exception e){
}
}
As to your concrete question, you need to implement a custom ExceptionHandler for this which does basically the following when an exception occurs in an ajax request:
String errorPageLocation = "/WEB-INF/errorpages/500.xhtml";
context.setViewRoot(context.getApplication().getViewHandler().createView(context, errorPageLocation));
context.getPartialViewContext().setRenderAll(true);
context.renderResponse();
This is not exactly trivial if you want to take web.xml error pages into account. You'd need to parse the entire web.xml for this to find the error page locations. The OmniFaces utility library has exactly such an exception handler, the FullAjaxExceptionHandler. You can find the full source code here and the showcase example here.
As to your concrete functional requirement, I wouldn't throw an exception when there's just an user error. This is fully recoverable. You need to create and add a FacesMessage and have ajax to update the <h:messages>, <p:messages> or <p:growl>. The PrimeFaces ones support an autoUpdate="true" which would auto-update itself on ajax requests. E.g.
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Insufficient balance", null));
with
<p:messages autoUpdate="true" />
Throwing an exception makes only sense in unrecoverable situations like as when the DB is down. Note that you usually don't throw such an exception yourself. In case of JPA it would already be thrown as PersistenceException which you in turn shouldn't catch in JSF managed bean, but just let it go.

Why exception handler is not catching error in Spring MVC

I want to catch an Error in springMVC3 using exception handler. I annotated the exception. I can catch throwable and any exception. But when I tried with Error, It is not catching the exception. Any idea why it is so? The below code catches exceptions
ExceptionHandler(InvalidDataException.class)
public ModelMap handleException(InvalidDataException ex) {
logger.debug("exception catched :" + ex);
return new ModelMap();
}
But the below is not catching;
#ExceptionHandler(Error.class)
public ModelMap handleException(Error ex) {
logger.debug("exception catched :" + ex);
return new ModelMap();
}
The second example is not working because you are catching an Error, which extends Throwable and not Exception. You will find that the code will work if you change to the '#ExceptionHandler' and the 'handleException()' method to either 'Exception', 'InvalidDataException' or any other exception that is of interest.
Even I too faced the same problem ,I think #ExceptionHandler can deal with exceptions only not with throwable and errors
Refer the link:ExceptionHandler doesn't work with Throwable

Resources