I am building web app with spring-mvc and hibernate. My question is, does #Transactional guarantee that it will do rollback even tough the exception is caught by #ExceptionHandler method in our #Controller ?
Yes. The #Transactional scope is "tighter", so it will always be handled before #ExceptionHandler gets its turn. You could look inside the Spring source code to see how it's done, but it would basically be a massive flaw if other logic were able to run before the transactional context had finished its job, whether commit or rollback.
Related
Using Spring, I am reaching the following scenario.
I have a service that has to be #Transactional because it calls several DAOs. But it also calls other services that are already #Transactional.
Somehow, I will be calling nested #Transactional services.
Will Spring manage well?
#Transactional without any explicit parameters uses propagation = REQUIRED. This means:
If there is no transaction in the current thread, a new transaction will be created
If there is a transaction, it will be used
The 2nd service (the nested one) annotated with #Transactional will be executed in the same transaction as the 1st one (the outer one). You don't need to do anything.
In some cases if you want to explicitly separate the nested call from the outer one you can use propagation = REQUIRES_NEW.
I'm working on rather simple RESTful service based on SpringBoot. I'm using Ebean and SpringData. All my REST methods are annotated with #Transactional:
#Transactional
#PostMapping
public Entity createEntity(...) {
// some code
}
The problem I'm facing is that if there is a network issue but this method executes without an exception, the transaction will still get committed. For example, the client might send the data, my code creates the record but then the server can't send a response back to the client. In this case, I'd want the transaction to rollback but I didn't find a way of doing that.
Is it even possible to rollback the transaction in this case? Maybe there is a Spring platform limitation I'm overlooking.
Thanks
EDIT: To answer the replies below and specify the question further: It's easy enough to rollback the transaction. The tricky part is to run any code in response to the network failure. I was hoping that I can configure Spring to do it for me. Like "wait until you sent the last byte and then rollback or commit the transaction". My current code will commit the transaction as soon as the createEntity() method has finished.
This is not Spring framework's limitation. Once the method is executed successfully, it is NOT spring framework's #Transactional responsibility to roll it back.
The best you could do is to have an ExceptionHandler. See this answer for a better perspective: https://stackoverflow.com/a/45034574/945214
The other thing you could do is to improve the performance of the whole HTTP request topology, so that the probability of the such potential failure(s) reduces (as the touch time decreases). See my writeup on app performance at: https://www.linkedin.com/pulse/improving-website-performance-kshitiz-garg/
If you can find out when you need to rollback (checking a return status/...), you can just throw your own Exception.
Watchout as it only rollbacks for unchecked Exception (otherwise, you'll need to add rollbackFor=Exception.class on your #Transactional if you want it to rollback for any exception).
See :
https://www.catalysts.cc/wissenswertes/spring-transactional-rollback-on-checked-exceptions/
Annotation #Transactional. How to rollback?
You can rollback Transaction without throwing an exception using:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
Recently refactoring some code, came across transaction rollback scenario where one EJB bean calls another. Now in exception block each bean has its context which is marked for rollback.
Is this a good practice or they should just re-throw the exception & finally the initiator bean only does the rollback.
Also, if there is single transaction spanned across EJB's, then rollback should happen at the originator bean or where it encountered exception.
Transaction type JTA for persistence with XA data source.
With this
is marked for rollback
you mean that the EJB catch the exception and use setRollbackOnly ?
If that's the case, then it depends on your design to decide which approach is preferred.
Normally a transaction is rolled back if a system exception is detected by the container. Application exception on the opposite does not have this effect.
But, if your business logic require that even a business exception has an important impact such that it must have the effect of rolling back the whole transaction, then you have the choice of setRollBackOnly, or launch an application exception with rollback=true.
This second approach has also the effect of not destroying the bean.
Regarding your second question:
Also, if there is single transaction spanned across EJB's, then
rollback should happen at the originator bean or where it encountered
exception.
the rollback is managed by the container, and again it depends on your design. Keep in mind that the error may pass trough the hole of your unique bean in charge of rolling back the transaction, and not being catched at all. So you will end up with an unwanted scenario with a transaction not being rolled back at all.
I am involved in a new project and I was assigned to investigate an error that is happening when apparently a transaction(or more than one) to the database in being performed. We are using Java for the backend(Spring framework), MyBatis for mapping objects and Websphere Liberty as server, the problem comes in some methods that are marked as #Transactional, this is the declaration:
#Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED,isolation=Isolation.READ_UNCOMMITTED)
Inside the method there are some executions to the database and apparently in some cases throws a TimeoutException and makes Rollback of operation, I guess concurrent calls make this(I am not sure) this is the error image we got:
I am new in transactions and I donĀ“t know if the parameters declared could affect in the performance, what can cause a TimeoutException as this?
I am lost, I would be grateful with any help.
Thank you.
I am new to JBoss. As part of My Application I am using JBoss.We are also using EJB's as a part of the project also. A exception like StaleObjectStateException is raised . So , the EJB uses this exception to rollback a transaction. So, Please tell me how to stop StaleObjectStateException from being logged.Log4j is used here.
StaleObjectStateException being a runtime exception, shouldn't be caught in normal cases
But the only way for you to stop it from coming to logs, is to catch the exception in your code and eat up.
However, IMHO it should be of prime importance to figure out why you are getting this exception.
org.hibernate.StaleObjectStateException is a Hibernate exception that usually indicates that some other thread of control has updated the state of your entity bean in the database.
You must catch it before it is thrown from an EJB and deal with it somehow.
Any RuntimeException that is thrown from an EJB call automatically results in transaction rollback.
You should also read the javadoc for org.hibernate.StaleStateException to ensure that some of the other scenarios it describes do not apply to you.