How can I get transaction event(commit, rollback) - events

I created a CMT based EJB. The EJB inserts a record into the database and then it executes another code(A) asynchronously. The ejb continues it's processing so the transaction can be committed or rolledback after asynchronous call.
In the code (A) I need to wait until the EJB's transaction committed or rolled back. Then read the record which the EJB inserted or skip next execution.
My question is that can I notified the EJB's transaction event or have to poll until I can read the record.
I'm working on the IBM WebSphere 7.0 (Java EE 5)

The only way to synchronize asynchronously invoked code with transaction events, as far as I know, is to use CDI events. In the code that runs inside the transaction you have to send a CDI event. You can configure the handler of the CDI event to run only on certain transaction outcomes - these handlers are called transactional observers.
I found this page from the JBoss docs that outline the syntax and general concept - see section 11.7
http://docs.jboss.org/weld/reference/latest/en-US/html/events.html
Basically it looks like this
public void refreshCategoryTree(#Observes(during = AFTER_SUCCESS) CategoryUpdateEvent event)
{// only called after the transaction committed successfully }
I don't know about WebSphere but since this is part of the CDI Spec I would assume it should work there as well. I once used this with JBoss and it worked for me. You can even have the handler run inside its own transaction if you want.

Related

Sending rabbitMQ events after transaction commit

I have big task in transaction (#Transactional method). In this task the id-s are collected and then after transaction commit they must be sent to RabbitMQ (with convertAndSend-method). The RabbitMQ-listener in the other side takes the ids and updates the statuses in DB (it's important to update statuses after transaction changes because only after them the updated data is actual)
I have next questions:
What is the best way to use like the hook in the end (commit) of transaction? I need make the one "afterCommit" method for several service classes (many transactional-methods);
What need I use as the storage of ids? I have thought about smth like ThreadLocal variable but this is not a variant - if there is the parallelStream, the new Thread is created;
May be some other solution?
I have read about the delay RabbitMQ plugin but it is not the variant 4 my task - their time is very different.
Looking at the tags in your question I suppose you are using the spring framework.
So you could use Spring Events and its ApplicationEventPublisher to publish your specific ApplicationEvent together with all the necessary data (the ids in your case).
Spring allows you to bind an event listener to a phase of the current transaction. Just use the #TransactionalEventListener annotation on a method that sends the data to RabbitMQ finally. Binding is possible to different transaction phases. With the default binding (AFTER_COMMIT) the event will only be fired if the transaction has completed successfully.
This Baeldung article on Spring Events is a nice place to find more detailed information.

How to select PROPAGATION in spring transaction?

I am just reading the spring-mybatis.xml,here are some code of transaction-manager:
I want to know why some methods defines as "REQUIRED" or "SUPPORTS"?How to think about it and decide which to choose?
Your question is, I think it's about Spring transaction and it's depend on your business logic and how you can control spring transaction.
To understand the Spring transaction "REQUIRED" or "SUPPORTS", you need to understand spring transaction definition. This transaction definition types are come from org.springframework.transaction.TransactionDefinition class. But first you need to understand 1)Spring transaction types and then 2)Spring transaction Definition.
1) Spring supports two types of transaction management:
Programmatic transaction management: This means that you have manage the transaction with the help of programming. That gives you extreme flexibility, but it is difficult to maintain.
Declarative transaction management: This means you separate transaction management from the business code. You only use annotations or XML based configuration to manage the transactions.
2) Spring Transaction Definition
PROPAGATION_REQUIRED:
Spring REQUIRED behavior means that the same transaction will be used if there is an already opened transaction in the current bean method execution context. Create a new one if none exists.
In short this means that if an inner(2nd Transaction) method causes a transaction to rollback, the outer(1st Transaction) method will fail to commit and will also rollback the transaction.
PROPAGATION_SUPPORTS:
Support a current transaction; execute non-transactionally if none exists.
Understandanding these "REQUIRE" "SUPPORTS" is not enough, as I mentioned to you that you need to understand all Spring definition under org.springframework.transaction.TransactionDefinition class.
Unfortunately, I had one power point about this Spring types and transaction which I wrote at Dec 2014 in slideshare website.
Spring Transaction Management
In this slide, I added very important point about Spring transaction in power point note session. So please not only refer to slide content but also refer to slide note session. Hope it help.
Example, refer as power point notes session too for more understanding about Spring transaction definition.
Edited:
Propagation Means: Typically, all code executed within a transaction scope will run in that transaction. However, you have the option of specifying the behavior in the event that a transactional method is executed when a transaction context already exists. For example, code can continue running in the existing transaction (the common case); or the existing transaction can be suspended and a new transaction created. Spring offers all of the transaction propagation options familiar from EJB CMT. To read about the semantics of transaction propagation in Spring, see Transaction Propagation

Spring #Async - no data found in integration test

I'm trying to unit (integration) test a method annotated with Spring's #Async.
The test sets up some data in in-memory h2 database, then runs the asynchronous method. Asynchronous code does not see test data :O
Removing #Async fixes the problem.
Any help? :)
I had the same error. The solution was quite simple for me: I did not put a COMMIT; to the end of my data_init-h2.sql
I presume you did not put this either. If you think about it this is quite logical. Your main thread fires up a transaction but does not actually commit it to h2. Spring fires up another thread and the #Async method is run there in a separate transaction.
Because of the lack of commit you do not see the data changes on this other thread. On the main thread you can see your data changes even before they are committed as you are in that transaction.
The transaction isn't propagated like it was before your #Async.
#Async and #Transactional: not working
Your test could commit the data and delete it either side of the test, removing Spring's automated rollback inside test #Transactionals.
You could create a default-access method that the async method calls into, that your test could also call direct, though you would no longer be testing the Async behaviour.
There's likely a nicer spring implementation that supports what you need, making the transaction available but I don't have it.

Making specific method non transactional in Spring

I have a spring application which is based on Spring Batch. By default spring batch introduces transaction for its steps (i.e. at reader,writer and processor) . There are certain stages where I don't really need transaction to be enabled. Because transaction is enabled unnecessary for these methods its giving me some runtime errors as I am making call to two different databases in one method.
Is there any annotation which spring provides to DISABLE transaction for a specific set of methods ?
OR is there anything available in spring batch which can allow me to get rid of transaction either completely or declarative
I am even open to the solution which can disable transaction globally.
Any link , paper will greatly be appreciated.
Thanks in advance
Samir
Spring Batch is inherently transactional. Even if your datasources are not transactional, the semantics of the JobRepository require it. The closest you can get with Spring Batch and not being transactional is using the ResourcelessTransactionManager. This transaction manager is essentially a no-op transaction manager that just keeps track of if an operation is within the scope of a transaction or not.

what exactly "Propagation.REQUIRES_NEW" means using Spring transaction management?

my confusion related to this matter is that how we can use a previously created transaction? or in other words how many threads a transaction could be related to?
A transaction can be related to only one thread in spring. Well, with some effort you can make it a long-running transaction, but that's an anti-pattern afaik.
REQUIRES_NEW means that whenever the program flow enters the annotated method, a new transaction will be started regardless of any existing transaction.
REQUIRED means that an existing transaction will be reused, or if there's no existing transaction a new one will be started.

Resources