I'm using Hibernate and Spring and I'm currently stuck with something which I thought would be very simple to fix. I have a service method similar to this:
#Transactional
public void deleteObject(ObjectClass object)
{
this.objectClassDAO.delete(object);
}
I need to display a friendly message when the user tries to delete an object which is related to another entity. The problem I have is that the ConstraintViolationException is thrown until commit() is called, which runs outside of the scope of my service method. Is there a way to let spring call some intermediate code in the event of a particular exception, so that I can set the proper error message?
I've been searching on google for over an hour with no luck. The approaches I've found that seem at least mildly related seem like overkill and like they run at application level. Is there a simple way to intercept an exception after a commit at method-level?
You're probably using FlushMode.AUTO and the exception is being thrown when the transaction ends (in the proxy around your service created by Spring). You can explicitly call Session.flush() inside of the objectClassDAO.delete() method. You typically don't want to do this, but in this case it will force a synchronization with the underlying persistence and if there is a constraint violation the exception will be thrown before objectClassDAO.delete returns. This may be a last resort though.
Related
Docs state obvious thing:
a method will throw an exception if it is executed inside existent transaction.
Can anyone give a meaningful example of when/why it can be used on purpose?
Well, there may be several use cases that require your code not to run in a transaction. You'd use NEVER to enforce that as opposed to NOT_SUPPORTED which would just "suspend" the current transaction and resume it afterwards.
One use case that we had would be sending an email after some transactional operation. Sending the email itself doesn't require a transaction and to make sure the operation was successful and didn't get rolled back at the last moment our email sending service uses NEVER (otherwise we might accidentally send a "success" email and then get a rollback). That way if someone would call it while the operation's transaction still hasn't been successfully committed yet we'd get an exception and know that this should be fixed.
One use case might be framework related code that handles transactions or scopes. Think of Apache Deltaspike, arquillian, hibernate, ...
If you expose public methods you might want to make sure they are not wrongly used inside some transaction. Instead of unintentionally messing up open transactions you would rather fail-fast using #NEVER.
If you want to modify a nontransactional resource inside your code and want to make sure that others know this fact, you can use this feature.
I have heard that one should not use exception for communication.
I have a scenario that I would like to discuss.
We have a rest controller that invokes a service that is responsible for fetching a product from the database. Currently if product can't be found we will get an exception (checked exception) productNotFoundException.
This exception goes all the way to the controller. In the controller we have a controller exception handler (controller advice) that takes care of the exceptions and returns 404.
I was told that if they are run on different threads then the whole application would crash and it would be better to deal with the exception directly. Currently a lot of methods are being called and all have throws prodNotfoundex.
Can some one explain why it would crash. My project is a spring boot project.
I was told to return an empty response to the controller instead of throwing an exception.
I'm not sure how it would crash your application, if you handle/catch the exception properly.
Regarding exceptions, it should be seen as an exceptional state -- that is not in the normal flow of actions. Eg. the FileNotFoundException is exceptional, because you wanted to open the file, but it's not there. You expected it to be there, but it wasn't.
If you search for a product, you don't expect it to be there in the general sense of "expecting to find a loaf in the grocery store". You searched for a bunch of keywords, and the search resulted an empty response/zero matches. It is not exceptional in your business logic.
On the other hand, when you click "order" on a product (say on the product page), and then the product is not found, it is "exceptional". You expected a product you found 2 minutes ago to be there, but it isn't any more.
Some links on Java Exception handling costs:
http://java-performance.info/throwing-an-exception-in-java-is-very-slow/
Is it expensive to use try-catch blocks even if an exception is never thrown?
How expensive are Exceptions
How slow are Java exceptions?
Decide it for yourself.
I have few questions like
Which is the right place to handle a Hibernate RuntimeException.
DAO Layer?
ServiceLayer?
For instance, I have saveCustomer and the transaction fails, how can I inform the user through Exceptions?
I'm using the OpenSessionInView pattern, which will commit the transaction only after the view is rendered. In this case, if the transaction fails, How can I inform the user about this?
Generally it's a good idea to handle exceptions at the point in your code where you have the most information on how to handle them (or generate an appropriate error message with enough information). In the j2ee apps I've developed I usually have a transactional service layer that stitches together various DAO calls and I usually handle hibernate-specific runtime exceptions and all other data-related exceptions in the service layer. That said, if there's a pile of logic within a DAO where something bad could go wrong, it's probably not a bad idea idea to catch it there, add some error message context, and then rethrow it up the chain.
If an exception happens within your transaction you can either leave it uncaught or rethrow it with some additional context. This way your transaction manager knows to rollback the transaction. Always have an exception handler set up in your view/controller layer to handle any application-specific runtime exceptions that were thrown from your service layer calls. Inspect them for additional error messages and then use them to inform the user appropriately.
As far as I know, the default behavior when an exception is thrown out of a transaction it should rollback and not get committed at all. The answer to #2 really answers this one as well, i.e., if you've wrapped all your view layer's service calls in try/catch blocks or configure one globally via your web framework you shouldn't have a problem notifying the user that something bad-wrong happened.
This article (Best Practices for Exception Handling) has a decent overview on exception handling in general that you may also find useful.
Catch the exception where you can do something with the exception. If you catch it in DAO layer, then the information specific to dao layer needs to be extracted. e.g. if it is can not insert null value, then log the field details where it is failing. Once done, then the service layer can do business related processing of the exception directly or in wrapped format. You can see these common mistakes in exception handling. This is not applicable to specific hibernate example but in general to all.
Im working on developing a webapplication with Spring 3 and Hibernate 3.6. Ive got some questions to the #Transactional Annotation and the structure of the code.
-> When I use #Transactional (transaction management with Spring), do I have to surround the #Transactional-annotated methods with try/catch when calling them?
For example, when I got a method which loads, changes and returns then an object and I call it from another class: do I have to surround the call with try/catch? maybe something goes wrong, no object is returned, database connection fails.. I dont know.
until now, I thought #Transactional cares for all possible occurring exceptions and rolls back every operation in this transaction when an error occurs.
but if it occurs, I must inform the user somehow. when I call the transactional-method in the try-block and it is rolled back, the catch block is activated?
I can tell then the user "something did go wrong". Otherwise the user maybe would not be informed?
Or is it sufficient to check if there is an object returned (if/else), then I dont need try/catch?
Im new and I would like to hear how other structure their code. Thank you :-)
Handling exceptions in Spring is really easy with HandlerExceptionResolvers and #ExceptionHandlers. I tend to use #ExceptionHandler exclusively.
You can use an #ExceptionHandler to handle a specific exception instead of handling it yourself in a try-catch block.
If the user wanted a resource that wasn't found and you want to send a 404.
#ExceptionHandler(NotFoundException.class)
#ResponseStatus(HttpStatus.NOT_FOUND)
public void handleNotFoundException(NotFoundException exc) {
// log something.
}
If there was a Server issue where you'd want to send a 500
#ExceptionHandler(SomeException.class)
public void handleException(SomeException exc, WebRequest request, HttpServletResponse response) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Sorry dude, my server broke");
}
You also should narrowly handle the exceptions. In general you shouldn't do #ExceptionHandler(Exception.class) and I also believe that it works in order, so if you do handle the general Exception it should be the last method in the class.
The Key feature used by Spring is Exception Translation.
rely on exception translation to generate exceptions your client layer understands and use try / catch there only, if possible.
thanks for answering me. I read through the link (spring documentation) and I found the following:
"However, the DAO throws plain HibernateException (which is unchecked, so does not have to be declared or caught), which means that callers can only treat exceptions as generally fatal - unless they want to depend on Hibernate's own exception hierarchy.
Catching specific causes such as an optimistic locking failure is not possible without tying the caller to the implementation strategy. This trade off might be acceptable to applications that are strongly Hibernate-based and/or do not need any special exception treatment."
My DAO is based on Plain Hibernate 3 API, so if I understand it correct, my DAO only throws plain HibernateExceptions. They are unchecked and do not have to be declared or caught.
If something goes wrong, with #Transactional the whole operation is rolled back.
To make sure that everything works as I expected it to work, I have to tie my DAO even closer to my application code. There I can check for example if an object is given back or not. (if null - else)
I could also catch the exception, log it and inform the user that something did go wrong and that his transaction did not work.
So at this point, Im still thinking, that - depending on the transaction:
if I can work with a result, everything is ok - if not, I can inform the user.
when the transaction is not specified to give back a result, I can use try/catch for catching a HibernateException. But is the Transaction still rolled back then? I thought, catching an HibernateException avoids Rolling Back of the transaction.
I still do not know what to do. :-(
Beside of this unfortunately I do not understand what MVC Exception Handling (#ExceptionHandler) has to do with this. There was a table of handled exceptions, but I did not find the HibernateException.
Or do you think it will work with this: #ExceptionHandler(HibernateException.classs)? also you said you would not recommend to handle exceptions this way.
As described here, I want to update the user's database by means of catching the exception that occurs when the entity classes don't match. I understand that I could add a catch statement to every db-interface method, but that's error-prone*. Other 'polling methods' are also possible, but they are not interrupt-driven as I want through catching exceptions.
I think what I'm looking for is to catch the exception before it's delivered to the user (possibly to crash the application). I would put there my catch block. I'd have put it in the main() in a non NB app.
My understanding is that the exception is thrown on an entity basis (i.e. a method that involves only one entity, which has not changed, will not throw any exceptions, although other entities have changed).
I had a similar problem, but I guess mine is a bit harder to solve. I use JPA at server side, and the server is actually a webservice provider.
The persistence is managed by the container, and according to my app settings, it uses a "Create" strategy. Of course, every time I change my entities and redeploy the application it throws a lot of exceptions.
What I finally decided to do is to create/migrate the existing database in a separate process. This is, reading the metadata associated to the entities and comparing it with the current database.
Afterwards, it creates a migration script in case the db schema is different to fit it into the new one without losing any information (the migration script generation complexity depends on how do you plan to handle cases like data type changes or attribute removal). The last step is redeploying the app (in your case start it).
I'd suggest a proactive approach, where you don't wait for the exception to be thrown, but trying to guess the changes before to run the application.