Does Spring really gives new transaction for each thread? - spring

I am working on a project which makes extensive use of spring transactions. I t so happened that i was throwing an exception AND NOT HANDLING IT PROPERLY which does not commit or rollback the transact Ion. So the connection remains active even when the thread is stopped. When new request to the web server ( Apache tomcat 7.0) comes the spring provides the earlier connection to the new thread. Since the thread didn't started the connection so the thread couldn't close it either ie .commit doesn't work. because of which the objects are not getting persisted in database in the consequent transactions even when there is no exception. How can i work around the problem so that i can detect where is the actual problem happening or can a design an exit point where i can explicitly close the transaction before response is sent to browser.

A runtime unchecked exception or error that is thrown from a #Transactional method will rollback that transaction by default; a return or a checked exception will commit the transaction by default. You can tell Spring to override that behaviour using the annotation type elements of the #Transactional annotation.
The Spring Framework reference manual has an entire chapter devoted to transaction management. You need to read and understand that as your starting point.

Related

Spring Boot DB connection release mode

Is there a way to control database connection release strategy in Spring Boot? Something like Hibernate's ConnectionReleaseMode?
My test code would be rougly following:
INSERT query
HTTP call
UPDATE query
INSERT and UPDATE queries are their own methods in a repository bean (either extending CrudRepository, or as a Mybatis #Mapper). HTTP call is in it's own bean.
Now my service bean is where I experiment with different #Transactional settings as my ultimate goal is to have these three steps executed within a single transaction.
The problem is, the HTTP call can take hundreds of millis and Spring is holding the database connection during that time. This quickly leads to an empty connection pool, while the connections themselves are idle.
I have done the same experiments with default configuration using spring-boot-starter-data-jpa and also using mybatis-spring-boot-starter.
The only thing which got me closer to my goal was setting spring.jpa.open-in-view=false for data-jpa, which would release db connections in case of not using #Transactional at all or with propagation set to NEVER. It doesn't work if it's all wrapped in a transactin though.
I'm feeling like I'm missing some vital part of the transaction concept in Spring. Though the Spring reference docs mentions release mode only in relation to JTA transaction manager + JEE container + Hibernate.
Transactions are bound to a connection/session so you can't release the connection in the middle of a transaction. You have to finish the transaction to close/release the connection. Keep in mind that a transaction could abort at any time, and since the HTTP call is not "part of" the transaction, but just runs while the transaction is in progress, it won't help you to keep the transaction open while the HTTP call is running. I'd suggest you go with one of the following solutions:
Use a circuit breaker to cancel the HTTP call if it hits a timeout to have an upper bound for how long a connection/transaction can be open/held
Move the HTTP call out of the transaction, either before or after the transaction
Use two database transactions
Note that you could use a transactional Job Scheduler to schedule a job in the first TX. The job could then, with at least once semantics, try to invoke the HTTP call and then continue with the second transaction or do some compensation if something fails.

Explicitly joining a JTA transaction requires a JTA transaction issue with jBPM 7 and Spring Boot

We use jBPM 7.41 business application with Oracle database. Under high load, transaction timeouts are detected and arjuna marks them for rollback. Then, jBPM executor thread reuse the same transaction and throws a repetitive exception "No active transaction...". The jBPM is working at the begining but after few minutes of work, there is no active JTA transaction. We use asynchronous executor with a simple command throwing exception, the processes execute normally but as soon as Arjuna Transaction Reaper cancels a transaction, the executor threads will throw the same exception "Explicitly joining a JTA transaction requires a JTA transaction".
We think that the same fix done for JtaTransactionManager in is needed for KieSpringTransactionManager.
We created a ticket here https://issues.redhat.com/browse/JBPM-9450 describing the problem and attached logs and a project to be able to reproduce it.
We tried several options, replacing Narayana with Atomikos and Bitronix, Oracle with PostgreSQL but the issue is the same.
It seems that we’re encountering the same problem described here: https://issues.redhat.com/plugins/servlet/mobile#issue/RHBPMS-4621.
Thank you in advance,
We use:
Spring Boot: 2.2.2.RELEASE
Kie Server: 7.45.0.Final
Narayana: 5.9.0.Final
Logs : https://issues.redhat.com/secure/attachment/12501068/logs.txt
Sample project to reproduce the issue available here: https://issues.redhat.com/secure/attachment/12501190/jbpm-perfs-oracle.zip

Spring Integration JMS - Spring code does commit on RuntimeException

I would like to ask experienced Spring Integration developers or even code authors regarding weird behavior Im experiencing with my code. The issue is that Spring Code executes COMMIT on my RuntimeException. So here is my setup:
1.
I have standard JMS inbound channel adapter configured using
<jms:message-driven-channel-adapter />
I have transactionManager which implements the Best effort 1PC pattern - that one available in Spring, ChainedTransactionManager.
Im consuming messages in simple testing flow where the JMS inbound adapter only publishes to direct channel and via one transformer endpoint the converted message is published to another direct endpoint where the handler which is ServiceActivator intentionally throws my application exception which extends RuntimeException.
Now when I debug the whole flow and when Im stepping through the Spring internal code I always end in place where the configured transaction manager calls COMMIT and thus my ChainedTransactionManager executes COMMIT as well despite Im simulating error and thus clear rollback scenario. The breakpoint in the rollback method is not hit at all.
What can I have wrong?
Now I have gone through the code again and even the Spring code sets the status to RollbackOnly and executes some exception handlers but at the end it still goes on successfully and ultimately it calls the commit line as shown on the screenshot and chainedTransactionManager instructs its local TMs to commit as well.
Im hoping there is some detail/mistake Im not able to spot :) Thanks!
Screenshot from class .m2\repository\org\springframework\spring-jms\5.2.3.RELEASE\spring-jms-5.2.3.RELEASE-sources.jar!\org\springframework\jms\listener\AbstractPollingMessageListenerContainer.java

Wildfly 10 jms send Message to queue as part of XA transaction

I have recently had to support a colleague in verifying why some system tests are not passing in wildfly, system tests that pass consistently on weblogic and glass fish.
After analysing the log, it became clear the reason is related to a JMS message sent by a backed thread getting committed to a queue too soon, when the expectation was the message would be committed when the entry point Container Managed Transaction of an MDB commits. So the message is going out before the MDB that sends it is done running.
In weblogic, to achieve the expected behaviour, you need to make sure that when you take the connection factory given by the container , which is XA configured, you set the connection.createseesion with
transacted = true and
acknowledgement = session transacted.
In a process similar to the one depicted in this URL
http://www.mastertheboss.com/jboss-server/jboss-jms/sending-jms-messages-over-xa-with-wildfly-jboss-as
Except in the snippet above auto acknowledge is set and the first parameter is set to false.
In wildly when our weblogic and glass fish configuration is used, nothing is committed and the system behaves as if the JMS message sent were to be rolled back.
If configuration as in the example above were to be used, instead what would happen is that the JMS message is immediately and the consumer MDB immediately launches being trigerred before the producer transaction actually ends, causing the system test to fail.
According to the official JMS configuration, by using a connection-pooled factory with the transaction=XA attribute, the container should immediately bind the commit of the transaction to the lifecycle of the parent transaction.
See official documentation bellow in particular in respect to the Java:/JmsXa connection factory.
https://docs.jboss.org/author/display/WFLY10/Messaging+configuration
My colleague was initially using a non pooled connection factory, but the injection info reference has since then been fixed. I have tried all possible combinations of parameters in the shed message, but my outcome is sitll:
Either sent too soon or never sent.
To conclude all the other resources are XA. Namely the oracle db is using the XA driver.
Can anyone confirm if in wildly the send JMS message only when parent transaction commits is working and if so how the session is being configured?
I will check if perhaps my colleague has not made a mistake in terms of the configuration of the connection factory used by the Men's themselves to consume messages out of the queue.but if that one is also XA... Then it is a big problem.
So the issues is fixed.
The commit of the JMS message to the queue at the end of the transaction works perfectly.
The issue was two fold:
(a) First spot of code I was looking at address the issue was not correct. Someone had decided to write his own send telegram to queue API elsewhere, and was not using the central API for sneding telegrams, so any modification I to the injection connection factory was actually not taking effect. The stale connection factories were still being used.
(b) Once the correct API was spotted it was easy to make the mechanism work by using the widlfy XA pooled connection factory mentioned in the post above.
The one thing that was tweaked was the connection.CreationSession api.
The API in JEE 7 has been enlarged and it is now better documented than in jEE 6.
To send a JMS message in a container as part of an XA transaction one should do:
connection.createSession() without any parameters.
This can easily be seen in the connection javadoc:
https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html
QUOTE 1:
This method has been superseded by the method createSession(int
sessionMode) which specifies the same information using a single
argument, and by the method createSession() which is for use in a Java
EE JTA transaction. Applications should consider using those methods
instead of this one.
QUOTE 2:
In a Java EE web or EJB container, when there is an active JTA
transaction in progress:
Both arguments transacted and acknowledgeMode are ignored. The session will participate in the JTA transaction and will be committed
or rolled back when that transaction is committed or rolled back, not
by calling the session's commit or rollback methods. Since both
arguments are ignored, developers are recommended to use
createSession(), which has no arguments, instead of this method.
Which means, the code snippet in:
http://www.mastertheboss.com/jboss-server/jboss-jms/sending-jms-messages-over-xa-with-wildfly-jboss-as
Is not appropriate. What one should be doing is creating the session without any parameter and leting the container handle the rest.
Which it does just fine.

How application can be notified when Spring Transaction Manager rollbacks a SQL transaction?

In Spring based application, Transaction Manager is responsible for committing or rolling back SQL transactions.
My application uses a custom cache for some part of persistent data.
This cache is not managed by Spring nor Hibernate.
If a SQL transaction encounters errors and must be rolled back, then cache modifications should be rolled back as well.
My question is, how to register an event listener or callback which will call my cache.evict() method when Spring Transaction Manager rolls back a transaction?
You can use TransactionSynchronizationAdapter for this. For reference, you can look at this: Spring - commit JMS Transaction after JPA transaction
In the answer given in the link, the synchronization is registered for afterCommit. In your case, it would be afterCompletion. In that implementation, you will need to check if the transaction is in a rolled back state and do the cache eviction.
There are lots of ways of doing this...
You can use application events if you want... Application Events in Spring Framework 4.2
You can throw a custom runtime exception and you can handle it in your exception handler (if you're using spring MVC). but here I don't recommend to do any important operations like clearing of cache here... Exception handling in Spring MVC
You can use a combination of #1 and #2. You can send an event that will eventually throw a runtime exception that you handle it in UI (spring mvc or whatever you use). This is how I would do it
You can throw an exception and anyone calling your bean will get the custom transaction exception you want and will have to deal with notification... I don't recommend this

Resources