From 1174cdad654e74959ec2be8de7599a81dd3840c7 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Wed, 21 Mar 2018 19:23:38 -0500 Subject: [PATCH] HHH-12417 - default strategy based on registrations with StrategySelector ConnectionProviderInitiator and tests --- .../selector/spi/StrategySelector.java | 2 +- .../internal/RegionFactoryInitiator.java | 4 +- .../internal/ConnectionProviderInitiator.java | 57 ++++++++++---- .../hibernate/engine/spi/CacheInitiator.java | 5 +- .../cache/SingleRegisteredProviderTest.java | 75 +++++++++++++++++++ .../StrategyRegistrationProviderImpl.java | 38 ++++++++++ ...stry.selector.StrategyRegistrationProvider | 7 ++ 7 files changed, 172 insertions(+), 16 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/cache/SingleRegisteredProviderTest.java create mode 100644 hibernate-testing/src/main/java/org/hibernate/testing/cache/StrategyRegistrationProviderImpl.java create mode 100644 hibernate-testing/src/main/resources/META-INF/services/org.hibernate.boot.registry.selector.StrategyRegistrationProvider diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelector.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelector.java index 01dd6a3268ba..457d1d29e14b 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelector.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelector.java @@ -146,5 +146,5 @@ public interface StrategySelector extends Service { * to allow defaulting the choice to the single registered implementor when * only one is registered */ - Collection getRegisteredStrategyImplementors(Class strategy); + Collection> getRegisteredStrategyImplementors(Class strategy); } diff --git a/hibernate-core/src/main/java/org/hibernate/cache/internal/RegionFactoryInitiator.java b/hibernate-core/src/main/java/org/hibernate/cache/internal/RegionFactoryInitiator.java index 796873a1db89..18a45ae067d8 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/internal/RegionFactoryInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/internal/RegionFactoryInitiator.java @@ -77,9 +77,11 @@ public RegionFactory initiateService(Map configurationValues, ServiceRegistryImp boolean allowDefaulting = true; if ( allowDefaulting ) { final StrategySelector selector = registry.getService( StrategySelector.class ); - final Collection implementors = selector.getRegisteredStrategyImplementors( RegionFactory.class ); + final Collection> 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" ); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/ConnectionProviderInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/ConnectionProviderInitiator.java index 2a249083fe1f..6f7978cc83f9 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/ConnectionProviderInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/ConnectionProviderInitiator.java @@ -10,6 +10,7 @@ import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.sql.Connection; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -122,20 +123,31 @@ else if ( explicitSetting instanceof Class ) { return instantiateExplicitConnectionProvider( providerClass ); } else { - String providerName = explicitSetting.toString(); - if ( LEGACY_CONNECTION_PROVIDER_MAPPING.containsKey( providerName ) ) { - final String actualProviderName = LEGACY_CONNECTION_PROVIDER_MAPPING.get( providerName ); - DeprecationLogger.DEPRECATION_LOGGER.connectionProviderClassDeprecated( providerName, actualProviderName ); - providerName = actualProviderName; - } + String providerName = StringHelper.nullIfEmpty( explicitSetting.toString() ); + if ( providerName != null ) { + if ( LEGACY_CONNECTION_PROVIDER_MAPPING.containsKey( providerName ) ) { + final String actualProviderName = LEGACY_CONNECTION_PROVIDER_MAPPING.get( providerName ); + DeprecationLogger.DEPRECATION_LOGGER.connectionProviderClassDeprecated( + providerName, + actualProviderName + ); + providerName = actualProviderName; + } - LOG.instantiatingExplicitConnectionProvider( providerName ); - final Class providerClass = strategySelector.selectStrategyImplementor( ConnectionProvider.class, providerName ); - try { - return instantiateExplicitConnectionProvider( providerClass ); - } - catch (Exception e) { - throw new HibernateException( "Could not instantiate connection provider [" + providerName + "]", e ); + LOG.instantiatingExplicitConnectionProvider( providerName ); + final Class providerClass = strategySelector.selectStrategyImplementor( + ConnectionProvider.class, + providerName + ); + try { + return instantiateExplicitConnectionProvider( providerClass ); + } + catch (Exception e) { + throw new HibernateException( + "Could not instantiate connection provider [" + providerName + "]", + e + ); + } } } } @@ -146,6 +158,16 @@ else if ( explicitSetting instanceof Class ) { ConnectionProvider connectionProvider = null; + final Class singleRegisteredProvider = getSingleRegisteredProvider( strategySelector ); + if ( singleRegisteredProvider != null ) { + try { + connectionProvider = singleRegisteredProvider.newInstance(); + } + catch (IllegalAccessException | InstantiationException e) { + throw new HibernateException( "Could not instantiate singular-registered ConnectionProvider", e ); + } + } + if ( connectionProvider == null ) { if ( c3p0ConfigDefined( configurationValues ) ) { connectionProvider = instantiateC3p0Provider( strategySelector ); @@ -214,6 +236,15 @@ public void processBeanInfo(BeanInfo beanInfo) throws Exception { return connectionProvider; } + private Class getSingleRegisteredProvider(StrategySelector strategySelector) { + final Collection> implementors = strategySelector.getRegisteredStrategyImplementors( ConnectionProvider.class ); + if ( implementors != null && implementors.size() == 1 ) { + return implementors.iterator().next(); + } + + return null; + } + private ConnectionProvider instantiateExplicitConnectionProvider(Class providerClass) { try { return (ConnectionProvider) providerClass.newInstance(); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/CacheInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/CacheInitiator.java index 66bdc04c70b2..5f9c5633656f 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/CacheInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/CacheInitiator.java @@ -9,7 +9,9 @@ import org.hibernate.boot.spi.SessionFactoryOptions; import org.hibernate.cache.internal.DisabledCaching; import org.hibernate.cache.internal.EnabledCaching; +import org.hibernate.cache.internal.NoCachingRegionFactory; import org.hibernate.cache.spi.CacheImplementor; +import org.hibernate.cache.spi.RegionFactory; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.SessionFactoryServiceInitiator; @@ -27,7 +29,8 @@ public CacheImplementor initiateService( SessionFactoryImplementor sessionFactory, SessionFactoryOptions sessionFactoryOptions, ServiceRegistryImplementor registry) { - return sessionFactoryOptions.isSecondLevelCacheEnabled() + final RegionFactory regionFactory = registry.getService( RegionFactory.class ); + return ( ! NoCachingRegionFactory.class.isInstance( regionFactory ) ) ? new EnabledCaching( sessionFactory ) : new DisabledCaching( sessionFactory ); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/cache/SingleRegisteredProviderTest.java b/hibernate-core/src/test/java/org/hibernate/test/cache/SingleRegisteredProviderTest.java new file mode 100644 index 000000000000..e34f3e861dc6 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/cache/SingleRegisteredProviderTest.java @@ -0,0 +1,75 @@ +/* + * 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.test.cache; + +import java.util.Collection; + +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.selector.spi.StrategySelector; +import org.hibernate.cache.internal.EnabledCaching; +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.junit.Test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * @author Steve Ebersole + */ +public class SingleRegisteredProviderTest extends BaseNonConfigCoreFunctionalTestCase { + @Override + protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) { + super.configureStandardServiceRegistryBuilder( ssrb ); + + 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 ); + } + + @Test + public void testCachingExpectations() { + final Collection> implementors = sessionFactory().getServiceRegistry() + .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 ) ); + } + + @Test + public void testConnectionsExpectations() { + final Collection> implementors = sessionFactory().getServiceRegistry() + .getService( StrategySelector.class ) + .getRegisteredStrategyImplementors( ConnectionProvider.class ); + + assertThat( implementors.size(), equalTo( 1 ) ); + + final ConnectionProvider configuredProvider = sessionFactory().getServiceRegistry().getService( ConnectionProvider.class ); + + assertThat( configuredProvider, instanceOf( DriverManagerConnectionProviderImpl.class ) ); + assertThat( implementors.iterator().next(), equalTo( DriverManagerConnectionProviderImpl.class ) ); + } +} diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/StrategyRegistrationProviderImpl.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/StrategyRegistrationProviderImpl.java new file mode 100644 index 000000000000..511aa7545d73 --- /dev/null +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/StrategyRegistrationProviderImpl.java @@ -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.testing.cache; + +import java.util.ArrayList; +import java.util.Collections; +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 JCache RegionFactory available to the Hibernate + * {@link org.hibernate.boot.registry.selector.spi.StrategySelector} service + * under a number of keys. Prefer to use + * + * @author Steve Ebersole + */ +public class StrategyRegistrationProviderImpl implements StrategyRegistrationProvider { + @Override + @SuppressWarnings("unchecked") + public Iterable getStrategyRegistrations() { + return Collections.singletonList( + new SimpleStrategyRegistrationImpl( + RegionFactory.class, + CachingRegionFactory.class, + "testing", + CachingRegionFactory.class.getName() + ) + ); + } +} diff --git a/hibernate-testing/src/main/resources/META-INF/services/org.hibernate.boot.registry.selector.StrategyRegistrationProvider b/hibernate-testing/src/main/resources/META-INF/services/org.hibernate.boot.registry.selector.StrategyRegistrationProvider new file mode 100644 index 000000000000..0548f9551697 --- /dev/null +++ b/hibernate-testing/src/main/resources/META-INF/services/org.hibernate.boot.registry.selector.StrategyRegistrationProvider @@ -0,0 +1,7 @@ +# +# 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.testing.cache.StrategyRegistrationProviderImpl \ No newline at end of file