#ExceptionHandler not working in a Service class - spring-boot

The below is a service class
#Service
class Test {
public Object findEmployees1(String id, String dbId) {
return employeeRepo.findByDatabaseIdAndIdentifier(dbId, id);
}
public Object findEmployees2(String name, String dbId) {
Object records = employeeRepo.findByNameAndDatabaseId(name, dbId);
}
#ExceptionHandler(Exception.class)
public void internalErrorExceptionHandler(Exception ex) {
LOGGER.error("Log the exception here");
throw new InternalErrorException(ex.getMessage());
}
}
I want if any exception(eg some SQLException) comes in any of the method in the class test , it gets caught by the #ExceptionHandler and is logged there and re thrown
I cannot use #ExceptionHandler with #ControllerAdvice as I don't have any class with #Controller annotation on it . I am writing just a common module to get data from the database.
When I execute the code , the log under #ExceptionHandler is not printed as it never gets called.
The requirement is to log and rethrow a common exception if any exception comes in any of the service class methods without having individual try catch statements in each method.

As suggested, you can use spring aop to handle such exceptions. Instead of duplicating I will link to the existing question I have tried to answer here.
The other way is, if you are using ByteBuddy, you can use following annotation on the method which is expected to throw exception.
#Advice.OnMethodExit(onThrowable = RuntimeException.class)

Related

Exceptionhandler for Enum in request parameter

I have a Get request: \allTopic
It inputs a filterCriteria custom object which contains multiple fields and one of those is an Enum called Role, which is either student or teacher
And there are many more different API calls with different Enums. So I want to create #controllerAdvice that can handle all these.
I need help with
Annotations to put in the Get API controller function header
Annotations to put in the filterCriteria class
What particular exception to handle in #exceptionHandler in #controlleradvice
I have some similar code as per your need, please have a look
#ControllerAdvice
public class ExceptionController {
#ExceptionHandler(value = PageNotFoundException.class)
public String pageNotFoundException(PageNotFoundException exception){
return "error/404";
}
#ExceptionHandler(value = AuthFailedException.class)
public String authFailedException(AuthFailedException exception){
return "error/401";
}
#ExceptionHandler(value = ServerException.class)
public String serverException(ServerException exception){
return "error/500";
}
}
Afterwards, you can throw any of the given type of exception.
please note, you have to create such your exception.
Example:
public class PageNotFoundException extends RuntimeException{
}
I hope, it helps!

How to pass variable from #controller to #controlleradvice

right now I make custom handler using controlleradvice and is working well. I want to add additional info to the custom validation that "the invoice process has been failed". how do I achieve that ? thank you
You can define you own exception object and uses it to pass the data from the controller method to the exception handler method.
First define an exception as :
public class InvoiceException extends RuntimeException {
private Long invoiceId;
private String additionalInfo;
}
Then in the controller if you check that if violates the related business rules, create an instance of this exception and throw it :
public class InvoiceController {
#PostMapping("/invoice")
public Long processInvoice(InvoiceRequest request){
if(fail) {
throw new InvoiceException(invoiceId, "foobar");
} ​
​}
}
In the #ContorllerAdvice , you can then access these data from the exception instance :
#ControllerAdvice
public class MyExceptionHandler {
​#ExceptionHandler(InvoiceException.class)
​public ResponseEntity<ErrorMessage> handle(InvoiceException ex) {
​
​}
}

Hibernate not executing queries until response is commited

I am doing few hibernate save operations in spring's transactional service class.
My expectation is that by the time method execution finishes hibernate should write data to database.
But hibernate is actually executing those queries only when controller is about to return a response.
My sample code is as follows.
#Controller
public class TestController {
#Autowired
private SaveService saveService;
#RequestMapping(value = "saveData", method = RequestMethod.POST)
public String saveData(HttpServletRequest request, Model model) {
try {
saveService.saveData(object1, object2, object3); // LINE 1
sendEmail(); // LINE 2
//some code here // LINE 3
} catch(Exception e) {
//log exception
//return error message
}
}
}
#Service("saveService")
#Transactional
public class SaveServiceImpl implements SaveService {
#Autowired
private SaveDAO saveDAO;
public void saveData(Object objec1, Object objec2, Object objec3) {
saveDAO.save(object1);
saveDAO.save(object2);
saveDAO.save(object3);
}
}
In above code I am calling SaveService.saveData() method from controller. And if save is successful I want to go ahead and send an email. But if for some reason SaveService.saveData() throws an exception i don't want
to send the email.
When I performed some tests it was observed that even if SaveService.saveData() throws an exception it's not thrown
until the email is sent from controller. I want that if a call to saveService.saveData() at 'LINE 1' in controller
throws an exception the next line that sends email should not get executed.
I wanted to know if this is expected hibernate behavior and if it is what can I do to tell hibernate to execute
queries before exiting service methods.
Thank you.
This behavior is due to hibernate optimizations. Hibernate will wait until the last time possible to execute the sentences.
You can avoid this with session.flush(), Flushing the session forces Hibernate to synchronize the in-memory state of the Session with the database (i.e. to write changes to the database).
The problem here is when an exception occurs, your the variables/objects are not initialized in the catch block and you are accessing it.
As it looks like you have just added a snippet of the code in question, so I guess the variables object1, object2, object3 needs to initalized to null.
for example: object1=null

Spring Controllers,Service Classes,HiberNate Dao Classes ? why no Exceptions at dao's,service classes?

I did'nt get proper understanding from existing answers I have fully form-based web-application in which i have one spring controller for each form.
common base-class having code of varible(singleton object) declaraion of all service class instances(to-avoid declaring bo member variable in every controller,for business sevices interaction),which is parent for all controllers.
Common base-class having code of variable(singleton object) declaration of all dao service instances,which is parent for all BO's classes.
Common base-class having code of variable(singleton object) declaration of HibernateTemplate,SessionFactory using #Autowired annotaions.Which is parent for all dao classes.One parent for all of above three classes which is having Logger object instances.
One fbisExceptionHandler.java which captures exceptions from all #RequestMapping methods from all controllers as bellow
#ControllerAdvice
public class ExceptionControllerAdvice
{
#ExceptionHandler(Exception.class)
public ModelAndView exception(Exception e)
{
ModelAndView mav = new ModelAndView("exception");
mav.addObject("name", e.getClass().getSimpleName());
logger.error( e.getMessage())
mav.addObject("message", e.getMessage());
return mav;
}
}
please answer my questions
1) Is this single method fine for handling all exceptions .i,e those getting caught in controller,service classes,dao classes ?
2)why my all hibernate dao's methods not using either try..catch block or throws declaraion at methods signature....Is hibernate dao's did'nt throw any exception ? If so where they caught ?
for example one of my hibernate dao is
3)How all constarints from db vendors are handled ? Is there any hibernate inbuilt way ?
4) why my all my bo's methods not using either try..catch block or throws declaraion at methods signature.... where exactly exceptions being thrown and caught ?
My sample dao
package com.fbis.form18.daoimp;
all imports
#Repository
public class Form18daoImp implements Form18Dao{
#Autowired
SessionFactory sessionFactory;
HibernateTemplate hibernateTemplate;
#Autowired
public void setSessionFactory(SessionFactory sessionFactory)
{
this.hibernateTemplate=new HibernateTemplate(sessionFactory);
}
public void save(Form18Dtls form18dtls) {
sessionFactory.getCurrentSession().save(form18dtls);
logger.info("Form18Dtls saved successfully");
}
#Override
public Form18Dtls findbyFacId(String facID) {
#SuppressWarnings("rawtypes")
List list=hibernateTemplate.find("from Form18Dtls where FAC_ID=?", facID);
logger.info("findbyFacId ran successfully");
return (Form18Dtls)list.get(0);
}
all dao's methods are continued here..
}
My sample bo
package com.fbis.form18.boimp;
all imports
#Service("form18Bo")
public class Form18boImp implements Form18Bo
{
#Autowired
Form18Dao form18dtlsdao;
#Transactional
public void save(Form18Dtls from18dtls)
{
String UniqueTransactionNumber=getFacId(from18dtls.getFacDistrict(),"Form18_Dtls");
from18dtls.setFacId(UniqueTransactionNumber);
from18dtls.setSubmtdDate(new java.util.Date());
from18dtls.setAppStatus("I");
from18dtls.setFormId(23);
form18dtlsdao.save(from18dtls);
}
public String getFacId(String district,String tableName)
{
FacIdGenerator facid=new FacIdGenerator();
String genFacid=facid.factoryIdCreator("F18", district, tableName);
logger.info("getFacId ran successfully");
return genFacid;
}
#Override
public Form18Dtls findbyFacId(String facID) {
return form18dtlsdao.findbyFacId(facID);
}
other bo's continued here
If i am following wrong heirarkey of classes,suggestions are welcome,Thanks in advance
If I understand correctly, your question revolves around exceptions thrown from the data access layer, in this case you are using hibernate as your vendor.
If this is so then this is a pure java issue regarding checked exceptions and un-checked exceptions. Hibernate exceptions are un-checked (extend the RuntimeException) so there is no need to declare them on the method signatures and no need to catch them. On top of that, it is possible to tell Spring to transform specific vendor (e.g. hibernate) exceptions to Spring DataAccessException (see http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/dao.html).
Regarding your numbered questions above:
Yes
As I said, hibernate throws RuntimeExceptions, you do not need to declare them and if you do not catch them, then your #ExceptionHandler will catch them and handle them.
I don't understand the question
The same answer as in number 2

Spring Data Jpa - Repository doesn't thrown exception when #transactional exists

I have the following classes:
public interface GarageRepository extends PagingAndSortingRepository<Garage, Integer> {}
public class GarageBO {
private GarageRepository garageRepository;
public void updateGarage(Garage garage) {
try {
garageRepository.save(garage);
} catch (Exception e) {
throw BoozinaExceptions.getCodeException(garage, e);
}
}
}
public class GarageFacade implements GarageService {
private GarageBO garageBO;
#Transactional
public void updateGarage(Garage garage) {
garageBO.updateGarage(garage);
}
}
Supposing that i'm trying to update a garage and an unique violation is throwed.
When i call updateGarage from GarageFacade with the #Transactional annotation, garageRepository doesn't throws any exception.
When i call the same method without the #Transactional annotation, garageRepository throws the unique violation exception and now i can convert the exception using BoozinaExceptions.getCodeException(garage, e);
This behavior happens because when i have the #Transactional annotation, the exception will be throwed when Spring jpa data execute the commit. This happens after GarageBO.updateGarage execution ok ?
But i need to convert the unique violation. How can i do that ?
How to handle spring exception after commit then convert to my exception ?
What you describe is the expected behavior. The transaction is committed after the method ends, the commit leads to the unique constraint violation.
Adding #Transactional to the service methods makes the transaction end after the call to the service method the transaction is committed. Removing it makes the transaction commit after the call to the repository method.
Also why do you have a BO a Facade and a Repository?! Basically the BO and Facade are the same IMHO.
TO fix your your problem have your GarageRepository extend JpaRepository instead of PagingAndSortingRepository and call the saveAndFlush method instead of save. This will execute the sql (not committing the transaction) and trigger a constraint violation exception.
Another solution is to instead of doing a try/catch in your BO create and Aspect which does the conversion. Saves you coding the try/catch each time you need it.

Resources