Kims-DeveloperGroup / hibernate-arcus

Hibernate 2nd cache implementation using Arcus cache

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

When @Cache.usage changes, casting exception is thrown

rica-v3 opened this issue · comments

commented

After changing "CacheConcurrencyStrategy" READ_ONLY to READ_WRITE, getting entity occurs the exception below.

Cause:

The cached entity is StandardCacheEntryImpl but current entity should be AbstractReadWriteAccess$Lockable

org.hibernate.HibernateException: Unable to perform afterTransactionCompletion callback: org.hibernate.cache.spi.entry.StandardCacheEntryImpl cannot be cast to org.hibernate.cache.spi.support.AbstractReadWriteAccess$Lockable

	at org.hibernate.engine.spi.ActionQueue$AfterTransactionCompletionProcessQueue.afterTransactionCompletion(ActionQueue.java:990)
	at org.hibernate.engine.spi.ActionQueue.afterTransactionCompletion(ActionQueue.java:513)
	at org.hibernate.internal.SessionImpl.afterTransactionCompletion(SessionImpl.java:2404)
	at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.afterTransactionCompletion(JdbcCoordinatorImpl.java:454)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.afterCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:203)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$400(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:283)
	at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
	at hibernate.CollectionCacheTest.testCollectionCache_whenCollectionCacheIsPut_thenCollectionCacheShouldBeHitForTheNextGet(CollectionCacheTest.java:98)
	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)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.hibernate.testing.junit4.ExtendedFrameworkMethod.invokeExplosively(ExtendedFrameworkMethod.java:45)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:298)
	at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:292)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassCastException: org.hibernate.cache.spi.entry.StandardCacheEntryImpl cannot be cast to org.hibernate.cache.spi.support.AbstractReadWriteAccess$Lockable
	at org.hibernate.cache.spi.support.EntityReadWriteAccess.afterInsert(EntityReadWriteAccess.java:85)
	at org.hibernate.action.internal.EntityInsertAction.cacheAfterInsert(EntityInsertAction.java:257)
	at org.hibernate.action.internal.EntityInsertAction.doAfterTransactionCompletion(EntityInsertAction.java:239)
	at org.hibernate.engine.spi.ActionQueue$AfterTransactionCompletionProcessQueue.afterTransactionCompletion(ActionQueue.java:983)
	... 23 more

Solution:

When changing CacheConcurrencyStrategy, regionName should be modified together not to reuse same cache items

commented

To resolve the casting exception, EntityReadWriteAccess needs to be overridden by handling Casting Exception

package org.hibernate.cache.spi.support;
public class EntityReadWriteAccess extends AbstractReadWriteAccess implements EntityDataAccess

	@Override
	public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version) {
		try {
			writeLock().lock();
			* Lockable item = (Lockable) getStorageAccess().getFromCache( key, session ); // <--- casting exception point #1
			if ( item == null ) {
				getStorageAccess().putIntoCache(
						key,
						new Item( value, version, getRegion().getRegionFactory().nextTimestamp() ),
						session
				);
				return true;
			}
			else {
				return false;
			}
		}
		finally {
			writeLock().unlock();
		}
	}
	@Override
	public boolean afterUpdate(
			SharedSessionContractImplementor session,
			Object key,
			Object value,
			Object currentVersion,
			Object previousVersion,
			SoftLock lock) {
		try {
			writeLock().lock();
			* Lockable item = (Lockable) getStorageAccess().getFromCache( key, session ); // <--- casting exception point #2

			if ( item != null && item.isUnlockable( lock ) ) {
				SoftLockImpl lockItem = (SoftLockImpl) item;
				if ( lockItem.wasLockedConcurrently() ) {
					decrementLock( session, key, lockItem );
					return false;
				}
				else {
					getStorageAccess().putIntoCache(
							key,
							new Item( value, currentVersion, getRegion().getRegionFactory().nextTimestamp() ),
							session
					);
					return true;
				}
			}
			else {
				handleLockExpiry(session, key, item );
				return false;
			}
		}
		finally {
			writeLock().unlock();
		}
	}
commented

This is not a bug, but is intended by hibernate-orm

Solution:

When changing CacheConcurrencyStrategy, regionName should be modified together not to reuse same cache items