Arquillian and TransactionAttributeType.REQUIRES_NEW - java

In my arquillian test a number of application methods are called, which either read data from the database or create data and persist to database. a) At some point a method annotated with #TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) is called. The test fails as the annotated method cannot find(on read it returns 0 records) some data persisted by some previous called methods(annotated with TransactionAttributeType.REQUIRED). Probably this is a normal behavior as a new Transaction opens. Reading the data in a previous called method and passing them as parameters to the annotated(TransactionAttributeType.REQUIRE) method works fine, but data should be read inside the REQUIRES_NEW method. Same problem appears in other tests when the TransactionAttributeType.REQUIRES_NEW is used. Is there a workaround to handle this case?
b) I've also mentioned that arquillian has issues with methods annotated with #TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED). It is like the code in these methods is not executed at all.
My current solution for both issues is to create a Mock class overriding the problematic methods. In case of b, the overridden method is annotated with #TransactionAttribute(TransactionAttributeType.SUPPORTS).

Try using flush() method and then refresh() of EntityManager before calling the method annoted with TransactionAttributeType.REQUIRED_NEW.

Related

Transactional method called by method in same class called from another class

I have a transactional method that is called called multiple time (in a loop) by a method in the same class.
This method in the same class is called by a method in a different class.
From my investigation, when we call a transaction method within the same class, this has no effect. The same transaction is used.
But in my case, will a new transaction be used?
Structure:
A.class - Method A
|-> B.class - Method A
|-> call mutiple times - B.class - #Transactional Method B
Can you advise?
My expectations is that a new transaction on Method B is created each time I loop through it.
Do I need to pass the Method B to a different class? Or it will start a new transaction every time?
So BY DEFAULT two things are potentially working against you.
Spring's default txn interceptors, which is how AOP transactions work, will not pick up calls within the same instance. This can be changed by switching to AspectJ weaving. This article has a good explanation https://www.baeldung.com/spring-aop-vs-aspectj IIRC the default in spring is jdk proxying.
Spring's default transactional annotation will propagate existing txns. So if there's not a pre-existing txn AND you overcome the above you should get what you want. If there's a pre-existing txn, it will by default be used, but this behaviour can be changed by modifying the propagate parameter on your #Transactional annotation. This article has a good explanation: https://www.baeldung.com/spring-transactional-propagation-isolation

Is it possible to Invoke query method in EntityListener callback methods?

I have a question is it possible to invoke Query or EntityManager method in EntityListener callback methods, or is there any other solution similar to EntityListener?
EntityListeners are classes whose methods gets called by JPA when the condition are satisfied. Thes classes are instantiated when required and there's no way to pass any value to the constructor.
The only way to do this is getting the EntityManager from an external class in the method you need to use it. Search HibernateUtils to get an example of this External Class.
Here you are as well a complete example of that: https://gist.github.com/yusufcakmak/215ede715bab0e1d6489

interdependency of data between two methods called inside single method which is marked as #Transactional and both methods use different db connection

In java, if I am keeping method as #transactional and inside that method calling another method of another jar which uses another db connection and dependent on data which will be received before calling it..issue is as both methods use different db connection..when second method tries to use data returned from first one find it "data not found" as the first method inside that whole method will be commited at the end because of #transactional status. what is the solution for this?

Spring Propagation.REQUIRES_NEW

In my understanding newPrint method in the following code should create a new transaction but apparently it prints out the same transaction-status object as was used in oldPrint method. I am calling oldPrint from another class. Is it because newPrint is being called using this? If yes, then when will a new transaction get created? If I call both methods from another class two separate transaction will be created anyway because #Transactional is used at class level.
#Transactional
public class Unsubcriber {
#Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void newPrint() {
System.out.println(TransactionAspectSupport.currentTransactionStatus());
}
public void oldPrint() {
System.out.println(TransactionAspectSupport.currentTransactionStatus());
newPrint();
}
Output:
org.springframework.transaction.support.DefaultTransactionStatus#3bacd0e7
org.springframework.transaction.support.DefaultTransactionStatus#3bacd0e7
What would be the scenario when Propagation.REQUIRES_NEW would work?
Assuming geoand's edit clarification is true, the answer to your question is Spring uses AOP proxies to apply the transaction restrictions. So, this will work when calls come into you Unsubscriber from outside, which can then be intercepted and the transaction boundaries can be applied. If you're calling it from within your class, as you said, using 'this', then there is no proxying that can be done and hence your #Transactional will not come into play.
Here are few rules of #Transactional worth mentioning
1.#Transactional annotations only work on public methods. If you have a private or protected method with this annotation there’s no (easy)
way for Spring AOP to see the annotation. It doesn’t go crazy trying
to find them so make sure all of your annotated methods are public.
2.Transaction boundaries are only created when properly annotated (see above) methods are called through a Spring proxy. This means that
you need to call your annotated method directly through an #Autowired
bean or the transaction will never start. If you call a method on an
#Autowired bean that isn’t annotated which itself calls a public
method that is annotated YOUR ANNOTATION IS IGNORED. This is because
Spring AOP is only checking annotations when it first enters the
#Autowired code.
Source - http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/
What you are seeing is a class misconception about Spring AOP.
Since newPrint() is being called from a method inside the same class, no advice is triggered and therefor no handling for transactional takes place.
Had you called the method newPrint() outside the class, a new transaction would be created whether or not the caller already participated in a transaction.
Since you have used #Transactional on the class, every method get's the default #Transactional settings and that is why you actually have a transaction.
Take a look at this section of the Spring reference documentation for a detailed discussion on how AOP works in Spring.
A total hack to get your code working like you expect would be the following:
((Unsubcriber ) AopContext.currentProxy()).newPrint();
This solution is mentioned in various places among which is this SO post.
Calling a method from within a class (using this) means that it will not go through the transaction initialisation contained within Spring's proxy object. Since the this keyword is a pointer to an instance of your original object, not the transaction aware, enhanced Spring object.
The annotations will work as expected in scenarios such as:
object1.oldPrint();
object1.newPrint();

Validating calls within a method using Mockito or jUnit

I'm working on some modifications to a DAO. The modifications included refactoring some code to keep a couple of methods from calling .getResultsList() multiple times. Instead, the results are cached to a List and all subsequent code works with that list making the code run more efficiently by only reaching out to the database once.
I was asked to create jUnit tests for the methods I modified to ensure that something like this won't happen again in the future. Is it possible for me to validate how many times a local variable inside a method has a function called on it using mockito?
I've seen several questions/forum posts on using verify to validate the number of calls made on a mocked object. But I don't actually have access to mock this object as it is being created inside the method any not being passed in.
Basically -
myDao has a class variable EntityManager called em, the em.createNamedQuery() function is stored to a TypedQuery variable q. This q is what .getResultsList was being called on multiple times.
In my jUnit test, is it possible to listen to what's happening inside the method I'm calling on my mocked Dao and make sure that q.getResultsList is only called once while the method is running?
UPDATE
myDao in my test class is configured using the #Autowired annotation like so:
#Autowired
MyDao myDao;
It is defined in the applicationContext.xml like so:
<bean id="myDao" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.mypackage.myDao"/>
</bean>
The method I'm calling is inside that DAO, so I call myDao.myMethod(myVar); Inside myMethod is the q variable I'm wanting to listen to. It's a local variable.
If you are mocking myDao then you aren't going to be able to validate code within myDao.
To test this you need a test for the myDao class. In that unit test you can mock EntityManager and have createNamedQuery return a mocked query. Then you can use mockito's verify and times(1) to verify that getResultsList() was only called once on the mocked query.

Categories

Resources