Hi arielcarrera ,
what I can say we do not have tests for this type of setup. Besides the quickstart the CDI related code and tests are under cdi submodule narayana/ArjunaJTA/cdi at master · jbosstm/narayana. But even if there is such setup used (what I don't think) there are used WildFly as the app container.
Would you have some (simple) reproducer where the behaviour could be checked?
Hi ochaloup !
I have this sample project (the failed method is TestCase.testSuspendMergeFirst) :
I have this sample project taking as reference two demo projects:
I will take a look to this folder. Thank you.
Hi ochaloup, I tried to do the same test in Arquillian with a managed Wildfly container (Wildfly 17.0.1.Final) like Narayana does, but it fails too.
I made this second project with Arquillian:
Maybe is something in my test code that is wrong and you can take a look... otherwise everybody must use a dependent scoped entitymanager what sounds strange because @RequestScoped should be a valid use case with JPA and JTA.
Hi arielcarrera ,
I was trying to understand what's happening and debugged the code with your reproducers. What I can say all seems to work correctly. Probably it does not work in the way one could expect for the first sight. But I assume there isn't a bug. Let's try to find out...
If you use the @RequestScope for the EntityManager then the same EntityManager is used for any injection (to Repository1 and Repository2). That means that whatever bean injects the EntityManager the same EntityManager is used and the same JDBC connection is taken. The connection is not released when transaction finishes (or is suspended) but it is reused for the next transaction which is not possible. The JDBC connection needs to be "released" before is used for the next transaction.
The EntityManager is an object which is bound not to the Request but to the bean usage. The @Dependent pseudo-scope or maybe rather the @TransactionScoped should be used for that.
Probably, this could uncover an issue with Agroal that should announce that the same connection should not be reused for two different transactions. Do you think it could be an issue? luis.barreiro
I had a discussion on this topic with manovotn (lead of the Weld project) and he confirmed that the current behaviour (from the CDI perspective) is correct.
I hope the investigation and the explanation helps
Hi ochaloup, I've been testing with the transactional scope and it seems to work as one would expect.
While it has the disadvantage that one cannot access the entity manager at any time in the request, taking care to place @Transactional in the methods where it is accessed, or to make a correct transaction management programmatically, beyond any performance issue that may influence I don't find more drawbacks.
All my tests passed successfully.
The dependent pseudo-scope may be a good option for some kind of projects but it's not enough to me. It's not enough if you need to start a transaction at a service layer and you desire to share a persistence context between multiple repository methods.
There are lots of examples using an entity manager with RequestScoped, but if nested transactions are used this is a bad practice.
I tried to repeat my test battery with agroal (which you had recommended to me a long time ago) in an environment with junit, hibernate and narayana (without arquillian) ... but I had not a good result trying to configure JTA
If I delegate the configuration in Hibernate something must be missing and resource is not enlisting in the transaction, and if I add the Agroal's transaction integration to the provider it ends up with more than one resource enlisted per operation (one of hibernate and another of arjuna)... for now I will leave this test aside . It looks like a promising project.
I opened an issue in hibernate to see if they can provide a demo with hibernate-agroal (using transactions).
Thanks for your help.
Hi arielcarrera ,
I see, I got it. I'm still thinking if there is some valid configuration for the RequestScope. As I'm thinking about it more I'm in doubt if there is some missing piece of integration where the pool manager or JPA associates the connection for transaction and that the 'REQUIRES_NEW' associates a new connection until finishes. Interestingly enough the same scenario does not work in WFLY so this is either by design (as discussed in the last comment) or some omission as for WFLY you can use the EJB resource injection (@Resource) that has a different lifecycle than the CDI (it's driven by different code). It would be worthy to investigate how EJB works with the transactions per request (as it should be the default EJB behaviour). I'm putting that to my TODO but I'm not sure when I get to that.
Btw. would you be so kind and link here the issue on hibernate? Have you used the linked project as the base you were investigating the issue with multiple resource enlistments?
Btw2. one technical note. When you talk about 'REQUIRES_NEW' transaction it's not a nested transaction. It's a suspended top level transaction. JTA supports only(!) top-level transactions which could be suspended and then resumed later. The nested transaction is a different transaction model which behaves differently (see some details on the web, something here Narayana Project Documentation).
Thank you for your interest
Hi ochaloup I agree with you. I think the developer does not expect this behavior with RequestScoped and REQUIRES_NEW (you are right I called them wrong in the previous post and mixed with another concept like Spring/Narayana's nested Transactions that although it is not part of JTA spec, exists and it is wrong to call it that, my apologies).
I read on several occasions the JTA, JDBC and CDI spec but I do not remember that it is clear that it should behave like this before a scenario of this type.
As I said before, in many examples and projects are set entity managers with @RequestScoped and I never saw a warning on this topic. In the same source of Hibernate, in the example of Hibernate with CDI this type of SCOPE is used (https://github.com/hibernate/hibernate-demos/tree/master/other/cdi-jpa-testing). If you have contact with the people of Hibernate or with the people currently in Debezium, perhaps you could ask Gunnar Morling who made the demo and a good article (https://in.relation.to/2019/01/23/testing-cdi-beans-and-persistence-layer-under-java-se/ talking about how to configure Hibernate+CDI in standalone environments for testing purpose.
I searched the Jboss and Spring forums and maybe there is the key about how it works with EJB containers.
You can take a look here in the Spring issue (year 2005) about this problem or a very similar one:
and here in the JbossTM issue:
What the Spring guys say about calling the XAResource delist method might make some sense and be necessary to get a new connection for the new transaction and recover the old one later in the call to the suspend method (regardless of whether or not the specification says this, we know that specifications have gray areas).
There is also this issue in the forum:
In this one they make him test a configuration that I don't know if it still exists that is <track-connection-by-tx> without success and then they attribute the problem to a "Lazy JCA enlistment".
I think with this you have a good starting point, if I can help you feel free to contact me.
Btw. here is the issue I opened to see if the people of Hibernate can provide some configuration example with Agroal and Transaction integration since I do not achieve a correct configuration with hibernate-agroal and currently there is not much documentation or examples about it (https://hibernate.atlassian.net/browse/HHH-13535).
About your question, yes, I tried with these projects (that I have send you), testing several configurations. One test I did for example was to enable Agroal Transaction Integration in a custom Provider. I have also tried with a project that has a similar configuration but with a larger test suite but this project integrates Spring Data JPA with Hibernate, Narayana and CDI and it is a little more complex (I have a similar one in my github too but I need to push some changes).