How to catch exception thrown by save method of JpaRepository interface - spring

I have a SpingBoot project that uses Spring Data Jpa as its repository level abstraction. I have a repository that extends JpaRepository interface. I call the save() method from within my Service layer as follows :
myCustomeRepository.save(new ObjectXYZ(abc,xyz));
I also observed that the save() method inherited from the CrudRepository throws IllegalArgumentException when receiving null entities.
Should I go ahead and try to catch the IllegalArgumentException in my Service layer ?i.e.
try{
myCustomeRepository.save(new ObjectXYZ(abc,xyz));
}catch (IllegalArgumentException iae){
}
NOTE: I have already implemented validation(#NotEmpty) at the DTO level using Hibernate Validator.

IllegalArgumentException extends RuntimeException, so the compiler will not force you to catch it.
Whether you catch it or not depends on what you want to do if it occurs:
If you expect it to never happen, because of the validation you have in place, then don't catch it. If it does happen (e.g. there's a problem with your validation) then your application will fail and you will find out that there's a problem.
If it indicates that the client has passed bad data to your service layer, you could catch it and do whatever your service layer does to report invalid data to its clients, or you could just not catch it, and (assuming you are writing a web application) have a global mapping of the exception to a 400 bad request status.
What you should not do is catch it and ignore it, because then you will have difficulty figuring out what is wrong with your system if it is ever thrown.

Related

Undeclared Throwable Exception when using Spring Boot AOP controller advice with join points matching jpa repository functions

Problem:
Spring boot service using MVCS architecture. I am using Spring AOP advice (around advice) for all functions present in any class in repository directory. So for example when jpa save method is called, the around advice is triggered.
Now, Here is how things get called when no exception occurs.
CONTROLLER -> SERVICE LAYER -> call to repository layer function triggers advice function which allows join point to proceed -> REPOSITORY LAYER -> around advice -> and everything executes fine.
Now, Here is the flow when exception is thrown by the controller advice function.
CONTROLLER -> SERVICE LAYER -> call to repository layer function triggers advice function which allows join point to proceed -> REPOSITORY LAYER -> some DB exception occurs (for example trying to set a database attribute with NON NULL constraint to NULL) -> back to controller advice, it catches the exception then throws a custom checked exception to service layer and than going through service layer and then controller where the exception is handled.
The problem is that service layer doesn't know about controller advice (it acts like a proxy) and thinks that repository layer won't throw any exception since it doesn't declare throws in its methods signature (for example the default save method).
So the exception that reaches the controller is not the one which is thrown by the controller advice functions. In fact Java wraps that exception inside UndeclaredThrowableException.
One way to deal with this situation is to check ex.getCause() and get the exception which java wrapped in UndeclaredThrowableException.
Another is to declare throws in the repository methods signature so that the service layers can know about the repository function throwing exception. (But this is not possible for default implementation provided by jpa - like the save function - atleast not without overriding the save function) and this I don't want to do because there are a lot of jpa inbuilt functions to override.
Any elegant solution/suggestion to the problem ?
You cannot magically violate JVM restrictions about throwing undeclared checked exceptions. Therefore, you will have to
throw a checked exception which has actually been declared in the intercepted target method, or
throw a runtime exception instead, optionally wrapping it around the checked exception you want to throw.
Sorry, I cannot change the JVM for you. You need to play by its rules.

Global Exception Handling via Spring Advice In a MQ based Spring Boot Application

I've a MQ Spring Boot PaaS application where I need to implement exception handling via a common exception handler class (GlobalExceptionHandler). My PaaS application receives message from a source queue, perform some database operations via spring jpa and write the response back to a destination queue.
I need to handle all the database RuntimeException, custom business exceptions and other checked exceptions via GlobalExceptionHandler class.
My GlobalExceptionHandler will have handlers (method) defined for every exception. In my handler, I will be logging the exception first and then I will be creating a [error code, desc] and then I need to return it back to main flow.
I do not have any controller in my application. So I think, I can't use #ControllerAdvice. Currently I'm using spring AOP #AfterThrowing as below but I'm not able to return the [code, desc] from handlers.
#AfterThrowing(pointcut = "execution(* com.abc.xyz.service..*(..)) ",
throwing = "dataNotFoundException")
public void handleDataNotFoundException(DataNotFoundException dataNotFoundException) {
LOGGER.info("Info : " + dataNotFoundException.getMessage());
// code, desc need to create here and send it back to calling place.
// I need to change the return type here from void.
}
Can anyone please guide me in implementing exception handling here.
As I explained here, #AfterThrowing cannot modify return values or otherwise change the execution flow of your epplication. You cannot even catch the exception there. You need to use an #Around advice instead.
I suggest you read some documentation first and then ask more follow-up questions.

What is the replacement for Spring's deprecated NoSuchRequestHandlingMethodException?

The NoSuchRequestHandlingMethodException was deprecated in Spring 4.3, in favor of annotation-driven handler methods. What does this mean? The exception is still listed in the documentation, without mentioning its deprecated status. If I understand correctly, this exception is thrown when there is no request mapper for a given request. It appears to be handled by the DefaultExceptionHandlerResolver, here, and the relevant method has been deprecated as well.
If this method is deprecated, can I assume Spring does not throw this exception anymore? How am I supposed to replace this functionality with annotation-driven exception handling? Which exception am I supposed to handle, if this one is deprecated?
Side note: I also noticed a newer NoHandlerFoundException, here. Is this a replacement? If so, why? It appears to do the same thing. And why are the exceptions related to other HTTP status codes not deprecated? It all doesn't make a lot of sense.
The NoSuchRequestHandlingMethodException exception is part of the multiaction package that has been deprecated in Spring:
https://docs.spring.io/spring-framework/docs/2.5.x/javadoc-api/org/springframework/web/servlet/mvc/multiaction/class-use/NoSuchRequestHandlingMethodException.html
If you don't use multiactions, you can safely get rid of that catch statement and/or stop trying to catch and handle that exception. For example, some "Exception-to-Response error handlers" sample code might look like this to try and catch cases when the dispatcher doesn't find a proper mapping:
#ControllerAdvice
public class RestErrorHandler {
#ExceptionHandler({FileNotFoundException.class, NoSuchRequestHandlingMethodException.class})
#ResponseStatus(HttpStatus.NOT_FOUND)
#ResponseBody
public ErrorInfo process404(HttpServletRequest req, Exception ex) {
return handleException(req, HttpStatus.NOT_FOUND, ex);
}
}
But the latest dispatcher (non-multiaction) will never throw such an exception, so you could simply get rid of the NoSuchRequestHandlingMethodException and, instead, handle the NoHandlerFoundException (which is not thrown by default, but you can configure the spring dispatcher to throw it IF you really need to, because, by default, the dispatcher already returns a 404).

Integrate GWT with Spring Security framework

I have searched for tutorials on this topics, but all of them are outdated. Could anyone provide to me any links, or samples about integrating Spring security into GWT?
First of all, you have to bear in mind that GWT application is turned into javascript running on client-side, so there is nothing you can really do about securing some resources out there. All sensitive information should be stored on server side (as in every other case, not only for GWT), so the right way is to think of Spring Security integration from the point of view of application services layer and integrating that security with communication protocol you use - in case of GWT it is request factory in most cases.
The solution is not very simple, but I could not do it in any better way... any refinement suggestions are welcome.
You need to start with creating GWT ServiceLayerDecorator that will connect the world of request factory with world of Spring. Overwrite createServiceInstance method taking name of spring service class to be invoked from ServiceName annotation value and return instance of this service (you need to obtain it from Spring ApplicationContext):
final Class<?> serviceClass = requestContext.getAnnotation(ServiceName.class).value();
return appContext.getBean(serviceClass);
Also, you need to override superclass invoke(Method, Object...) method in order to catch all thrown runtime exceptions.
Caught exception cause should be analyzed, if it's an instance of Spring Security AccessDeniedException. If so, exception cause should be rethrown. In such case, GWT will not serialize exception into string, but rethrow it again, thus, dispatcher servlet can handle it by setting appropriate HTTP response status code. All other types of exceptions will be serialized by GWT into String.
Actually, you could catch only GWT ReportableException, but unfortunately it has package access modifier (heh... GWT is not so easily extensible). Catching all runtime exceptions is much more safe (althouth not very elegant, we have no choice) - if GWT implementation change, this code will still work fine.
Now you need to plug in your decorator. You can do it easily by extending request factory servlet and defining your's servlet constructor as follows:
public MyRequestFactoryServlet() {
this(new DefaultExceptionHandler(), new SpringServiceLayerDecorator());
}
The last thing - you need to do a dirty hack and overwrite request factory servlet doPost method changing the way how it handles exceptions - by default, exception is serialized into string and server sends 500 status code. Not all exceptions should result in 500 s.c - for example security exceptions should result in unauthorized status code. So what you need to do is to overwrite exception handling mechanism in the following way:
catch (RuntimeException e) {
if (e instanceof AccessDeniedException) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
} else {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
LOG.log(Level.SEVERE, "Unexpected error", e);
}
}
Instead of extending classes, you can try to use some 'around' aspects - it is cleaner solution in this case.
That's it! Now you can annotate your application services layer as usual with Spring Security annotations (#Secured and so forth).
I know - it's all complicated, but Google's request factory is hardly extendable. Guys did a great work about communication protocol, but design of this library is just terrible. Of course the client-side code has some limitations (it is compiled to java script), but server-side code could be designed much better...

Handling exception when using HibernateDaoSupport

I am using Spring Hibernate integration in my application and DAO classes are extending HibernateDaoSupport.
Suppose I save some object using the code
getHibernateTemplate().save(object);
As Spring Hibernate integration doesn't mandate to write try-catch block, but suppose if any exception is thwron while saving that object.
Then what is the best way to handle it? I means should I catch it in the service layer and wrap it in some user defined excpetions.
Do I need to write try-catch in DAO layer method itself in case I want to log which method in DAO throws exception?
I have never used HibernateDaoSupport or Hibernate Template before so ignorant about exception handling. Please provide me your valuable inputs
The idea behind Spring using RuntimeException is that generally there are different types of exception:
Exceptions that you want to recover from (such as a DuplicateKeyException if a record that you're trying to insert already exists or the more general DataIntegrityViolationException if there was a DB constraint that was violated as a result of user input)
Exceptions that you can't recover from (the database is down)
For the first case, you may well handle the exception (either through a custom business exception, so that the view layer can redirect to the input page and provide a meaningful message)
For the second case, it would be easier to let the exception bubble up and have it handled by a generic exception handler that then displays a generic error page to the user. For this scenario it doesn't make sense to wrap the exception in a custom exception as you won't be able to recover. A blown up DB tends to be fatal.
So what I would do:
try {
getHibernateTemplate().save(object);
} catch (DataIntegrityViolationException dive) {
throw new BusinessValidationException(dive, "You've got the data wrong");
}
Spring exception hierarchy is well documented.
Usually you can't do much if you have a data access exception, because in the working system this may be caused by the shortage of diskspace on the DB server, or network connection problems etc.
Such exceptions are usually need to be logged and investigated as soon as possible.
There some recoverable errors, they can be handled with spring exception hierarchy, but imho most of them should be avoided during the developing phase, so your web server should validate as many things as possible, before it goes to the db.
If you want to set the exception logging see the similar questions:
Exception handler in Spring MVC
Spring MVC Best Practice Handling Unrecoverable Exceptions In Controller

Resources