[jboss-jira] [JBoss JIRA] (WFLY-9839) Incorrect lock management in infinispan

Oleg K (JIRA) issues at jboss.org
Thu Feb 15 10:48:00 EST 2018


     [ https://issues.jboss.org/browse/WFLY-9839?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Oleg K updated WFLY-9839:
-------------------------
    Steps to Reproduce: 
1. Create JPA Entity class:
{{{
@Entity
public class MyEntity {
    @Id
    private Long id;
    private String name;
    @Version
    private int verions;
    // getters and setters omitted
}}}

2. One EJB with @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) and long running transactions
{{{
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class MyEntityManagerEJB {
    @PersistenceContext
    private EntityManager em;

    public void updateMyEntity(Long id, String newName) {
        try {
            Thread.sleep(15000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        MyEntity e = em.find(MyEntity.class, id);
        e.setName(newName);
        em.flush();
    }
}
}}}

3. Another EJB which calls first EJB. Also with separate transaction. Here we have an exception at commented line on EVERY LongRunningTransactionEJB.doWork() call. Buf if we change doRefresh to false - all operations are performed OK
{{{
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class LongRunningTransactionEJB {

    @PersistenceContext
    private EntityManager em;

    @EJB
    private MyEntityManagerEJB myEntityManager;

    public String doWork(Long entityId, String suffix) {
        final boolean doRefresh = true;// change this to false - it will pass the test

        MyEntity e = em.find(MyEntity.class, entityId);

        myEntityManager.updateMyEntity(e.getId(), "new name " + suffix);
        if (doRefresh) {
            em.refresh(e);
        }
        myEntityManager.updateMyEntity(e.getId(), "another new name " + suffix);// <--- here we have an exception
        em.refresh(e);
        return e.getName();
    }
}
}}}

  was:
1. Create JPA Entity class:
{{{
@Entity
public class MyEntity {
    @Id
    private Long id;
    private String name;
    @Version
    private int verions;
    // getters and setters omitted
}}}

2. One EJB with @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) and long running transactions
{{{
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class MyEntityManagerEJB {
    @PersistenceContext
    private EntityManager em;

    public void updateMyEntity(Long id, String newName) {
        try {
            Thread.sleep(15000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        MyEntity e = em.find(MyEntity.class, id);
        e.setName(newName);
        em.flush();
    }
}
}}}

3. Another EJB which calls first EJB. Also with separate transaction. Here we have an exception at commented line on EVERY LongRunningTransactionEJB.doWork() call
{{{
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class LongRunningTransactionEJB {

    @PersistenceContext
    private EntityManager em;

    @EJB
    private MyEntityManagerEJB myEntityManager;

    public String doWork(Long entityId, String suffix) {
        final boolean doRefresh = true;// change this to false - it will pass the test

        MyEntity e = em.find(MyEntity.class, entityId);

        myEntityManager.updateMyEntity(e.getId(), "new name " + suffix);
        if (doRefresh) {
            em.refresh(e);
        }
        myEntityManager.updateMyEntity(e.getId(), "another new name " + suffix);// <--- here we have an exception
        em.refresh(e);
        return e.getName();
    }
}
}}}



> Incorrect lock management in infinispan
> ---------------------------------------
>
>                 Key: WFLY-9839
>                 URL: https://issues.jboss.org/browse/WFLY-9839
>             Project: WildFly
>          Issue Type: Bug
>          Components: JPA / Hibernate, Transactions
>    Affects Versions: 10.1.0.Final, 11.0.0.Final
>         Environment: Reproduced on Debian 8 GNU/Linux, 
> Java - openjdk version "1.8.0_131"
>            Reporter: Oleg K
>            Assignee: Scott Marlow
>
> If we update one JPA entity with one id (primary key) in several transactions and refresh (via EntityManager.refresh call) loaded entity between them - infinispan does not release lock for the entity - so one can fail on timeout waiting for that lock to be released.
> The root exception is:
> org.infinispan.util.concurrent.TimeoutException: ISPN000299: Unable to acquire lock after 15 seconds for key 10 and requestor GlobalTransaction:<null>:6:local. Lock is held by GlobalTransaction:<null>:4:local
> 	at org.infinispan.util.concurrent.locks.impl.DefaultLockManager$KeyAwareExtendedLockPromise.lock(DefaultLockManager.java:238)
> 	at org.infinispan.interceptors.locking.AbstractLockingInterceptor.lockAndRecord(AbstractLockingInterceptor.java:193)
> 	at org.infinispan.interceptors.locking.AbstractTxLockingInterceptor.checkPendingAndLockKey(AbstractTxLockingInterceptor.java:193)
> 	at org.infinispan.interceptors.locking.AbstractTxLockingInterceptor.lockOrRegisterBackupLock(AbstractTxLockingInterceptor.java:116)
> 	at org.infinispan.interceptors.locking.PessimisticLockingInterceptor.visitDataWriteCommand(PessimisticLockingInterceptor.java:134)
> 	at org.infinispan.interceptors.locking.AbstractTxLockingInterceptor.visitPutKeyValueCommand(AbstractTxLockingInterceptor.java:65)
> 	at org.infinispan.commands.write.PutKeyValueCommand.acceptVisitor(PutKeyValueCommand.java:78)
> 	at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:99)
> 	at org.infinispan.interceptors.TxInterceptor.enlistWriteAndInvokeNext(TxInterceptor.java:367)
> 	at org.infinispan.interceptors.TxInterceptor.visitPutKeyValueCommand(TxInterceptor.java:221)
> 	at org.infinispan.commands.write.PutKeyValueCommand.acceptVisitor(PutKeyValueCommand.java:78)
> 	at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:99)
> 	at org.infinispan.interceptors.InvocationContextInterceptor.handleAll(InvocationContextInterceptor.java:114)
> 	at org.infinispan.interceptors.InvocationContextInterceptor.handleDefault(InvocationContextInterceptor.java:83)
> 	at org.infinispan.commands.AbstractVisitor.visitPutKeyValueCommand(AbstractVisitor.java:43)
> 	at org.infinispan.commands.write.PutKeyValueCommand.acceptVisitor(PutKeyValueCommand.java:78)
> 	at org.infinispan.interceptors.InterceptorChain.invoke(InterceptorChain.java:335)
> 	at org.infinispan.cache.impl.CacheImpl.executeCommandAndCommitIfNeeded(CacheImpl.java:1672)
> 	at org.infinispan.cache.impl.CacheImpl.putInternal(CacheImpl.java:1121)
> 	at org.infinispan.cache.impl.CacheImpl.put(CacheImpl.java:1111)
> 	at org.infinispan.cache.impl.DecoratedCache.put(DecoratedCache.java:453)
> 	at org.infinispan.cache.impl.AbstractDelegatingCache.put(AbstractDelegatingCache.java:291)
> 	at org.hibernate.cache.infinispan.access.TxInvalidationCacheAccessDelegate.update(TxInvalidationCacheAccessDelegate.java:67)
> 	at org.hibernate.cache.infinispan.entity.ReadWriteAccess.update(ReadWriteAccess.java:29)
> 	at org.hibernate.action.internal.EntityUpdateAction.cacheUpdate(EntityUpdateAction.java:222)
> 	at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:196)
> 	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:582)
> 	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:456)
> 	at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
> 	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
> 	at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282)
> 	at org.hibernate.jpa.spi.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:1300)
> 	at org.jboss.as.jpa.container.AbstractEntityManager.flush(AbstractEntityManager.java:459)
> 	at wildfly.infinispan.test.MyEntityManagerEJB.updateMyEntity(MyEntityManagerEJB.java:36)
> 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 	at java.lang.reflect.Method.invoke(Method.java:498)



--
This message was sent by Atlassian JIRA
(v7.5.0#75005)


More information about the jboss-jira mailing list