Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] Odd optimistic lock exception behavior

Hi Chris,

No the only operations in this method are the bulk DELETE and the bulk UPDATE calls I mentioned below.  When I step through the code in the debugger the OLEX is triggered when the bulk UPDATE's executeUpdate is run.

This only happens when the Foo table is empty. If I first check the Foo table to see if it is empty and skip the DELETE call if it is the bulk UPDATE's executeUpdate runs fine. This is the work around I currently have in place.

Let me provide some more color on the environment this call is done in.

The entry point is a JSF2 page which when it renders it display values (if any) contained in Foo table.  

When a button is clicked on this page the backing bean (@Managed) which contains a couple of injected (via @EJB) EJBs (EJB1 and EJB2), makes a call to a method on EJB1 which is annotated with @Asynchronous.  EJB1 contains an injected EntityManager via the @PersistenceContext detailed below.  EJB1 also injects EJB2. 

This @Asynchronous method on EJB1 calls the method I outlined below which is on EJB2. EJB2 injects the same unitName that is injected into EJB1.  The method on EJB2 called by EJB1 is marked with @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) and makes the bulk DELETE and UPDATE. 

While the @Asychronous method is being executed in its own thread the JSF lifecycle transitions into the RENDER phase and the managed backing bean (in the original thread) makes some calls to EJB2 which involved reading from Foo. 

Things to note.  First, the bulk DELETE and UPDATE occur in their own thread spawned by @Asynchronous, which is obviously different from the thread the @Managed bean is running in which called it.  Second, the two EJBs involved here both inject their EntityMangers the same way:

@PersistenceContext(unitName = "PRODUCTION")
private EntityManager entityManager;

Third, the isolation level is READ_COMMITTED. 

-Noah

On Aug 9, 2012, at 8:34 AM, Christopher Delahunt <christopher.delahunt@xxxxxxxxxx> wrote:

> Hello Noah,
> 
> The exception shows it is coming from a getSingleResult call on line 133, not an executeUpdate.  Are there any other operations in this method that could result in the exception? 
> 
> Best regards
> Chris
> 
> On 2012-08-08, at 7:39 PM, Noah White <emailnbw@xxxxxxxxx> wrote:
> 
>> 
>> Hi folks,
>> 
>> Hoping someone can shed some light on the following behavior.  I have a no-interface stateless EJB 3.1 bean with the following method and injected JTA persistence context deployed to Glassfish 3.1.2 w/Eclipselink 2.3.2v20111125-r10461.
>> 
>> This method is fired by an @Asynchronous method on another EJB.  This other method is itself fired as the result of a JSF2 managed bean method call triggered by a form submit.
>> 
>> 
>> @PersistenceContext(unitName = "PRODUCTION")
>> private EntityManager entityManager;
>> 
>> @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>> pubic void resetAll() {
>> 
>> ...
>>   Query q = entityManager.createQuery("DELETE FROM Foo");
>>   q.executeUpdate();
>>   Query p = entityManager.createQuery("UPDATE Bar b SET b.dirty=false WHERE b.dirty=true");
>>   p.executeUpdate
>> ...
>> }
>> 
>> p.executeUpdate is throwing an OptimisticLockException. What's odd is that entity Bar does not have a @Version property or field whereas Foo does. 
>> 
>> As I mentioned the thread which triggered the @Asynchronous EJB method is a JSF managed bean method fired as the result of a POST. During the JSF lifecycle of the POST additional methods are call which update information on the page. This information involves the Foo entity.  One thought was this had something to do with the TX in the above call and the TX in the managed bean that is fetching Foo information during the post POST render lifecycle and that this was being caused by the TX isolation level. However, I confirmed that the iso level is READ_COMMITED so I don't see that as being the problem. 
>> 
>> Interestingly, this only happens if there are no Foo entities, that is to say when the Foo table is empty.  Once there is at least one row in Foo this method will execute trouble free without the OLEX being thrown.  I am guessing this is because the DELETE returns 0 updated rows since the table is empty and this is interpreted as an OLEX but why is this not being triggered/thrown when q.executeUpdate is called as opposed to when p.executeUpdate is being called? Could this be due to the fact I am using batch-writing and the UPDATE is what is actually triggering the flush?
>> 
>> This is against an Oracle 10g DB w/the ojdbc6.jar thin driver.  My persistence.xml also has the following which may (or may not) be relevant:
>> 
>> eclipselink.jdbc.native-sql "true"
>> eclipselink.jdbc.batch-writing "Oracle-JDBC"
>> 
>> This is the stack trace:
>> 
>> Caused by: javax.persistence.OptimisticLockException: Exception [EclipseLink-5011] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.OptimisticLockException
>> Exception Description: One or more objects cannot be updated because it has changed or been deleted since it was last read
>>  at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:782)
>>  at org.eclipse.persistence.internal.jpa.EJBQueryImpl.performPreQueryFlush(EJBQueryImpl.java:1298)
>>  at org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeReadQuery(EJBQueryImpl.java:434)
>>  at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getSingleResult(EJBQueryImpl.java:773)
>>  at com.abc.FooBean.resetAll(FooBean.java:133)
>>  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>>  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>>  at java.lang.reflect.Method.invoke(Method.java:601)
>>  at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
>>  at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
>>  at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5388)
>>  at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
>>  at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
>>  at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
>>  at org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:42)
>>  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>>  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>>  at java.lang.reflect.Method.invoke(Method.java:601)
>>  at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
>>  at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
>>  at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
>>  at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
>>  at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:144)
>>  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>>  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>>  at java.lang.reflect.Method.invoke(Method.java:601)
>>  at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
>>  at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
>>  at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:370)
>>  at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5360)
>>  at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5348)
>>  at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:214)
>>  ... 39 more
>> Caused by: Exception [EclipseLink-5011] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.OptimisticLockException
>> Exception Description: One or more objects cannot be updated because it has changed or been deleted since it was last read
>>  at org.eclipse.persistence.exceptions.OptimisticLockException.batchStatementExecutionFailure(OptimisticLockException.java:79)
>>  at org.eclipse.persistence.internal.databaseaccess.ParameterizedSQLBatchWritingMechanism.executeBatchedStatements(ParameterizedSQLBatchWritingMechanism.java:148)
>>  at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.writesCompleted(DatabaseAccessor.java:1707)
>>  at org.eclipse.persistence.internal.sessions.AbstractSession.writesCompleted(AbstractSession.java:3836)
>>  at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.writesCompleted(UnitOfWorkImpl.java:5520)
>>  at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:448)
>>  at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:780)
>>  ... 73 more
>> |#]
>> 
>> TIA,
>> 
>> -Noah
>> 
>> 
>> 
>> 
>> _______________________________________________
>> eclipselink-users mailing list
>> eclipselink-users@xxxxxxxxxxx
>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
> _______________________________________________
> eclipselink-users mailing list
> eclipselink-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users



Back to the top