6

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 :-)

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
nano7
  • 2,455
  • 7
  • 35
  • 52

3 Answers3

5

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.

Robby Pond
  • 73,164
  • 16
  • 126
  • 119
  • Are you serious about the code example? Exceptions should never be swallowed like that. That way the proxy has no chance to detect the exception and roll back the transaction. I hope you mean something like this: `catch(SomeException exc) { throw new IllegalStateException(exc); }` – Sean Patrick Floyd Mar 21 '11 at 14:39
  • @Sean that's just pseudocode. I'd hope he wouldn't swallow an exception unless he had a good reason to do so. – Robby Pond Mar 21 '11 at 14:43
  • that's why I'm asking, not downvoting. You should make stuff like that clear, there are many newbies around – Sean Patrick Floyd Mar 21 '11 at 14:50
  • Thanks for answering. The second pseudocode was just what I mentioned im my question. I did not mean to catch an exception IN a transactional method, but to surround the call of a transactional-annotated method. So the answer is not clear to me: I CAN do it that way, but I should not? How can I inform an user if a transaction is rolled back? – nano7 Mar 21 '11 at 14:50
  • You can use exception translation as mentioned in Sean's answer to generate a standard exception (in spring the DataAccessException or whatever) and use an @ExceptionHandler to catch the exception and inform the user. I updated my answer to show an example. – Robby Pond Mar 21 '11 at 15:01
1

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.

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
0

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.

nano7
  • 2,455
  • 7
  • 35
  • 52