ISPN-7350 Read only entities can be inserted and deleted
This commit is contained in:
parent
af554fe59b
commit
61a8416463
|
@ -25,11 +25,10 @@ public class CollectionRegionImpl extends BaseTransactionalDataRegion implements
|
|||
}
|
||||
|
||||
public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
|
||||
if (AccessType.READ_ONLY.equals(accessType)) {
|
||||
return new ReadOnlyAccess(this);
|
||||
} else if (AccessType.TRANSACTIONAL.equals(accessType)) {
|
||||
if (AccessType.READ_ONLY.equals(accessType)
|
||||
|| AccessType.TRANSACTIONAL.equals(accessType))
|
||||
return new TransactionalAccess(this);
|
||||
}
|
||||
|
||||
throw new CacheException("Unsupported access type [" + accessType.getExternalName() + "]");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
package org.hibernate.cache.infinispan.collection;
|
||||
|
||||
import org.infinispan.util.logging.Log;
|
||||
import org.infinispan.util.logging.LogFactory;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
|
||||
/**
|
||||
* This defines the strategy for transactional access to collection data in a
|
||||
* Infinispan instance.
|
||||
* <p/>
|
||||
* The read-only access to a Infinispan really is still transactional, just with
|
||||
* the extra semantic or guarantee that we will not update data.
|
||||
*
|
||||
* @author Chris Bredesen
|
||||
* @author Galder Zamarreño
|
||||
* @since 3.5
|
||||
*/
|
||||
class ReadOnlyAccess extends TransactionalAccess {
|
||||
private static final Log log = LogFactory.getLog(ReadOnlyAccess.class);
|
||||
|
||||
ReadOnlyAccess(CollectionRegionImpl region) {
|
||||
super(region);
|
||||
}
|
||||
public SoftLock lockItem(Object key, Object version) throws CacheException {
|
||||
throw new UnsupportedOperationException("Illegal attempt to edit read only item");
|
||||
}
|
||||
|
||||
public SoftLock lockRegion() throws CacheException {
|
||||
throw new UnsupportedOperationException("Illegal attempt to edit read only region");
|
||||
}
|
||||
|
||||
public void unlockItem(Object key, SoftLock lock) throws CacheException {
|
||||
log.error("Illegal attempt to edit read only item");
|
||||
}
|
||||
|
||||
public void unlockRegion(SoftLock lock) throws CacheException {
|
||||
log.error("Illegal attempt to edit read only item");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,8 +1,5 @@
|
|||
package org.hibernate.cache.infinispan.entity;
|
||||
|
||||
import org.infinispan.util.logging.Log;
|
||||
import org.infinispan.util.logging.LogFactory;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
|
||||
|
@ -15,36 +12,21 @@ import org.hibernate.cache.spi.access.SoftLock;
|
|||
* @since 3.5
|
||||
*/
|
||||
class ReadOnlyAccess extends TransactionalAccess {
|
||||
private static final Log log = LogFactory.getLog(ReadOnlyAccess.class);
|
||||
|
||||
ReadOnlyAccess(EntityRegionImpl region) {
|
||||
super(region);
|
||||
}
|
||||
|
||||
public SoftLock lockItem(Object key, Object version) throws CacheException {
|
||||
throw new UnsupportedOperationException("Illegal attempt to edit read only item");
|
||||
}
|
||||
|
||||
public SoftLock lockRegion() throws CacheException {
|
||||
throw new UnsupportedOperationException("Illegal attempt to edit read only item");
|
||||
}
|
||||
|
||||
public void unlockItem(Object key, SoftLock lock) throws CacheException {
|
||||
log.error("Illegal attempt to edit read only item");
|
||||
}
|
||||
|
||||
public void unlockRegion(SoftLock lock) throws CacheException {
|
||||
log.error("Illegal attempt to edit read only item");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException {
|
||||
public boolean update(Object key, Object value, Object currentVersion,
|
||||
Object previousVersion) throws CacheException {
|
||||
throw new UnsupportedOperationException("Illegal attempt to edit read only item");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
|
||||
throws CacheException {
|
||||
public boolean afterUpdate(Object key, Object value, Object currentVersion,
|
||||
Object previousVersion, SoftLock lock) throws CacheException {
|
||||
throw new UnsupportedOperationException("Illegal attempt to edit read only item");
|
||||
}
|
||||
|
||||
}
|
|
@ -51,12 +51,6 @@ public class CollectionRegionImplTestCase extends AbstractEntityCollectionRegion
|
|||
CollectionRegion region = regionFactory.buildCollectionRegion("test", properties, null);
|
||||
assertNull("Got TRANSACTIONAL", region.buildAccessStrategy(AccessType.TRANSACTIONAL)
|
||||
.lockRegion());
|
||||
try {
|
||||
region.buildAccessStrategy(AccessType.READ_ONLY).lockRegion();
|
||||
fail("Did not get READ_ONLY");
|
||||
} catch (UnsupportedOperationException good) {
|
||||
}
|
||||
|
||||
try {
|
||||
region.buildAccessStrategy(AccessType.NONSTRICT_READ_WRITE);
|
||||
fail("Incorrectly got NONSTRICT_READ_WRITE");
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
|
||||
* as indicated by the @author tags. See the copyright.txt file in the
|
||||
* distribution for a full listing of individual contributors.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this software; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
||||
*/
|
||||
package org.hibernate.test.cache.infinispan.collection;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
/**
|
||||
* ReadOnlyExtraAPITestCase.
|
||||
*
|
||||
* @author Galder Zamarreño
|
||||
* @since 3.5
|
||||
*/
|
||||
public class ReadOnlyExtraAPITestCase extends TransactionalExtraAPITestCase {
|
||||
@Override
|
||||
protected AccessType getAccessType() {
|
||||
return AccessType.READ_ONLY;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testLockItem() {
|
||||
try {
|
||||
getCollectionAccessStrategy().lockItem( KEY, new Integer( 1 ) );
|
||||
fail( "Call to lockItem did not throw exception" );
|
||||
}
|
||||
catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testLockRegion() {
|
||||
try {
|
||||
getCollectionAccessStrategy().lockRegion();
|
||||
fail( "Call to lockRegion did not throw exception" );
|
||||
}
|
||||
catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -30,7 +30,6 @@ import org.hibernate.cache.spi.access.AccessType;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Base class for tests of TRANSACTIONAL access.
|
||||
|
@ -39,6 +38,7 @@ import static org.junit.Assert.fail;
|
|||
* @since 3.5
|
||||
*/
|
||||
public abstract class AbstractReadOnlyAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase {
|
||||
|
||||
@Override
|
||||
protected AccessType getAccessType() {
|
||||
return AccessType.READ_ONLY;
|
||||
|
@ -64,9 +64,9 @@ public abstract class AbstractReadOnlyAccessTestCase extends AbstractEntityRegio
|
|||
BatchModeTransactionManager.getInstance().begin();
|
||||
assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
|
||||
if (minimal)
|
||||
localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
|
||||
localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, 1, true);
|
||||
else
|
||||
localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
|
||||
localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, 1);
|
||||
|
||||
sleep(250);
|
||||
Object expected = isUsingInvalidation() ? null : VALUE1;
|
||||
|
@ -77,17 +77,11 @@ public abstract class AbstractReadOnlyAccessTestCase extends AbstractEntityRegio
|
|||
assertEquals(expected, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
@Override
|
||||
public void testUpdate() throws Exception {
|
||||
|
||||
final String KEY = KEY_BASE + testCount++;
|
||||
|
||||
try {
|
||||
localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
|
||||
fail("Call to update did not throw exception");
|
||||
}
|
||||
catch (UnsupportedOperationException good) {}
|
||||
localAccessStrategy.update(KEY_BASE + testCount++,
|
||||
VALUE2, 2, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,13 +50,8 @@ public class EntityRegionImplTestCase extends AbstractEntityCollectionRegionTest
|
|||
@Override
|
||||
protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) {
|
||||
EntityRegion region = regionFactory.buildEntityRegion("test", properties, null);
|
||||
assertNull("Got TRANSACTIONAL", region.buildAccessStrategy(AccessType.TRANSACTIONAL)
|
||||
.lockRegion());
|
||||
try {
|
||||
region.buildAccessStrategy(AccessType.READ_ONLY).lockRegion();
|
||||
fail("Did not get READ_ONLY");
|
||||
} catch (UnsupportedOperationException good) {
|
||||
}
|
||||
assertNull("Got TRANSACTIONAL",
|
||||
region.buildAccessStrategy(AccessType.TRANSACTIONAL).lockRegion());
|
||||
|
||||
try {
|
||||
region.buildAccessStrategy(AccessType.NONSTRICT_READ_WRITE);
|
||||
|
@ -73,7 +68,7 @@ public class EntityRegionImplTestCase extends AbstractEntityCollectionRegionTest
|
|||
|
||||
@Override
|
||||
protected void putInRegion(Region region, Object key, Object value) {
|
||||
((EntityRegion) region).buildAccessStrategy(AccessType.TRANSACTIONAL).insert(key, value, new Integer(1));
|
||||
((EntityRegion) region).buildAccessStrategy(AccessType.TRANSACTIONAL).insert(key, value, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -40,36 +40,11 @@ public class ReadOnlyExtraAPITestCase extends TransactionalExtraAPITestCase {
|
|||
return AccessType.READ_ONLY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testLockItem() {
|
||||
try {
|
||||
getEntityAccessStrategy().lockItem( KEY, Integer.valueOf( 1 ) );
|
||||
fail( "Call to lockItem did not throw exception" );
|
||||
}
|
||||
catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testLockRegion() {
|
||||
try {
|
||||
getEntityAccessStrategy().lockRegion();
|
||||
fail( "Call to lockRegion did not throw exception" );
|
||||
}
|
||||
catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testAfterUpdate() {
|
||||
try {
|
||||
getEntityAccessStrategy().afterUpdate(
|
||||
KEY,
|
||||
VALUE2,
|
||||
Integer.valueOf( 1 ),
|
||||
Integer.valueOf( 2 ),
|
||||
new MockSoftLock()
|
||||
);
|
||||
KEY, VALUE2, 1, 2, new MockSoftLock());
|
||||
fail( "Call to afterUpdate did not throw exception" );
|
||||
}
|
||||
catch (UnsupportedOperationException expected) {
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package org.hibernate.test.cache.infinispan.functional;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.stat.SecondLevelCacheStatistics;
|
||||
import org.hibernate.stat.Statistics;
|
||||
import org.infinispan.util.logging.Log;
|
||||
import org.infinispan.util.logging.LogFactory;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static org.infinispan.test.TestingUtil.withTx;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Parent tests for both transactional and
|
||||
* read-only tests are defined in this class.
|
||||
*
|
||||
* @author Galder Zamarreño
|
||||
* @since 4.1
|
||||
*/
|
||||
public abstract class AbstractFunctionalTestCase extends SingleNodeTestCase {
|
||||
|
||||
static final Log log = LogFactory.getLog(AbstractFunctionalTestCase.class);
|
||||
|
||||
@Test
|
||||
public void testEmptySecondLevelCacheEntry() throws Exception {
|
||||
sessionFactory().getCache().evictCollectionRegion( Item.class.getName() + ".items" );
|
||||
Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics( Item.class.getName() + ".items" );
|
||||
Map cacheEntries = statistics.getEntries();
|
||||
assertEquals( 0, cacheEntries.size() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertDeleteEntity() throws Exception {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
final Item item = new Item( "chris", "Chris's Item" );
|
||||
withTx(tm, new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.persist(item);
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
log.info("Entry persisted, let's load and delete it.");
|
||||
|
||||
withTx(tm, new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
Item found = (Item) s.load(Item.class, item.getId());
|
||||
log.info(stats.toString());
|
||||
assertEquals(item.getDescription(), found.getDescription());
|
||||
assertEquals(0, stats.getSecondLevelCacheMissCount());
|
||||
assertEquals(1, stats.getSecondLevelCacheHitCount());
|
||||
s.delete(found);
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -23,33 +23,17 @@
|
|||
*/
|
||||
package org.hibernate.test.cache.infinispan.functional;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.stat.SecondLevelCacheStatistics;
|
||||
import org.hibernate.stat.Statistics;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Functional entity read-only tests.
|
||||
*
|
||||
* @author Galder Zamarreño
|
||||
* @since 3.5
|
||||
*/
|
||||
public class BasicReadOnlyTestCase extends SingleNodeTestCase {
|
||||
public class BasicReadOnlyTestCase extends AbstractFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
public String getCacheConcurrencyStrategy() {
|
||||
return "read-only";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptySecondLevelCacheEntry() throws Exception {
|
||||
sessionFactory().getCache().evictEntityRegion( Item.class.getName() );
|
||||
Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics( Item.class.getName() + ".items" );
|
||||
Map cacheEntries = statistics.getEntries();
|
||||
assertEquals( 0, cacheEntries.size() );
|
||||
}
|
||||
|
||||
}
|
|
@ -33,8 +33,6 @@ import org.hibernate.Criteria;
|
|||
import org.hibernate.NaturalIdLoadAccess;
|
||||
import org.hibernate.cache.infinispan.access.PutFromLoadValidator;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.infinispan.util.logging.Log;
|
||||
import org.infinispan.util.logging.LogFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -51,13 +49,13 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
|
||||
/**
|
||||
* Functional entity transactional tests.
|
||||
*
|
||||
* @author Galder Zamarreño
|
||||
* @since 3.5
|
||||
*/
|
||||
public class BasicTransactionalTestCase extends SingleNodeTestCase {
|
||||
private static final Log log = LogFactory.getLog( BasicTransactionalTestCase.class );
|
||||
public class BasicTransactionalTestCase extends AbstractFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
public void configure(Configuration cfg) {
|
||||
|
@ -90,42 +88,6 @@ public class BasicTransactionalTestCase extends SingleNodeTestCase {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEntityCache() throws Exception {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
final Item item = new Item( "chris", "Chris's Item" );
|
||||
withTx(tm, new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.persist( item );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
log.info("Entry persisted, let's load and delete it.");
|
||||
|
||||
withTx(tm, new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
Session s = openSession();
|
||||
Item found = (Item) s.load(Item.class, item.getId());
|
||||
log.info(stats.toString());
|
||||
assertEquals(item.getDescription(), found.getDescription());
|
||||
assertEquals(0, stats.getSecondLevelCacheMissCount());
|
||||
assertEquals(1, stats.getSecondLevelCacheHitCount());
|
||||
s.delete(found);
|
||||
s.close();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCollectionCache() throws Exception {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
|
@ -452,16 +414,6 @@ public class BasicTransactionalTestCase extends SingleNodeTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptySecondLevelCacheEntry() throws Exception {
|
||||
sessionFactory().getCache().evictCollectionRegion( Item.class.getName() + ".items" );
|
||||
Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics( Item.class.getName() + ".items" );
|
||||
Map cacheEntries = statistics.getEntries();
|
||||
assertEquals( 0, cacheEntries.size() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNaturalIdCached() throws Exception {
|
||||
saveSomeCitizens();
|
||||
|
|
Loading…
Reference in New Issue