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:
parent
84897f0ad0
commit
7f12e2a161
|
@ -145,6 +145,8 @@ public interface StrategySelector extends Service {
|
|||
* Retrieve all of the registered implementors of the given strategy. Useful
|
||||
* to allow defaulting the choice to the single registered implementor when
|
||||
* only one is registered
|
||||
*
|
||||
* @return The implementors. Should never return {@code null}
|
||||
*/
|
||||
<T> Collection<Class<? extends T>> getRegisteredStrategyImplementors(Class<T> strategy);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.Properties;
|
|||
|
||||
import org.hibernate.boot.registry.StandardServiceInitiator;
|
||||
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
|
@ -19,6 +20,9 @@ import org.hibernate.internal.CoreMessageLogger;
|
|||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* Initiator for the {@link RegionFactory} service.
|
||||
*
|
||||
|
@ -39,58 +43,78 @@ public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFa
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public RegionFactory initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
|
||||
final Properties p = new Properties();
|
||||
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" );
|
||||
}
|
||||
}
|
||||
}
|
||||
final RegionFactory regionFactory = resolveRegionFactory( configurationValues, registry );
|
||||
|
||||
LOG.debugf( "Cache region factory : %s", regionFactory.getClass().getName() );
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.jboss.logging.annotations.Message;
|
|||
import org.jboss.logging.annotations.MessageLogger;
|
||||
import org.jboss.logging.annotations.ValidIdRange;
|
||||
|
||||
import static org.jboss.logging.Logger.Level.INFO;
|
||||
import static org.jboss.logging.Logger.Level.WARN;
|
||||
|
||||
/**
|
||||
|
@ -28,18 +29,47 @@ public interface SecondLevelCacheLogger extends BasicLogger {
|
|||
"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 )
|
||||
@Message(
|
||||
value = "Read-only caching was requested for mutable entity [%s]",
|
||||
id = 90001001
|
||||
id = NAMESPACE + 3
|
||||
)
|
||||
void readOnlyCachingMutableEntity(NavigableRole navigableRole);
|
||||
|
||||
@LogMessage( level = WARN )
|
||||
@Message(
|
||||
value = "Read-only caching was requested for mutable natural-id for entity [%s]",
|
||||
id = 90001002
|
||||
id = NAMESPACE + 4
|
||||
)
|
||||
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);
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.util.concurrent.locks.Lock;
|
|||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import org.hibernate.cache.spi.DomainDataRegion;
|
||||
import org.hibernate.cache.spi.SecondLevelCacheLogger;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
||||
|
@ -179,6 +180,7 @@ public abstract class AbstractReadWriteAccess extends AbstractCachedDomainDataAc
|
|||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected void handleLockExpiry(SharedSessionContractImplementor session, Object key, Lockable lock) {
|
||||
SecondLevelCacheLogger.INSTANCE.softLockedCacheExpired( getRegion().getName(), key );
|
||||
log.info( "Cached entry expired : " + key );
|
||||
|
||||
// create new lock that times out immediately
|
||||
|
|
|
@ -8,17 +8,18 @@ package org.hibernate.test.cache;
|
|||
|
||||
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.internal.EnabledCaching;
|
||||
import org.hibernate.cache.internal.NoCachingRegionFactory;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
|
||||
import org.hibernate.testing.cache.CachingRegionFactory;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
|
@ -28,48 +29,78 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SingleRegisteredProviderTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||
public class SingleRegisteredProviderTest extends BaseUnitTestCase {
|
||||
@Test
|
||||
public void testCachingExplicitlyDisabled() {
|
||||
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
|
||||
.applySetting( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" )
|
||||
.build();
|
||||
|
||||
ssrb.applySetting( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
|
||||
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 );
|
||||
assertThat( registry.getService( RegionFactory.class ), instanceOf( NoCachingRegionFactory.class ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCachingExpectations() {
|
||||
final Collection<Class<? extends RegionFactory>> implementors = sessionFactory().getServiceRegistry()
|
||||
public void testCachingImplicitlyEnabledRegistered() {
|
||||
final BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
|
||||
.build();
|
||||
|
||||
final Collection<Class<? extends RegionFactory>> implementors = bsr
|
||||
.getService( StrategySelector.class )
|
||||
.getRegisteredStrategyImplementors( RegionFactory.class );
|
||||
|
||||
assertThat( implementors.size(), equalTo( 1 ) );
|
||||
assertThat( sessionFactory().getSessionFactoryOptions().isSecondLevelCacheEnabled(), equalTo( true ) );
|
||||
assertThat( sessionFactory().getCache(), instanceOf( EnabledCaching.class ) );
|
||||
assertThat( sessionFactory().getCache().getRegionFactory(), instanceOf( CachingRegionFactory.class ) );
|
||||
assertThat( implementors.iterator().next(), equalTo( CachingRegionFactory.class ) );
|
||||
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
|
||||
.applySetting( AvailableSettings.USE_SECOND_LEVEL_CACHE, "" )
|
||||
.build();
|
||||
|
||||
assertThat( ssr.getService( RegionFactory.class ), instanceOf( NoCachingRegionFactory.class ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionsExpectations() {
|
||||
final Collection<Class<? extends ConnectionProvider>> implementors = sessionFactory().getServiceRegistry()
|
||||
public void testCachingImplicitlyEnabledNoRegistered() {
|
||||
final BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
|
||||
.build();
|
||||
|
||||
final Collection<Class<? extends RegionFactory>> implementors = bsr
|
||||
.getService( StrategySelector.class )
|
||||
.getRegisteredStrategyImplementors( ConnectionProvider.class );
|
||||
.getRegisteredStrategyImplementors( RegionFactory.class );
|
||||
|
||||
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( implementors.iterator().next(), equalTo( DriverManagerConnectionProviderImpl.class ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,31 +5,11 @@
|
|||
* 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/publishing-repos.gradle' )
|
||||
apply from: rootProject.file( 'gradle/publishing-pom.gradle' )
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'maven-publish-auth'
|
||||
apply from: rootProject.file( 'gradle/published-java-module.gradle' )
|
||||
|
||||
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 {
|
||||
relocatedGroupId = 'org.hibernate'
|
||||
relocatedArtifactId = 'hibernate-jcache'
|
||||
relocatedVersion = project.version
|
||||
dependencies {
|
||||
compile project( ':hibernate-core' )
|
||||
compile( libraries.ehcache )
|
||||
}
|
||||
|
||||
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 )
|
28
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/ConfigSettings.java
vendored
Normal file
28
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/ConfigSettings.java
vendored
Normal 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";
|
||||
}
|
48
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/DomainDataRegionImpl.java
vendored
Normal file
48
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/DomainDataRegionImpl.java
vendored
Normal 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();
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
112
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/EhCacheMessageLogger.java
vendored
Normal file
112
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/EhCacheMessageLogger.java
vendored
Normal 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);
|
||||
|
||||
}
|
322
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/EhcacheRegionFactory.java
vendored
Normal file
322
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/EhcacheRegionFactory.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
68
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/HibernateEhcacheUtils.java
vendored
Normal file
68
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/HibernateEhcacheUtils.java
vendored
Normal 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() );
|
||||
}
|
||||
}
|
36
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/QueryResultsRegionImpl.java
vendored
Normal file
36
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/QueryResultsRegionImpl.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
137
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/StorageAccessImpl.java
vendored
Normal file
137
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/StorageAccessImpl.java
vendored
Normal 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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
38
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/TimestampsRegionImpl.java
vendored
Normal file
38
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/TimestampsRegionImpl.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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
|
62
hibernate-ehcache/src/test/java/org/hibernate/cache/ehcache/test/SmokeTest.java
vendored
Normal file
62
hibernate-ehcache/src/test/java/org/hibernate/cache/ehcache/test/SmokeTest.java
vendored
Normal 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 )
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -11,6 +11,7 @@ import org.jboss.logging.annotations.Message;
|
|||
import org.jboss.logging.annotations.MessageLogger;
|
||||
|
||||
import org.hibernate.cache.spi.Region;
|
||||
import org.hibernate.cache.spi.SecondLevelCacheLogger;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
import static org.jboss.logging.Logger.Level.ERROR;
|
||||
|
@ -24,19 +25,27 @@ public interface JCacheMessageLogger extends CoreMessageLogger {
|
|||
|
||||
static final int NAMESPACE = 40000;
|
||||
|
||||
/**
|
||||
* @deprecated (since 5.3) Use {@link SecondLevelCacheLogger#attemptToStartAlreadyStartedCacheProvider()}
|
||||
*/
|
||||
@LogMessage(level = WARN)
|
||||
@Message(
|
||||
value = "Attempt to restart an already started JCacheRegionFactory. Use sessionFactory.close() between " +
|
||||
"repeated calls to buildSessionFactory. Using previously created JCacheRegionFactory.",
|
||||
id = NAMESPACE + 1
|
||||
)
|
||||
@Deprecated
|
||||
void attemptToRestartAlreadyStartedJCacheProvider();
|
||||
|
||||
/**
|
||||
* @deprecated (since 5.3) Use {@link SecondLevelCacheLogger#attemptToStopAlreadyStoppedCacheProvider()}
|
||||
*/
|
||||
@LogMessage(level = WARN)
|
||||
@Message(
|
||||
value = "Attempt to restop an already stopped JCacheRegionFactory.",
|
||||
id = NAMESPACE + 2
|
||||
)
|
||||
@Deprecated
|
||||
void attemptToRestopAlreadyStoppedJCacheProvider();
|
||||
|
||||
@LogMessage(level = ERROR)
|
||||
|
|
|
@ -26,6 +26,7 @@ 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;
|
||||
|
@ -98,7 +99,7 @@ public class JCacheRegionFactory implements RegionFactory {
|
|||
}
|
||||
}
|
||||
else {
|
||||
LOG.attemptToRestartAlreadyStartedJCacheProvider();
|
||||
SecondLevelCacheLogger.INSTANCE.attemptToStartAlreadyStartedCacheProvider();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue