Search code examples
hibernaterollbackopen-session-in-view

Should Rollbacks be an exception? (specifically: in web-apps and with OSIV)


This is a rather theoretical question:

In my service classes I tend to always do a rollback if the operation cannot take place for whatever reason, even if the cause is false input or any other condition that's expected and checked.

In a web-application employing the Open Session in View pattern (OSIV) this has the nasty side-effect that the session is closed and any subsequent lazy-load operation fails. I have to write ugly plumbing code to only rollback the session at the end of the request when an error occured at some point during the request.

This got me thinking: Should rollbacks be an exceptional measure in cases something really went wrong? Should service methods have to make sure by themselves that no data is written/changed if the conditions aren't met? How to deal with the case when the front-end layer updates a model object (like in a form) when input validation was successful but the service method decides the selected input is illegal? Hibernate for example would persist these changes automatically in default configuration when no rollback is done.

Looking forward to you opinions and tips!


Solution

  • In my opinion it is better to think in the opposite way: First you get your error condition (which can result in an exception or it can result in just returning null), and then you decide if in this case of error a rollback is useful.

    One very important question is: Who is doing the transaction handling? Is it done by the caller of your services, or is it done in the services itself (which means, every service call is a transaction for its own).

    A) The caller is doing the transaction handling:
    Then the service nearly never should do a rollback, because it would also rollback other statements which the caller did before calling this service. The caller might consider the error of the service as normal case and continue. For that case no database statements must get lost. If the caller can't continue after the error, it's the caller's job to rollback the transaction.
    This means the service must not write incomplete data to the db and it must check possible error conditions before writing.
    There are two cases where a rollback in the service nevertheless can be useful:
    - The error condition is definitively the result of a programming error.
    - It would be a lot of effort in the service to handle the error condition without rollback. In this case it is very important to document the rollback condition in the Javadoc, because the caller has to take care for it.

    B) The service is doing the transaction handling. Each service call is a transaction for its own:
    The service is free free to do rollbacks as it likes. If the service first checks the condition and does not write data or if it does a rollback, the result is the same and not visible for the caller. If data are written, the service must do either a commit or a rollback. If it throws an exception, a rollback is strongly recommended, because the caller does not expect data written in this case.

    By the way, if an exception is thrown in the Session object, Hibernate does a rollback automatically.