Transaction logging When rollback - spring

I have a requirement to log the transaction to Database irrespective of commit or rollback. Incase of Transaction rollback, while all the tables gets rolled back, I want to insert a record to Transaction log table. Please suggest the best approach.

Spring generates traces for every rollback. Use an appender from your logging framework that inserts into your log table.

Related

Do we need to add any configuration on client side to avoid transaction retry errors in cockroach database

when there is concurrent updates happening on the same record, transaction 1 is able to update but as per the cockroach database documentation transaction t2 should be on queue, but transaction t2 is immediately failing. Do we need to add any other configuration to make transaction wait in queue instead of it throwing an immedaite retry transaction error. Thanks in advance
Yes, the client should handle transaction retry errors. Note that whenever possible, CockroachDB will auto-retry a transaction internally without notifying the client. CockroachDB will only send a serialization error to the client when it cannot resolve the error automatically without client-side intervention. In this case, cockroach provides client side tools to manually or automatically retry the txn. See the docs here.
As per CockroachDB Documentation
CockroachDB always uses SERIALIZABLE isolation, which is the strongest
of the four transaction isolation levels defined by the SQL standard
and is stronger than the SNAPSHOT isolation level developed later.
SERIALIZABLE isolation guarantees that even though transactions may
execute in parallel, the result is the same as if they had executed
one at a time, without any concurrency.
I am assuming you are using Spring Boot for you application and Spring Data for Database operations.
If there are concurrent updates in the database, it's always good to use SELECT FOR UPDATE when you are using sql query. Similarly, #Locks which does the same in JPA.
#Lock(LockModeType.PESSIMISTIC_READ)
#QueryHints({#QueryHint(name = "javax.persistence.lock.timeout", value = "3000")})
public Optional<Employee> findById(Long employeeId);
For more information you can refer documentation.

Transacted Route and Transactional Endpoints, Transaction commit order

My route looks like below
from("jms:queue:IN_QUEUE) //(A) Transactional Endpoint
.transacted("required") //(B) TX Policy with PROPAGATION_REQUIRED and JPATxManager
.bean("someBean", "readFromDB()") //(C) Read from DB
.bean("someBean", "writeToDB()") //(D) Write to DB
.to("file:/home/src?fileName=demo_${id}.txt")
I know the JMS consumer at (A) will fork out JMS Transaction on each poll and attaches to the
thread.
Also the transacted node in (B) will fork out JPA transaction after an exchange reaches there
and attaches to the thread.
Please find my questions below:
Can two different transactions get attached to a single thread (like the one above) ?
If Yes, which one should get suspended ?
What should be the commit and rollback order of the above mentioned route ?
Note: I didn't find any obvious answer from Camel In Action 2nd Ed book, So please guide me
Good afternoon,
This is a variation on your other question.
The:
from("jms:queue:IN_QUEUE) //(A) Transactional Endpoint
endpoint is transacted, meaning that you have marked the JMS component as transacted and the JMS sessions will be managed by a JmsTransactionManager.
.transacted("required") //(B) TX Policy with PROPAGATION_REQUIRED and
JPATxManager
This should not be a JPA transaction manager, but a JTA transaction manager (like Arjuna). As in your other question, you now have a JMS local transaction for reading you message, and local JPA transacted sessions for your DB access. You want the PlatformTransactionManager (a JTA transaction manager) to synchronize the local transactions for you.
As to your questions:
Can two different transactions get attached to a single thread (like the one above) ?
That really doesn't make any sense.
If Yes, which one should get suspended ?
Nothing will get suspended.
What should be the commit and rollback order of the above mentioned route ?
The DB read is not transactional and does not need to be committed. The file write will actually happen as the JTA transactional context is closed. This leaves the DB write. If that fails, then the DB read does not matter, the message will get put back on the source destination and the file write will not be called.
Enabling the DEBUG logging for the various transaction managers is very helpful.
I could go on about this with this in painful detail. This is more for burki. I think that you will really appreciate this. Very subtle, and it happens a lot.
from("jms:queue:SRC_QUEUE")
.transacted("required")
.to("jms1:queue:DEST_QUEUE")
What happens if the two endpoints are marked as transacted ... but... you do not have the 'transacted' line? Well, a JMS local transaction was started on the message listener. This will be committed as the route ends. There are two independent local JMS transactions. These are not synchronized by a JTA transaction manager.
What actually happens is that the commit for the message 'get' is called. There is no actual commit for the message 'put'. The message 'put' is committed when the JMS session is closed. This is in the JMS spec, that closing the connection inherently commits any transaction. So, because there is no linkage between the two components, the 'get' is committed, and then the 'put' session is closed.
This means that you can lose messages if there is an outage between the commit for the message 'get' and the session close for the message 'put'.
Does that make sense? There is no linkage between the local transactions, so Camel closes them in order, starting with committing the 'get' before calling the 'put'.
JTA transaction synchronization is the key. You still have local transaction resources (not XA), but they can be very well managed in a pretty lightweight JTA transactional context.
from("jms:queue:SRC_QUEUE")
.transacted("required")
.to("DB:transactedwrite")
.to("jms1:queue:DEST_QUEUE")
I couldn't be bothered to look up the correct syntax for a database insert, but you get the idea. In this case, you can get duplicate DB inserts if the JMS 'put' fails. This is not 'all or nothing' XA transactions. The transactions are committed in order. If one in the middle succeeds, then the next transaction fails, well the 'get' will get rolled back and you will get duplicates up to the point of failure.
Sorry, I can't answer your specific questions, but I can give some specific infos about the transactions of your route.
You've got 3 different "systems" with different transaction "scopes"
A JMS broker from which you consume
A database you read and write from and you configured a JPA TxManager for
A file system (no transactions at all) as destination
First of all, if you want to have transaction safety across JMS and the database you have to use XA transactions.
Then, it is unclear if you expect the JMS consumer to be transacted (because of the transacted() in your route) or if you really configured a JMS connection with local JMS transactions. I assume that you really consume transacted.
Let's talk about what you got without line B of your route:
You consume transacted from the broker
Camel processes the message through your route
When any error occurs during route processing, the message is not committed on the broker and therefore redelivered to your route
The transaction that is opened by a transactional consumer is kept open by Camel until the route is successfully processed.
So the only obvious problem would be an error after the database write, that triggers a redelivery and the database write is done once again. Probably the write is not idempotent and therefore must not happen twice.
So to solve these problems, you either have to use XA transactions or you simply use local JMS transactions and implement compensation logic for the "gaps" like the one described above.
The database transaction on the other hand has no benefit unless the read and write operation must be done in a transaction (but I have doubts that this is the case with two individual bean calls and a JMS consumer).

would setAutoCommit(false) during quartz job affected by other queries?

I have a quartz job that is wired with spring datasource to perform database partition.
I understand setAutoCommit(false) will start a transaction until rollback or commit are called. However I don't know if the transaction will include other queries from spring webservlet by users access the webpage during the quartz partition, from setAutoCommit(false) until setAutoCommit(true)?
So if any servlet query gets error, this would cause rollback to my whole partition transaction.

Spring transaction management records are not inserted into db table after transaction is commited

I am using Spring transaction management using Hibernate Transaction Manager. I have declarative transactions configured on a class. Transaction starts and commits. But while commiting its not inserting any records to table. Not able to see any Insert table log message. Is transaction uses some other hibernate session object. How to make it to use session object currently in use.

Spring Transaction Management and Oracle Stored procedures

I am currently integrating transaction management into my code.
I am trying to set it up against stored procedures that already exist.
The stored procedures have a commit at the end of them.
In my eclipse console, I can see the transaction management code being invoked
datasource.DataSourceTransactionManager Initiating transaction rollback
datasource.DataSourceTransactionManager Rolling back JDBC transaction on Connection [oracle.jdbc.driver.LogicalConnection#1544055]
datasource.DataSourceTransactionManager Releasing JDBC Connection [oracle.jdbc.driver.LogicalConnection#1544055] after transaction
But I can still see remains of the record that should have been rolled back in my database tables.
If we use spring transaction management, should we remove all commits from our stored procedures?
Thanks
Damien

Resources