HHH-11356 - Adjust the 2nd-Cache SPIs to better reflect supported uses

HHH-12323 - Update Statistics API and SPI based on changes to 2nd level caching changes
HHH-12416 - set up relocation for hibernate-ehcache
HHH-12417 - default strategy based on registrations with StrategySelector

Basically reverted HHH-12416 and added basic support for Ehcache 2 again
This commit is contained in:
Steve Ebersole 2018-03-22 22:51:07 -05:00
parent 84897f0ad0
commit 7f12e2a161
25 changed files with 1275 additions and 105 deletions

View File

@ -145,6 +145,8 @@ public interface StrategySelector extends Service {
* Retrieve all of the registered implementors of the given strategy. Useful * Retrieve all of the registered implementors of the given strategy. Useful
* to allow defaulting the choice to the single registered implementor when * to allow defaulting the choice to the single registered implementor when
* only one is registered * only one is registered
*
* @return The implementors. Should never return {@code null}
*/ */
<T> Collection<Class<? extends T>> getRegisteredStrategyImplementors(Class<T> strategy); <T> Collection<Class<? extends T>> getRegisteredStrategyImplementors(Class<T> strategy);
} }

View File

@ -12,6 +12,7 @@ import java.util.Properties;
import org.hibernate.boot.registry.StandardServiceInitiator; import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.boot.registry.selector.spi.StrategySelector; import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
@ -19,6 +20,9 @@ import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
/** /**
* Initiator for the {@link RegionFactory} service. * Initiator for the {@link RegionFactory} service.
* *
@ -39,58 +43,78 @@ public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFa
} }
@Override @Override
@SuppressWarnings({ "unchecked" })
public RegionFactory initiateService(Map configurationValues, ServiceRegistryImplementor registry) { public RegionFactory initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
final Properties p = new Properties(); final RegionFactory regionFactory = resolveRegionFactory( configurationValues, registry );
if (configurationValues != null) {
p.putAll( configurationValues );
}
final boolean useSecondLevelCache = ConfigurationHelper.getBoolean(
AvailableSettings.USE_SECOND_LEVEL_CACHE,
configurationValues,
true
);
final boolean useQueryCache = ConfigurationHelper.getBoolean(
AvailableSettings.USE_QUERY_CACHE,
configurationValues
);
RegionFactory regionFactory = NoCachingRegionFactory.INSTANCE;
// The cache provider is needed when we either have second-level cache enabled
// or query cache enabled. Note that useSecondLevelCache is enabled by default
if ( useSecondLevelCache || useQueryCache ) {
final Object setting = configurationValues != null
? configurationValues.get( AvailableSettings.CACHE_REGION_FACTORY )
: null;
regionFactory = registry.getService( StrategySelector.class ).resolveStrategy(
RegionFactory.class,
setting,
NoCachingRegionFactory.INSTANCE,
new StrategyCreatorRegionFactoryImpl( p )
);
}
if ( regionFactory == NoCachingRegionFactory.INSTANCE ) {
// todo (5.3) : make this configurable?
boolean allowDefaulting = true;
if ( allowDefaulting ) {
final StrategySelector selector = registry.getService( StrategySelector.class );
final Collection<Class<? extends RegionFactory>> implementors = selector.getRegisteredStrategyImplementors( RegionFactory.class );
if ( implementors != null && implementors.size() == 1 ) {
regionFactory = selector.resolveStrategy( RegionFactory.class, implementors.iterator().next() );
configurationValues.put( AvailableSettings.CACHE_REGION_FACTORY, regionFactory );
configurationValues.put( AvailableSettings.USE_SECOND_LEVEL_CACHE, "true" );
}
else {
LOG.debugf( "Cannot default RegionFactory based on registered strategies as `%s` RegionFactory strategies were registered" );
}
}
}
LOG.debugf( "Cache region factory : %s", regionFactory.getClass().getName() ); LOG.debugf( "Cache region factory : %s", regionFactory.getClass().getName() );
return regionFactory; return regionFactory;
} }
@SuppressWarnings({"unchecked", "WeakerAccess"})
protected RegionFactory resolveRegionFactory(Map configurationValues, ServiceRegistryImplementor registry) {
final Properties p = new Properties();
p.putAll( configurationValues );
final Boolean useSecondLevelCache = ConfigurationHelper.getBooleanWrapper(
AvailableSettings.USE_SECOND_LEVEL_CACHE,
configurationValues,
null
);
final Boolean useQueryCache = ConfigurationHelper.getBooleanWrapper(
AvailableSettings.USE_QUERY_CACHE,
configurationValues,
null
);
// We should immediately return NoCachingRegionFactory if either:
// 1) both are explicitly FALSE
// 2) USE_SECOND_LEVEL_CACHE is FALSE and USE_QUERY_CACHE is null
if ( useSecondLevelCache != null && useSecondLevelCache == FALSE ) {
if ( useQueryCache == null || useQueryCache == FALSE ) {
return NoCachingRegionFactory.INSTANCE;
}
}
final Object setting = configurationValues.get( AvailableSettings.CACHE_REGION_FACTORY );
final StrategySelector selector = registry.getService( StrategySelector.class );
final Collection<Class<? extends RegionFactory>> implementors = selector.getRegisteredStrategyImplementors( RegionFactory.class );
if ( ( useSecondLevelCache != null && useSecondLevelCache == TRUE )
|| ( useQueryCache != null && useQueryCache == TRUE ) ) {
// if either are explicitly defined and one is TRUE, we need a RegionFactory
if ( setting == null && implementors.size() != 1 ) {
throw new CacheException( "Caching was explicitly requested, but no RegionFactory was defined and there is not a single registered RegionFactory" );
}
final RegionFactory regionFactory = registry.getService( StrategySelector.class ).resolveStrategy(
RegionFactory.class,
setting,
(RegionFactory) null,
new StrategyCreatorRegionFactoryImpl( p )
);
if ( regionFactory != null ) {
return regionFactory;
}
}
if ( implementors.size() == 1 ) {
final RegionFactory regionFactory = selector.resolveStrategy( RegionFactory.class, implementors.iterator().next() );
configurationValues.put( AvailableSettings.CACHE_REGION_FACTORY, regionFactory );
configurationValues.put( AvailableSettings.USE_SECOND_LEVEL_CACHE, "true" );
return regionFactory;
}
else {
LOG.debugf(
"Cannot default RegionFactory based on registered strategies as `%s` RegionFactory strategies were registered",
implementors
);
}
return NoCachingRegionFactory.INSTANCE;
}
} }

View File

@ -15,6 +15,7 @@ import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.MessageLogger; import org.jboss.logging.annotations.MessageLogger;
import org.jboss.logging.annotations.ValidIdRange; import org.jboss.logging.annotations.ValidIdRange;
import static org.jboss.logging.Logger.Level.INFO;
import static org.jboss.logging.Logger.Level.WARN; import static org.jboss.logging.Logger.Level.WARN;
/** /**
@ -28,18 +29,47 @@ public interface SecondLevelCacheLogger extends BasicLogger {
"org.hibernate.orm.cache" "org.hibernate.orm.cache"
); );
int NAMESPACE = 90001000;
@LogMessage(level = WARN)
@Message(
value = "Attempt to restart an already started RegionFactory. Use sessionFactory.close() between " +
"repeated calls to buildSessionFactory. Using previously created RegionFactory.",
id = NAMESPACE + 1
)
void attemptToStartAlreadyStartedCacheProvider();
@LogMessage(level = WARN)
@Message(
value = "Attempt to restop an already stopped JCacheRegionFactory.",
id = NAMESPACE + 2
)
void attemptToStopAlreadyStoppedCacheProvider();
@LogMessage( level = WARN ) @LogMessage( level = WARN )
@Message( @Message(
value = "Read-only caching was requested for mutable entity [%s]", value = "Read-only caching was requested for mutable entity [%s]",
id = 90001001 id = NAMESPACE + 3
) )
void readOnlyCachingMutableEntity(NavigableRole navigableRole); void readOnlyCachingMutableEntity(NavigableRole navigableRole);
@LogMessage( level = WARN ) @LogMessage( level = WARN )
@Message( @Message(
value = "Read-only caching was requested for mutable natural-id for entity [%s]", value = "Read-only caching was requested for mutable natural-id for entity [%s]",
id = 90001002 id = NAMESPACE + 4
) )
void readOnlyCachingMutableNaturalId(NavigableRole navigableRole); void readOnlyCachingMutableNaturalId(NavigableRole navigableRole);
/**
* Log a message (WARN) about expiry of soft-locked region.
*/
@LogMessage(level = INFO)
@Message(
value = "Cache[%s] Key[%s]\n" +
"A soft-locked cache entry was expired by the underlying cache. If this happens regularly you " +
"should consider increasing the cache timeouts and/or capacity limits",
id = NAMESPACE + 5
)
void softLockedCacheExpired(String regionName, Object key);
} }

View File

@ -15,6 +15,7 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.hibernate.cache.spi.DomainDataRegion; import org.hibernate.cache.spi.DomainDataRegion;
import org.hibernate.cache.spi.SecondLevelCacheLogger;
import org.hibernate.cache.spi.access.SoftLock; import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
@ -179,6 +180,7 @@ public abstract class AbstractReadWriteAccess extends AbstractCachedDomainDataAc
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected void handleLockExpiry(SharedSessionContractImplementor session, Object key, Lockable lock) { protected void handleLockExpiry(SharedSessionContractImplementor session, Object key, Lockable lock) {
SecondLevelCacheLogger.INSTANCE.softLockedCacheExpired( getRegion().getName(), key );
log.info( "Cached entry expired : " + key ); log.info( "Cached entry expired : " + key );
// create new lock that times out immediately // create new lock that times out immediately

View File

@ -8,17 +8,18 @@ package org.hibernate.test.cache;
import java.util.Collection; import java.util.Collection;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.registry.selector.spi.StrategySelector; import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.cache.internal.EnabledCaching; import org.hibernate.cache.internal.NoCachingRegionFactory;
import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl; import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.cache.CachingRegionFactory; import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Test; import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.equalTo;
@ -28,48 +29,78 @@ import static org.hamcrest.MatcherAssert.assertThat;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class SingleRegisteredProviderTest extends BaseNonConfigCoreFunctionalTestCase { public class SingleRegisteredProviderTest extends BaseUnitTestCase {
@Override @Test
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) { public void testCachingExplicitlyDisabled() {
super.configureStandardServiceRegistryBuilder( ssrb ); final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
.applySetting( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" )
.build();
ssrb.applySetting( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" ); assertThat( registry.getService( RegionFactory.class ), instanceOf( NoCachingRegionFactory.class ) );
ssrb.applySetting( AvailableSettings.CACHE_REGION_PREFIX, "" );
ssrb.applySetting( AvailableSettings.CACHE_REGION_FACTORY, "" );
ssrb.applySetting( AvailableSettings.CONNECTION_PROVIDER, "" );
}
@Override
protected void configureBootstrapServiceRegistryBuilder(BootstrapServiceRegistryBuilder bsrb) {
super.configureBootstrapServiceRegistryBuilder( bsrb );
bsrb.applyStrategySelector( ConnectionProvider.class, "testing", DriverManagerConnectionProviderImpl.class );
} }
@Test @Test
public void testCachingExpectations() { public void testCachingImplicitlyEnabledRegistered() {
final Collection<Class<? extends RegionFactory>> implementors = sessionFactory().getServiceRegistry() final BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.build();
final Collection<Class<? extends RegionFactory>> implementors = bsr
.getService( StrategySelector.class ) .getService( StrategySelector.class )
.getRegisteredStrategyImplementors( RegionFactory.class ); .getRegisteredStrategyImplementors( RegionFactory.class );
assertThat( implementors.size(), equalTo( 1 ) ); assertThat( implementors.size(), equalTo( 1 ) );
assertThat( sessionFactory().getSessionFactoryOptions().isSecondLevelCacheEnabled(), equalTo( true ) );
assertThat( sessionFactory().getCache(), instanceOf( EnabledCaching.class ) ); final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
assertThat( sessionFactory().getCache().getRegionFactory(), instanceOf( CachingRegionFactory.class ) ); .applySetting( AvailableSettings.USE_SECOND_LEVEL_CACHE, "" )
assertThat( implementors.iterator().next(), equalTo( CachingRegionFactory.class ) ); .build();
assertThat( ssr.getService( RegionFactory.class ), instanceOf( NoCachingRegionFactory.class ) );
} }
@Test @Test
public void testConnectionsExpectations() { public void testCachingImplicitlyEnabledNoRegistered() {
final Collection<Class<? extends ConnectionProvider>> implementors = sessionFactory().getServiceRegistry() final BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.build();
final Collection<Class<? extends RegionFactory>> implementors = bsr
.getService( StrategySelector.class ) .getService( StrategySelector.class )
.getRegisteredStrategyImplementors( ConnectionProvider.class ); .getRegisteredStrategyImplementors( RegionFactory.class );
assertThat( implementors.size(), equalTo( 1 ) ); assertThat( implementors.size(), equalTo( 1 ) );
final ConnectionProvider configuredProvider = sessionFactory().getServiceRegistry().getService( ConnectionProvider.class ); bsr.getService( StrategySelector.class ).unRegisterStrategyImplementor(
RegionFactory.class,
implementors.iterator().next()
);
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.USE_SECOND_LEVEL_CACHE, "" )
.build();
assertThat( ssr.getService( RegionFactory.class ), instanceOf( NoCachingRegionFactory.class ) );
}
@Test
public void testConnectionsRegistered() {
final BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.build();
final Collection<Class<? extends ConnectionProvider>> implementors = bsr
.getService( StrategySelector.class )
.getRegisteredStrategyImplementors( ConnectionProvider.class );
assertThat( implementors.size(), equalTo( 0 ) );
bsr.getService( StrategySelector.class ).registerStrategyImplementor(
ConnectionProvider.class,
"testing",
DriverManagerConnectionProviderImpl.class
);
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr ).build();
final ConnectionProvider configuredProvider = ssr.getService( ConnectionProvider.class );
assertThat( configuredProvider, instanceOf( DriverManagerConnectionProviderImpl.class ) ); assertThat( configuredProvider, instanceOf( DriverManagerConnectionProviderImpl.class ) );
assertThat( implementors.iterator().next(), equalTo( DriverManagerConnectionProviderImpl.class ) );
} }
} }

View File

@ -5,31 +5,11 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
apply from: rootProject.file( 'gradle/base-information.gradle' ) apply from: rootProject.file( 'gradle/published-java-module.gradle' )
apply from: rootProject.file( 'gradle/publishing-repos.gradle' )
apply from: rootProject.file( 'gradle/publishing-pom.gradle' )
apply plugin: 'maven-publish'
apply plugin: 'maven-publish-auth'
description = "(deprecated - use `org.hibernate:hibernate-jcache:${project.version}` + `org.ehcache:ehcache:3.0.0` instead)" description = "Integration for using Ehcache 2.x as a Hibernate second-level-cache provider"
ext { dependencies {
relocatedGroupId = 'org.hibernate' compile project( ':hibernate-core' )
relocatedArtifactId = 'hibernate-jcache' compile( libraries.ehcache )
relocatedVersion = project.version
} }
publishing {
publications {
publishedArtifacts {
pom.withXml {
def relocation = asNode().appendNode( 'distributionManagement' ).appendNode( 'relocation' )
relocation.appendNode( 'groupId', project.relocatedGroupId)
relocation.appendNode( 'artifactId', project.relocatedArtifactId )
relocation.appendNode( 'version', project.relocatedVersion )
}
}
}
}
task release( dependsOn: bintrayUpload )

View File

@ -0,0 +1,28 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.cache.ehcache;
import net.sf.ehcache.CacheManager;
/**
* @author Steve Ebersole
*/
public interface ConfigSettings {
String SIMPLE_FACTORY_NAME = "jcache";
String PROP_PREFIX = "hibernate.cache.ehcache.";
/**
* Allows providing `hibernate-jcache` with a custom JCache {@link CacheManager}.
*/
String CACHE_MANAGER = PROP_PREFIX + "cache_manager";
/**
* This is the legacy property name. No need to change it to fit under {@link #PROP_PREFIX}
*/
String EHCACHE_CONFIGURATION_RESOURCE_NAME = "net.sf.ehcache.configurationResourceName";
}

View File

@ -0,0 +1,48 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.cache.ehcache.internal;
import net.sf.ehcache.Cache;
import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext;
import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
import org.hibernate.cache.spi.CacheKeysFactory;
import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cache.spi.support.DomainDataRegionTemplate;
import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
*/
public class DomainDataRegionImpl extends DomainDataRegionTemplate {
private static final Logger log = Logger.getLogger( DomainDataRegionImpl.class );
@SuppressWarnings("WeakerAccess")
public DomainDataRegionImpl(
DomainDataRegionConfig regionConfig,
RegionFactory regionFactory,
Cache underlyingCache,
CacheKeysFactory cacheKeysFactory,
DomainDataRegionBuildingContext buildingContext) {
super(
regionConfig,
regionFactory,
new DomainDataStorageAccessImpl( underlyingCache ),
cacheKeysFactory,
buildingContext
);
}
/**
* Public override for testing use only
*/
@Override
public DomainDataStorageAccessImpl getCacheStorageAccess() {
return (DomainDataStorageAccessImpl) super.getCacheStorageAccess();
}
}

View File

@ -0,0 +1,25 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.cache.ehcache.internal;
import net.sf.ehcache.Cache;
import org.hibernate.cache.spi.support.DomainDataStorageAccess;
/**
* @author Steve Ebersole
*/
public class DomainDataStorageAccessImpl extends StorageAccessImpl implements DomainDataStorageAccess {
public DomainDataStorageAccessImpl(Cache underlyingCache) {
super( underlyingCache );
}
@Override
public void putFromLoad(Object key, Object value) {
putIntoCache( key, value );
}
}

View File

@ -0,0 +1,112 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.cache.ehcache.internal;
import org.hibernate.internal.CoreMessageLogger;
import org.jboss.logging.Logger;
import org.jboss.logging.annotations.LogMessage;
import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.MessageLogger;
import static org.jboss.logging.Logger.Level.WARN;
/**
* The jboss-logging {@link MessageLogger} for the hibernate-ehcache module. It reserves message ids ranging from
* 20001 to 25000 inclusively.
* <p/>
* New messages must be added after the last message defined to ensure message codes are unique.
*/
@MessageLogger(projectCode = "HHH")
public interface EhCacheMessageLogger extends CoreMessageLogger {
EhCacheMessageLogger INSTANCE = Logger.getMessageLogger(
EhCacheMessageLogger.class,
"org.hibernate.orm.cache.ehcache"
);
/**
* Log a message (WARN) about inability to find configuration file
*
* @param name The name of the configuration file
*/
@LogMessage(level = WARN)
@Message(value = "Could not find configuration [%s]; using defaults.", id = 20002)
void unableToFindConfiguration(String name);
/**
* Log a message (WARN) about inability to find named cache configuration
*
* @param name The name of the cache configuration
*/
@LogMessage(level = WARN)
@Message(value = "Could not find a specific ehcache configuration for cache named [%s]; using defaults.", id = 20003)
void unableToFindEhCacheConfiguration(String name);
/**
* Logs a message about not being able to resolve the configuration by resource name.
*
* @param configurationResourceName The resource name we attempted to resolve
*/
@LogMessage(level = WARN)
@Message(
value = "A configurationResourceName was set to %s but the resource could not be loaded from the classpath. " +
"Ehcache will configure itself using defaults.",
id = 20004
)
void unableToLoadConfiguration(String configurationResourceName);
/**
* Logs a message (WARN) about attempt to use an incompatible
* {@link net.sf.ehcache.config.TerracottaConfiguration.ValueMode}.
*/
@LogMessage(level = WARN)
@Message(
value = "The default cache value mode for this Ehcache configuration is \"identity\". " +
"This is incompatible with clustered Hibernate caching - the value mode has therefore been " +
"switched to \"serialization\"",
id = 20005
)
void incompatibleCacheValueMode();
/**
* Logs a message (WARN) about attempt to use an incompatible
* {@link net.sf.ehcache.config.TerracottaConfiguration.ValueMode}.
*
* @param cacheName The name of the cache whose config attempted to specify value mode.
*/
@LogMessage(level = WARN)
@Message(value = "The value mode for the cache[%s] is \"identity\". This is incompatible with clustered Hibernate caching - "
+ "the value mode has therefore been switched to \"serialization\"", id = 20006)
void incompatibleCacheValueModePerCache(String cacheName);
/**
* Log a message (WARN) about an attempt to specify read-only caching for a mutable entity
*
* @param entityName The name of the entity
*/
@LogMessage(level = WARN)
@Message(value = "read-only cache configured for mutable entity [%s]", id = 20007)
void readOnlyCacheConfiguredForMutableEntity(String entityName);
/**
* Log a message (WARN) about expiry of soft-locked region.
*
* @param regionName The region name
* @param key The cache key
* @param lock The lock
*/
@LogMessage(level = WARN)
@Message(
value = "Cache[%s] Key[%s] Lockable[%s]\n" +
"A soft-locked cache entry was expired by the underlying Ehcache. If this happens regularly you " +
"should consider increasing the cache timeouts and/or capacity limits",
id = 20008
)
void softLockedCacheExpired(String regionName, Object key, String lock);
}

View File

@ -0,0 +1,322 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.cache.ehcache.internal;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.ConfigurationFactory;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext;
import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
import org.hibernate.cache.ehcache.ConfigSettings;
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
import org.hibernate.cache.spi.CacheKeysFactory;
import org.hibernate.cache.spi.DomainDataRegion;
import org.hibernate.cache.spi.QueryResultsRegion;
import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cache.spi.SecondLevelCacheLogger;
import org.hibernate.cache.spi.TimestampsRegion;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.cache.spi.support.RegionNameQualifier;
import org.hibernate.cache.spi.support.SimpleTimestamper;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.jboss.logging.Logger;
import static org.hibernate.cache.ehcache.ConfigSettings.EHCACHE_CONFIGURATION_RESOURCE_NAME;
/**
* @author Steve Ebersole
* @author Alex Snaps
*/
public class EhcacheRegionFactory implements RegionFactory {
private static final Logger LOG = Logger.getLogger( EhcacheRegionFactory.class );
private final AtomicBoolean started = new AtomicBoolean( false );
private final CacheKeysFactory cacheKeysFactory;
private volatile CacheManager cacheManager;
private SessionFactoryOptions options;
public EhcacheRegionFactory() {
this( DefaultCacheKeysFactory.INSTANCE );
}
public EhcacheRegionFactory(CacheKeysFactory cacheKeysFactory) {
this.cacheKeysFactory = cacheKeysFactory;
}
public CacheManager getCacheManager() {
return cacheManager;
}
public SessionFactoryOptions getOptions() {
return options;
}
@Override
public boolean isMinimalPutsEnabledByDefault() {
return true;
}
@Override
public AccessType getDefaultAccessType() {
return AccessType.READ_WRITE;
}
@Override
public long nextTimestamp() {
return SimpleTimestamper.next();
}
@Override
public long getTimeout() {
return SimpleTimestamper.timeOut();
}
@Override
public void start(SessionFactoryOptions settings, Map configValues) throws CacheException {
if ( started.compareAndSet( false, true ) ) {
synchronized ( this ) {
this.options = settings;
try {
this.cacheManager = getCacheManager( settings, configValues );
}
finally {
if ( this.cacheManager == null ) {
started.set( false );
}
}
}
}
else {
SecondLevelCacheLogger.INSTANCE.attemptToStartAlreadyStartedCacheProvider();
}
}
private CacheManager getCacheManager(SessionFactoryOptions settings, Map properties) {
final Object explicitCacheManager = properties.get( ConfigSettings.CACHE_MANAGER );
if ( explicitCacheManager != null ) {
return useExplicitCacheManager( settings, explicitCacheManager );
}
return useNormalCacheManager( settings, properties );
}
protected CacheManager resolveCacheManager(SessionFactoryOptions settings, Map properties) {
return useNormalCacheManager( settings, properties );
}
/**
* Locate the CacheManager during start-up. protected to allow for subclassing
* such as SingletonEhcacheRegionFactory
*/
protected static CacheManager useNormalCacheManager(SessionFactoryOptions settings, Map properties) {
try {
String configurationResourceName = null;
if ( properties != null ) {
configurationResourceName = (String) properties.get( EHCACHE_CONFIGURATION_RESOURCE_NAME );
}
if ( configurationResourceName == null || configurationResourceName.length() == 0 ) {
final Configuration configuration = ConfigurationFactory.parseConfiguration();
return new CacheManager( configuration );
}
else {
final URL url = loadResource( configurationResourceName, settings );
final Configuration configuration = HibernateEhcacheUtils.loadAndCorrectConfiguration( url );
return new CacheManager( configuration );
}
}
catch (net.sf.ehcache.CacheException e) {
if ( e.getMessage().startsWith(
"Cannot parseConfiguration CacheManager. Attempt to create a new instance of " +
"CacheManager using the diskStorePath"
) ) {
throw new CacheException(
"Attempt to restart an already started EhCacheRegionFactory. " +
"Use sessionFactory.close() between repeated calls to buildSessionFactory. " +
"Consider using SingletonEhCacheRegionFactory. Error from ehcache was: " + e.getMessage()
);
}
else {
throw new CacheException( e );
}
}
}
private static URL loadResource(String configurationResourceName, SessionFactoryOptions settings) {
URL url = settings.getServiceRegistry()
.getService( ClassLoaderService.class )
.locateResource( configurationResourceName );
if ( url == null ) {
final ClassLoader standardClassloader = Thread.currentThread().getContextClassLoader();
if ( standardClassloader != null ) {
url = standardClassloader.getResource( configurationResourceName );
}
if ( url == null ) {
url = EhcacheRegionFactory.class.getResource( configurationResourceName );
}
if ( url == null ) {
try {
url = new URL( configurationResourceName );
}
catch ( MalformedURLException e ) {
// ignore
}
}
}
if ( LOG.isDebugEnabled() ) {
LOG.debugf(
"Creating EhCacheRegionFactory from a specified resource: %s. Resolved to URL: %s",
configurationResourceName,
url
);
}
if ( url == null ) {
EhCacheMessageLogger.INSTANCE.unableToLoadConfiguration( configurationResourceName );
}
return url;
}
/**
* Load a resource from the classpath.
*/
protected URL loadResource(String configurationResourceName) {
if ( ! isStarted() ) {
throw new IllegalStateException( "Cannot load resource through a non-started EhcacheRegionFactory" );
}
return loadResource( configurationResourceName, options );
}
private CacheManager useExplicitCacheManager(SessionFactoryOptions settings, Object setting) {
if ( setting instanceof CacheManager ) {
return (CacheManager) setting;
}
final Class<? extends CacheManager> cacheManagerClass;
if ( setting instanceof Class ) {
cacheManagerClass = (Class<? extends CacheManager>) setting;
}
else {
cacheManagerClass = settings.getServiceRegistry().getService( ClassLoaderService.class )
.classForName( setting.toString() );
}
try {
return cacheManagerClass.newInstance();
}
catch (InstantiationException | IllegalAccessException e) {
throw new CacheException( "Could not use explicit CacheManager : " + setting );
}
}
@Override
public void stop() {
if ( started.compareAndSet( true, false ) ) {
synchronized ( this ) {
releaseCacheManager();
cacheManager = null;
}
}
else {
SecondLevelCacheLogger.INSTANCE.attemptToStopAlreadyStoppedCacheProvider();
}
}
protected void releaseCacheManager() {
// todo (5.3) : if this is a manager instance that was provided to us we should probably not close it...
// - when the explicit `setting` passed to `#useExplicitCacheManager` is
// a CacheManager instance
cacheManager.shutdown();
}
@Override
public String qualify(String regionName) {
return RegionNameQualifier.INSTANCE.qualify( regionName, options );
}
@Override
public QueryResultsRegion buildQueryResultsRegion(
String regionName,
SessionFactoryImplementor sessionFactory) {
return new QueryResultsRegionImpl(
regionName,
this,
getOrCreateCache( regionName, sessionFactory )
);
}
@Override
public TimestampsRegion buildTimestampsRegion(
String regionName,
SessionFactoryImplementor sessionFactory) {
return new TimestampsRegionImpl(
regionName,
this,
getOrCreateCache( regionName, sessionFactory )
);
}
@Override
public DomainDataRegion buildDomainDataRegion(
DomainDataRegionConfig regionConfig,
DomainDataRegionBuildingContext buildingContext) {
return new DomainDataRegionImpl(
regionConfig,
this,
getOrCreateCache( regionConfig.getRegionName(), buildingContext.getSessionFactory() ),
cacheKeysFactory,
buildingContext
);
}
protected Cache getOrCreateCache(String unqualifiedRegionName, SessionFactoryImplementor sessionFactory) {
checkStatus();
assert !RegionNameQualifier.INSTANCE.isQualified( unqualifiedRegionName, sessionFactory.getSessionFactoryOptions() );
final String qualifiedRegionName = RegionNameQualifier.INSTANCE.qualify(
unqualifiedRegionName,
sessionFactory.getSessionFactoryOptions()
);
final Cache cache = cacheManager.getCache( qualifiedRegionName );
if ( cache == null ) {
return createCache( qualifiedRegionName );
}
return cache;
}
protected Cache createCache(String regionName) {
throw new CacheException( "On-the-fly creation of JCache Cache objects is not supported [" + regionName + "]" );
}
protected String getProp(Map properties, String prop) {
return properties != null ? (String) properties.get( prop ) : null;
}
protected void checkStatus() {
if ( ! isStarted() ) {
throw new IllegalStateException( "JCacheRegionFactory not yet started!" );
}
}
boolean isStarted() {
return started.get() && cacheManager != null;
}
}

View File

@ -0,0 +1,68 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.cache.ehcache.internal;
import java.net.URL;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.ConfigurationFactory;
import net.sf.ehcache.config.NonstopConfiguration;
import net.sf.ehcache.config.TimeoutBehaviorConfiguration.TimeoutBehaviorType;
/**
* Copy of Ehcache utils into Hibernate code base
*
* @author Chris Dennis
* @author Abhishek Sanoujam
* @author Alex Snaps
*/
public final class HibernateEhcacheUtils {
private HibernateEhcacheUtils() {
}
/**
* Create a cache manager configuration from the supplied url, correcting it for Hibernate compatibility.
* <p/>
* Currently "correcting" for Hibernate compatibility means simply switching any identity based value modes
* to serialization.
*
* @param url The url to load the config from
*
* @return The Ehcache Configuration object
*/
public static Configuration loadAndCorrectConfiguration(URL url) {
final Configuration config = ConfigurationFactory.parseConfiguration( url );
// EHC-875 / HHH-6576
if ( config == null ) {
return null;
}
if ( config.getDefaultCacheConfiguration() != null
&& config.getDefaultCacheConfiguration().isTerracottaClustered() ) {
setupHibernateTimeoutBehavior(
config.getDefaultCacheConfiguration()
.getTerracottaConfiguration()
.getNonstopConfiguration()
);
}
for ( CacheConfiguration cacheConfig : config.getCacheConfigurations().values() ) {
if ( cacheConfig.isTerracottaClustered() ) {
setupHibernateTimeoutBehavior( cacheConfig.getTerracottaConfiguration().getNonstopConfiguration() );
}
}
return config;
}
private static void setupHibernateTimeoutBehavior(NonstopConfiguration nonstopConfig) {
nonstopConfig.getTimeoutBehavior().setType( TimeoutBehaviorType.EXCEPTION.getTypeName() );
}
}

View File

@ -0,0 +1,36 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.cache.ehcache.internal;
import net.sf.ehcache.Cache;
import org.hibernate.cache.spi.QueryResultsRegion;
import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cache.spi.support.DirectAccessRegionTemplate;
import org.hibernate.cache.spi.support.StorageAccess;
/**
* @author Chris Dennis
* @author Alex Snaps
* @author Steve Ebersole
*/
public class QueryResultsRegionImpl extends DirectAccessRegionTemplate implements QueryResultsRegion {
private final StorageAccessImpl cacheAccess;
public QueryResultsRegionImpl(
String name,
RegionFactory regionFactory,
Cache cache) {
super( name, regionFactory );
this.cacheAccess = new StorageAccessImpl( cache );
}
@Override
public StorageAccess getStorageAccess() {
return cacheAccess;
}
}

View File

@ -0,0 +1,87 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.cache.ehcache.internal;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.config.Configuration;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cache.CacheException;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.jboss.logging.Logger;
import static org.hibernate.cache.ehcache.ConfigSettings.EHCACHE_CONFIGURATION_RESOURCE_NAME;
/**
* @author Steve Ebersole
*/
public class SingletonEhcacheRegionFactory extends EhcacheRegionFactory {
private static final Logger LOG = Logger.getLogger( SingletonEhcacheRegionFactory.class );
private static final AtomicInteger REFERENCE_COUNT = new AtomicInteger();
@Override
protected CacheManager resolveCacheManager(SessionFactoryOptions settings, Map properties) {
try {
String configurationResourceName = getOptions().getServiceRegistry()
.getService( ConfigurationService.class )
.getSetting( EHCACHE_CONFIGURATION_RESOURCE_NAME, value -> value == null ? null : value.toString() );
if ( configurationResourceName == null || configurationResourceName.length() == 0 ) {
try {
REFERENCE_COUNT.incrementAndGet();
return CacheManager.create();
}
catch (RuntimeException e) {
REFERENCE_COUNT.decrementAndGet();
throw e;
}
}
URL url;
try {
url = new URL( configurationResourceName );
}
catch (MalformedURLException e) {
if ( !configurationResourceName.startsWith( "/" ) ) {
configurationResourceName = "/" + configurationResourceName;
LOG.debugf(
"prepending / to %s. It should be placed in the root of the classpath rather than in a package.",
configurationResourceName
);
}
url = loadResource( configurationResourceName );
}
try {
REFERENCE_COUNT.incrementAndGet();
return CacheManager.create( HibernateEhcacheUtils.loadAndCorrectConfiguration( url ) );
}
catch (RuntimeException e) {
REFERENCE_COUNT.decrementAndGet();
throw e;
}
}
catch (net.sf.ehcache.CacheException e) {
throw new CacheException( e );
}
}
@Override
protected void releaseCacheManager() {
if ( REFERENCE_COUNT.decrementAndGet() == 0 ) {
getCacheManager().shutdown();
}
}
}

View File

@ -0,0 +1,137 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.cache.ehcache.internal;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import net.sf.ehcache.constructs.nonstop.NonStopCacheException;
import net.sf.ehcache.hibernate.nonstop.HibernateNonstopCacheExceptionHandler;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.spi.support.StorageAccess;
import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
*/
public class StorageAccessImpl implements StorageAccess {
private static final Logger LOG = Logger.getLogger( StorageAccessImpl.class );
private final Cache cache;
public StorageAccessImpl(Cache cache) {
this.cache = cache;
}
public Cache getCache() {
return cache;
}
@Override
public Object getFromCache(Object key) {
try {
final Element element = getCache().get( key );
if ( element == null ) {
return null;
}
else {
return element.getObjectValue();
}
}
catch (net.sf.ehcache.CacheException e) {
if ( e instanceof NonStopCacheException ) {
HibernateNonstopCacheExceptionHandler.getInstance()
.handleNonstopCacheException( (NonStopCacheException) e );
return null;
}
else {
throw new CacheException( e );
}
}
}
@Override
public void putIntoCache(Object key, Object value) {
try {
final Element element = new Element( key, value );
getCache().put( element );
}
catch (IllegalArgumentException | IllegalStateException e) {
throw new CacheException( e );
}
catch (net.sf.ehcache.CacheException e) {
if ( e instanceof NonStopCacheException ) {
HibernateNonstopCacheExceptionHandler.getInstance()
.handleNonstopCacheException( (NonStopCacheException) e );
}
else {
throw new CacheException( e );
}
}
}
@Override
public void removeFromCache(Object key) {
try {
getCache().remove( key );
}
catch (ClassCastException | IllegalStateException e) {
throw new CacheException( e );
}
catch (net.sf.ehcache.CacheException e) {
if ( e instanceof NonStopCacheException ) {
HibernateNonstopCacheExceptionHandler.getInstance()
.handleNonstopCacheException( (NonStopCacheException) e );
}
else {
throw new CacheException( e );
}
}
}
@Override
public void clearCache() {
try {
getCache().removeAll();
}
catch (IllegalStateException e) {
throw new CacheException( e );
}
catch (net.sf.ehcache.CacheException e) {
if ( e instanceof NonStopCacheException ) {
HibernateNonstopCacheExceptionHandler.getInstance()
.handleNonstopCacheException( (NonStopCacheException) e );
}
else {
throw new CacheException( e );
}
}
}
@Override
public void release() {
try {
getCache().getCacheManager().removeCache( getCache().getName() );
}
catch (IllegalStateException e) {
//When Spring and Hibernate are both involved this will happen in normal shutdown operation.
//Do not throw an exception, simply log this one.
LOG.debug( "This can happen if multiple frameworks both try to shutdown ehcache", e );
}
catch (net.sf.ehcache.CacheException e) {
if ( e instanceof NonStopCacheException ) {
HibernateNonstopCacheExceptionHandler.getInstance()
.handleNonstopCacheException( (NonStopCacheException) e );
}
else {
throw new CacheException( e );
}
}
}
}

View File

@ -0,0 +1,57 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.cache.ehcache.internal;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.boot.registry.selector.SimpleStrategyRegistrationImpl;
import org.hibernate.boot.registry.selector.StrategyRegistration;
import org.hibernate.boot.registry.selector.StrategyRegistrationProvider;
import org.hibernate.cache.spi.RegionFactory;
/**
* Makes the 2 contained region factory implementations available to the Hibernate
* {@link org.hibernate.boot.registry.selector.spi.StrategySelector} service.
*
* @author Steve Ebersole
*/
public class StrategyRegistrationProviderImpl implements StrategyRegistrationProvider {
@Override
@SuppressWarnings("unchecked")
public Iterable<StrategyRegistration> getStrategyRegistrations() {
final List<StrategyRegistration> strategyRegistrations = new ArrayList<StrategyRegistration>();
strategyRegistrations.add(
new SimpleStrategyRegistrationImpl(
RegionFactory.class,
EhcacheRegionFactory.class,
"ehcache",
EhcacheRegionFactory.class.getName(),
EhcacheRegionFactory.class.getSimpleName(),
// legacy impl class name
"org.hibernate.cache.EhCacheRegionFactory",
"org.hibernate.cache.ehcache.EhCacheRegionFactory"
)
);
strategyRegistrations.add(
new SimpleStrategyRegistrationImpl(
RegionFactory.class,
SingletonEhcacheRegionFactory.class,
"ehcache-singleton",
SingletonEhcacheRegionFactory.class.getName(),
SingletonEhcacheRegionFactory.class.getSimpleName(),
// legacy impl class name
"org.hibernate.cache.SingletonEhCacheRegionFactory",
"org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"
)
);
return strategyRegistrations;
}
}

View File

@ -0,0 +1,38 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.cache.ehcache.internal;
import net.sf.ehcache.Cache;
import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cache.spi.TimestampsRegion;
import org.hibernate.cache.spi.support.DirectAccessRegionTemplate;
import org.hibernate.cache.spi.support.StorageAccess;
/**
* Access to a JCache Cache used to store "update timestamps".
*
* @author Chris Dennis
* @author Abhishek Sanoujam
* @author Alex Snaps
*/
public class TimestampsRegionImpl extends DirectAccessRegionTemplate implements TimestampsRegion {
private final StorageAccessImpl cacheAccess;
public TimestampsRegionImpl(
String regionName,
RegionFactory regionFactory,
Cache cache) {
super( regionName, regionFactory );
this.cacheAccess = new StorageAccessImpl( cache );
}
@Override
public StorageAccess getStorageAccess() {
return cacheAccess;
}
}

View File

@ -0,0 +1,13 @@
#
# Hibernate, Relational Persistence for Idiomatic Java
#
# License: GNU Lesser General Public License (LGPL), version 2.1 or later
# See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
#
#
# Hibernate, Relational Persistence for Idiomatic Java
#
# License: GNU Lesser General Public License (LGPL), version 2.1 or later
# See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
org.hibernate.cache.ehcache.internal.StrategyRegistrationProviderImpl

View File

@ -0,0 +1,62 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.cache.ehcache.test;
import java.util.Collection;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.cache.ehcache.internal.EhcacheRegionFactory;
import org.hibernate.cache.ehcache.internal.SingletonEhcacheRegionFactory;
import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cfg.AvailableSettings;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* @author Steve Ebersole
*/
public class SmokeTest {
@Test
public void testStrategySelectorRegistrations() {
final BootstrapServiceRegistry registry = new BootstrapServiceRegistryBuilder().build();
final Collection<Class<? extends RegionFactory>> implementors = registry
.getService( StrategySelector.class )
.getRegisteredStrategyImplementors( RegionFactory.class );
assertTrue( implementors.contains( EhcacheRegionFactory.class ) );
assertTrue( implementors.contains( SingletonEhcacheRegionFactory.class ) );
}
@Test
public void testEhcacheShortName() {
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
.applySetting( AvailableSettings.CACHE_REGION_FACTORY, "ehcache" )
.build();
assertThat(
registry.getService( RegionFactory.class ),
instanceOf( EhcacheRegionFactory.class )
);
}
@Test
public void testSingletonEhcacheShortName() {
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
.applySetting( AvailableSettings.CACHE_REGION_FACTORY, "ehcache-singleton" )
.build();
assertThat(
registry.getService( RegionFactory.class ),
instanceOf( SingletonEhcacheRegionFactory.class )
);
}
}

View File

@ -0,0 +1,17 @@
#
# Hibernate, Relational Persistence for Idiomatic Java
#
# License: GNU Lesser General Public License (LGPL), version 2.1 or later
# See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
#
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.rootLogger=info, stdout
log4j.logger.org.hibernate.test=info
# SQL Logging - HHH-6833
log4j.logger.org.hibernate.SQL=debug

View File

@ -11,6 +11,7 @@ import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.MessageLogger; import org.jboss.logging.annotations.MessageLogger;
import org.hibernate.cache.spi.Region; import org.hibernate.cache.spi.Region;
import org.hibernate.cache.spi.SecondLevelCacheLogger;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import static org.jboss.logging.Logger.Level.ERROR; import static org.jboss.logging.Logger.Level.ERROR;
@ -24,19 +25,27 @@ public interface JCacheMessageLogger extends CoreMessageLogger {
static final int NAMESPACE = 40000; static final int NAMESPACE = 40000;
/**
* @deprecated (since 5.3) Use {@link SecondLevelCacheLogger#attemptToStartAlreadyStartedCacheProvider()}
*/
@LogMessage(level = WARN) @LogMessage(level = WARN)
@Message( @Message(
value = "Attempt to restart an already started JCacheRegionFactory. Use sessionFactory.close() between " + value = "Attempt to restart an already started JCacheRegionFactory. Use sessionFactory.close() between " +
"repeated calls to buildSessionFactory. Using previously created JCacheRegionFactory.", "repeated calls to buildSessionFactory. Using previously created JCacheRegionFactory.",
id = NAMESPACE + 1 id = NAMESPACE + 1
) )
@Deprecated
void attemptToRestartAlreadyStartedJCacheProvider(); void attemptToRestartAlreadyStartedJCacheProvider();
/**
* @deprecated (since 5.3) Use {@link SecondLevelCacheLogger#attemptToStopAlreadyStoppedCacheProvider()}
*/
@LogMessage(level = WARN) @LogMessage(level = WARN)
@Message( @Message(
value = "Attempt to restop an already stopped JCacheRegionFactory.", value = "Attempt to restop an already stopped JCacheRegionFactory.",
id = NAMESPACE + 2 id = NAMESPACE + 2
) )
@Deprecated
void attemptToRestopAlreadyStoppedJCacheProvider(); void attemptToRestopAlreadyStoppedJCacheProvider();
@LogMessage(level = ERROR) @LogMessage(level = ERROR)

View File

@ -26,6 +26,7 @@ import org.hibernate.cache.spi.CacheKeysFactory;
import org.hibernate.cache.spi.DomainDataRegion; import org.hibernate.cache.spi.DomainDataRegion;
import org.hibernate.cache.spi.QueryResultsRegion; import org.hibernate.cache.spi.QueryResultsRegion;
import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cache.spi.SecondLevelCacheLogger;
import org.hibernate.cache.spi.TimestampsRegion; import org.hibernate.cache.spi.TimestampsRegion;
import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.cache.spi.support.RegionNameQualifier; import org.hibernate.cache.spi.support.RegionNameQualifier;
@ -98,7 +99,7 @@ public class JCacheRegionFactory implements RegionFactory {
} }
} }
else { else {
LOG.attemptToRestartAlreadyStartedJCacheProvider(); SecondLevelCacheLogger.INSTANCE.attemptToStartAlreadyStartedCacheProvider();
} }
} }

View File

@ -0,0 +1,41 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.testing.mocks.url;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* @author Steve Ebersole
*/
public class MockHttpURLConnection extends HttpURLConnection {
protected MockHttpURLConnection(URL url) {
super( url );
}
@Override
public InputStream getInputStream() throws IOException {
throw new UnsupportedOperationException( "not yet implemented" );
}
@Override
public void connect() throws IOException {
}
@Override
public void disconnect() {
}
@Override
public boolean usingProxy() {
return false;
}
}