I am using JTA UserTransaction to perform some database and JMS related activity.
The problem goes as below.
1.Start UsertTransaction
2.Perform DB search operation
3.Perform DB updated operation
4.Perform JMS send and recieve operation----> Problematic work flow
5.Perform DB updated operation
6.Commit the transaction.
The 4th step is creating problem as the message sent would not be persisted in the queue until the transaction is committed and due to this JMS receive functionality is broken.
Step 4 cant be performed before stating the JTA transaction as there is lot of dependency on the other steps.
Is there any way I can handle this type of situation.IS there any way to bypass transaction for step4? Any help appreciated.
Thanks
Related
I'm trying to understand how transaction works in Spring AMQP. Reading the docs: https://docs.spring.io/spring-amqp/reference/html/#transactions , I know the purpose for enabling transaction in publisher (Best Effort One Phase Commit pattern) but I have no idea why it could be necessary in MessageListener?
Let's take an example:
acknowledgeMode=AUTO
Consume message using #RabbitListener
Insert data into database
Publish message using rabbitTemplate
According to docs: https://docs.spring.io/spring-amqp/reference/html/#acknowledgeMode, if acknowledgeMode is set to AUTO then if any next operation fails, listener will fail too and message will be returned to queue.
Another question is whats the difference between local transaction and external transaction in that case (setting container.setTransactionManager(transactionManager()); or not)?
I would appreciate some clarification :)
Enable transactions in the listener so that any/all downstream RabbitTemplate operations participate in the same transaction.
If there is a failure, the container will rollback the transaction (removing the publishes), nack the message (or messages if batch size is greater than one) and then commit the nacks so the message(s) will be redelivered.
When using an external transaction manager (such as JDBC), the container will synchronize the AMQP transaction with the external transaction.
Downstream templates participate in the transaction regardless of whether it is local (AMQP only) or synchronized.
The below is my requirement:
1. An MDB receives a message
Triggers a asynchronous method in another session bean - asynchronous because this method will be a long running thread and we don't want to hold the MDB thread for long time. The asynchronous method read's records from DB, processes them and calls #3.
Writes to another MQ and then inserts some data into DB. POSTING TO MQ and DB INSERT should be in one transaction.
Here is the implementation :
For #1 - Using an MDB - container managed transaction without any transaction attribute.
For #2 - A stateless session bean - container managed, asynchronous, but transaction attribute as NOT_SUPPORTED (not supported because this is a long running thread, so don't want the transaction to be timed out).
For# 3 - A stateless sessions bean (invoked from #2 for every record that's being read in 2 - executed in a loop) - transaction attribute - REQUIRES_NEW because this method posts to MQ and Inserts into DB.
Issues:
Runtime Exception - When I throw a run time exception from #3, the next records are not processed - the session bean just exits.
Exception - When throwing a custom exception, the message on the queue is not reverted when DB insert fails.
What is the best way to implement or resolve this issue.
I did my best to give details - appreciate any help on this.
I have spring boot application, that makes update in two database Postgres. I use Atomikos for distributed transaction management.
I see that my application makes query in both database each 10 seconds:
"SELECT gid FROM pg_prepared_xacts where database = current_database()"
I'm wonder why? Has atomikos some property for changing period? For example 1 minute. What will be if query returns some gids?
I had looked internet hard about this question, but didn't find the answer.
I have some assumption, and I want to know the right answer.
Why does Atomikos ping pg_prepared_xacts?
It calls "recovery scan" and aim is recovering after failing of application, or error in application. Because of it, in database will not be "orphaned" prepared transactions created by Atomikos.
Has atomikos some property for changing period?
Yes, it has: com.atomikos.icatch.recovery_delay. Other useful properties are here: JtaProperties
What will be if query returns some gids?
Atomikos checks if returned gids are in atomikos transaction log and have status "to commit". If it's so, he will commit prepare transactions, else he will rollback transactions. Note, that Atomikos will handle prepare transactions, that were created by him, and will not handle other prepare transactions.
It´s more of a conceptual question: I currently have a working activemq queue which is consumed by a Java Spring application. Now I want the queue not to permanently delete the messages until the Java app tells it the message has been correctly saved in DB. After reading documentation I get I have to do it transactional and usa the commit() / rollback() methods. Correct me if I'm wrong here.
My problem comes with every example I find over the internet telling me to configure the app to work this or that way, but my nose tells me I should instead be setting up the queue itself to work the way I want. And I can't find the way to do it.
Otherwise, is the queue just working in different ways depending on how the consumer application is configured to work? What am I getting wrong?
Thanks in advance
The queue it self is not aware of any transactional system but you can pass the 1st parameter boolean to true to create a transactional session but i propose the INDIVIDUAL_ACKNOWLEDGE when creating a session because you can manage messages one by one. Can be set on spring jms DefaultMessageListenerContainer .
ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE
And calling this method to ack a message, unless the method is not called the message is considered as dispatched but not ack.
ActiveMQTextMessage.acknowledge();
UPDATE:
ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE can be used like this :
onMessage(ActiveMQTextMessage message)
try {
do some stuff in the database
jdbc.commit(); (unless auto-commit is enabled on the JDBC)
message.acknowledge();
}
catch (Exception e) {
}
There are 2 kinds of transaction support in ActiveMQ.
JMS transactions - the commit() / rollback() methods on a Session (which is like doing commit() / rollback() on a JDBC connection)
XA Transactions - where the XASession acts as an XAResource by communicating with the Message Broker, rather like a JDBC Connection takes place in an XA transaction by communicating with the database.
http://activemq.apache.org/how-do-transactions-work.html
Should I use XA transactions (two phase commit?)
A common use of JMS is to consume messages from a queue or topic, process them using a database or EJB, then acknowledge / commit the message.
If you are using more than one resource; e.g. reading a JMS message and writing to a database, you really should use XA - its purpose is to provide atomic transactions for multiple transactional resources. For example there is a small window from when you complete updating the database and your changes are committed up to the point at which you commit/acknowledge the message; if there is a network/hardware/process failure inside that window, the message will be redelivered and you may end up processing duplicates.
http://activemq.apache.org/should-i-use-xa.html
Hi please can anyone help me out on how to handle multiple transaction in spring. For example i am trying to register an user in my application. I have collected data from my UI layer.now i need to do the following activities
save the data into multiple tables in database.
need to send an email & sms to the user containing username and password
send an notification email to admin
update some other table value.
Now if something goes wrong in above 4 steps application should able to revert everything and display the error message.
How can I handle these task in spring??
You need to wrap your Database modification into a Service with #Transactional annotation and change the order about what you just said.
//This two step in the same service with #Transactional annotation.
1. save the data into multiple tables in database.
2. update some other table value.
//Once you save on database and everything it´s ok you can send emails without any problem since you dont have to rollback.
3. send an email & sms to the user containing username and password
4. send an notification email to admin
There is no way to treat email-sending as a transactional resource the same as a database! Once an email has been sent, it is difficult to call it back. In this field there simply is the infrastructure missing that provides all that handy transactional committal and rollback functionality that you get with databases.
Your best work-around is to send your emails after your database updates have been successfully committed. You can make your database updates transactional with Spring's DataSourceTransaction Manager and #Transaction or one of the other "two-thousand" ways of doing this with Spring.
To do the post-transaction committal sending of your email, check this question. Personally, I favor the idea to use a transaction after commit hook to send "email-trigger-messages" to a standalone Message Queue like HornetQ. That way, you can use the queue's out-off-the-box failover mechanism to ensure that your emails will definitely get be delivered.