You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@aries.apache.org by "Grzegorz Grzybek (Jira)" <ji...@apache.org> on 2021/06/14 07:30:01 UTC

[jira] [Commented] (ARIES-2050) Aries JPA 2.7 shouldn't always reuse EM instance from previous coordinations

    [ https://issues.apache.org/jira/browse/ARIES-2050?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17362761#comment-17362761 ] 

Grzegorz Grzybek commented on ARIES-2050:
-----------------------------------------

With my test, a scenario with REQUIRED → REQUIRES_NEW leads to this situation inside EMSupplierImpl:
{noformat}
result = {java.util.ArrayList@17622}  size = 3
 0 = {org.apache.felix.coordinator.impl.CoordinationHolder@17459} "org.apache.felix.coordinator.impl.CoordinationImpl@47"
  coordination: org.apache.felix.coordinator.impl.CoordinationImpl  = {org.apache.felix.coordinator.impl.CoordinationImpl@17478} 
   name: java.lang.String  = "txInterceptor.fuse.jpa.jta.test.service.TestService.performTest"
   variables: java.util.Map  = {java.util.HashMap@17482}  size = 2
    {@4706} "interface javax.transaction.Transaction" -> "REQUIRED"
    {@4435} "interface javax.persistence.EntityManager" -> {java.util.HashMap@17489}  size = 1
     key: java.lang.Class  = {@4435} "interface javax.persistence.EntityManager"
     value: java.util.HashMap  = {java.util.HashMap@17489}  size = 1
      "fuse.jpa.jta.test.JpaPersistenceUnit" -> {org.hibernate.internal.SessionImpl@17649} "SessionImpl(2115685679<open>)"
...
 1 = {org.apache.felix.coordinator.impl.CoordinationHolder@17460} "org.apache.felix.coordinator.impl.CoordinationImpl@4a"
  coordination: org.apache.felix.coordinator.impl.CoordinationImpl  = {org.apache.felix.coordinator.impl.CoordinationImpl@17471} 
   name: java.lang.String  = "txInterceptor.fuse.jpa.jta.test.service.NewTxTestService.testNewTransaction"
   variables: java.util.Map  = {java.util.HashMap@17475}  size = 2
    {@4706} "interface javax.transaction.Transaction" -> "REQUIRES_NEW"
    {@4435} "interface javax.persistence.EntityManager" -> {java.util.HashMap@17634}  size = 1
     key: java.lang.Class  = {@4435} "interface javax.persistence.EntityManager"
     value: java.util.HashMap  = {java.util.HashMap@17634}  size = 1
      "fuse.jpa.jta.test.JpaPersistenceUnit" -> {org.hibernate.internal.SessionImpl@17611} "SessionImpl(1734890509<open>)"
...
 2 = {org.apache.felix.coordinator.impl.CoordinationHolder@17461} "org.apache.felix.coordinator.impl.CoordinationImpl@4b"
  coordination: org.apache.felix.coordinator.impl.CoordinationImpl  = {org.apache.felix.coordinator.impl.CoordinationImpl@17465} 
   name: java.lang.String  = "jpa"
   variables: java.util.Map  = {java.util.HashMap@17468}  size = 0
{noformat}

Note that two TX-related coordinations (pushed by TxInterceptor) have:
* an attribute under {{javax.transaction.Transaction.class}} key
* different value under {{javax.persistence.EntityManager.class}} key - EMSupplierImpl doesn't always pick up the top-most coordination.

The quick summary of the change is:
* {{org.apache.aries.transaction.TxInterceptorImpl#preCall()}} doesn't necessarily create new coordination. For example for REQUIRED, if there already is a transaction, no new coordination is required. However if there's REQUIRES_NEW after REQUIRED, a new coordination is always needed.
* Assuming the above, {{org.apache.aries.jpa.support.impl.EMSupplierImpl#getTopCoordination()}} selects first (starting from the bottom) coordination that has {{javax.transaction.Transaction.class}} variable - this coordination will be selected to store the EntityManager instance.

> Aries JPA 2.7 shouldn't always reuse EM instance from previous coordinations
> ----------------------------------------------------------------------------
>
>                 Key: ARIES-2050
>                 URL: https://issues.apache.org/jira/browse/ARIES-2050
>             Project: Aries
>          Issue Type: Bug
>    Affects Versions: jpa-2.7.2
>            Reporter: Grzegorz Grzybek
>            Assignee: Grzegorz Grzybek
>            Priority: Major
>
> I have a scenario consisting of the following call graph:
> {noformat}
> testService.performTest() [ @Transactional(TxType.REQUIRED) ]
> +-- List<Car> cars = carDao.getAllCars()
> |   +-- return em.createQuery("select c from Car c", Car.class).getResultList()
> |       (em is injected using @PersistenceContext(unitName = "xa-test-unit"))
> |
> +-- carDao.createNew(car);
> |   +-- em.persist(car);
> |
> +-- newTxTestService.testNewTransaction(transactionManager.getTransaction()) [ @Transactional(TxType.REQUIRES_NEW) ]
>     +-- List<Car> cars = carDao.getAllCars();
>         +-- return em.createQuery("select c from Car c", Car.class).getResultList()
> {noformat}
> The problem is that inside the method marked with {{@Transactional(TxType.REQUIRES_NEW)}} the {{em}} proxy uses the same underlying {{em}} instance because of:
> {code:java}
> Coordination getTopCoordination() {
>     Coordination coordination = coordinator.peek();
>     while (coordination != null && coordination.getEnclosingCoordination() != null) {
>         coordination = coordination.getEnclosingCoordination();
>     }
>     return coordination;
> }
> {code}
> And even if the suspended transaction is not yet committed, the em returns the persisted (but not yet committed) cars.
> The coordination stack consists of (names of coordination objects):
> * txInterceptor.org.apache.aries.jpa.container.itest.bundle.blueprint.impl.TestServiceImpl.performTest
> * txInterceptor.org.apache.aries.jpa.container.itest.bundle.blueprint.impl.NewTxTestServiceImpl.testNewTransaction
> * jpa
> the top coordination contains {{em}} variable associated with suspended transaction.
> I'm working on a solution that properly assigns _current_ em respecting tx-demarcated coordinations.
> [~cschneider], [~gnodet], [~jbonofre] if you have an idea about the best solution, please share.
> For now I think both aries-jpa and aries-blueprint-transaction have to be fixed (the latter one should put some magical variable to the coordination objects pushed inside {{org.apache.aries.transaction.TxInterceptorImpl}})



--
This message was sent by Atlassian Jira
(v8.3.4#803005)