HHH-15422 Pick up ConnectionProvider from BeanContainer if not explicit set
This commit is contained in:
parent
657e7a278a
commit
8b5bc445c8
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.engine.jdbc.connections.internal;
|
package org.hibernate.engine.jdbc.connections.internal;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -19,6 +20,11 @@ import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
|
import org.hibernate.resource.beans.container.spi.BeanContainer;
|
||||||
|
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
|
||||||
|
import org.hibernate.resource.beans.internal.Helper;
|
||||||
|
import org.hibernate.resource.beans.spi.BeanInstanceProducer;
|
||||||
|
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
||||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
|
|
||||||
import static java.sql.Connection.TRANSACTION_NONE;
|
import static java.sql.Connection.TRANSACTION_NONE;
|
||||||
|
@ -102,6 +108,7 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final BeanContainer beanContainer = Helper.allowExtensionsInCdi( registry ) ? registry.requireService( ManagedBeanRegistry.class ).getBeanContainer() : null;
|
||||||
final StrategySelector strategySelector = registry.requireService( StrategySelector.class );
|
final StrategySelector strategySelector = registry.requireService( StrategySelector.class );
|
||||||
final Object explicitSetting = configurationValues.get( CONNECTION_PROVIDER );
|
final Object explicitSetting = configurationValues.get( CONNECTION_PROVIDER );
|
||||||
if ( explicitSetting != null ) {
|
if ( explicitSetting != null ) {
|
||||||
|
@ -111,25 +118,25 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
|
||||||
}
|
}
|
||||||
else if ( explicitSetting instanceof Class<?> providerClass ) {
|
else if ( explicitSetting instanceof Class<?> providerClass ) {
|
||||||
LOG.instantiatingExplicitConnectionProvider( providerClass.getName() );
|
LOG.instantiatingExplicitConnectionProvider( providerClass.getName() );
|
||||||
return instantiateExplicitConnectionProvider( providerClass );
|
return instantiateExplicitConnectionProvider( providerClass, beanContainer );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final String providerName = nullIfEmpty( explicitSetting.toString() );
|
final String providerName = nullIfEmpty( explicitSetting.toString() );
|
||||||
if ( providerName != null ) {
|
if ( providerName != null ) {
|
||||||
return instantiateNamedConnectionProvider(providerName, strategySelector);
|
return instantiateNamedConnectionProvider(providerName, strategySelector, beanContainer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return instantiateConnectionProvider( configurationValues, strategySelector );
|
return instantiateConnectionProvider( configurationValues, strategySelector, beanContainer );
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConnectionProvider instantiateNamedConnectionProvider(String providerName, StrategySelector strategySelector) {
|
private ConnectionProvider instantiateNamedConnectionProvider(String providerName, StrategySelector strategySelector, BeanContainer beanContainer) {
|
||||||
LOG.instantiatingExplicitConnectionProvider( providerName );
|
LOG.instantiatingExplicitConnectionProvider( providerName );
|
||||||
final Class<?> providerClass =
|
final Class<?> providerClass =
|
||||||
strategySelector.selectStrategyImplementor( ConnectionProvider.class, providerName );
|
strategySelector.selectStrategyImplementor( ConnectionProvider.class, providerName );
|
||||||
try {
|
try {
|
||||||
return instantiateExplicitConnectionProvider( providerClass );
|
return instantiateExplicitConnectionProvider( providerClass, beanContainer );
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
throw new HibernateException(
|
throw new HibernateException(
|
||||||
|
@ -140,7 +147,7 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConnectionProvider instantiateConnectionProvider(
|
private ConnectionProvider instantiateConnectionProvider(
|
||||||
Map<String, Object> configurationValues, StrategySelector strategySelector) {
|
Map<String, Object> configurationValues, StrategySelector strategySelector, BeanContainer beanContainer) {
|
||||||
if ( configurationValues.containsKey( DATASOURCE ) ) {
|
if ( configurationValues.containsKey( DATASOURCE ) ) {
|
||||||
return new DatasourceConnectionProviderImpl();
|
return new DatasourceConnectionProviderImpl();
|
||||||
}
|
}
|
||||||
|
@ -149,9 +156,9 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
|
||||||
getSingleRegisteredProvider( strategySelector );
|
getSingleRegisteredProvider( strategySelector );
|
||||||
if ( singleRegisteredProvider != null ) {
|
if ( singleRegisteredProvider != null ) {
|
||||||
try {
|
try {
|
||||||
return singleRegisteredProvider.newInstance();
|
return singleRegisteredProvider.getConstructor().newInstance();
|
||||||
}
|
}
|
||||||
catch (IllegalAccessException | InstantiationException e) {
|
catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException | InstantiationException e) {
|
||||||
throw new HibernateException( "Could not instantiate singular-registered ConnectionProvider", e );
|
throw new HibernateException( "Could not instantiate singular-registered ConnectionProvider", e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,11 +184,47 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
|
||||||
return new DriverManagerConnectionProviderImpl();
|
return new DriverManagerConnectionProviderImpl();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG.noAppropriateConnectionProvider();
|
if (beanContainer != null) {
|
||||||
return new UserSuppliedConnectionProviderImpl();
|
return beanContainer.getBean(
|
||||||
|
ConnectionProvider.class,
|
||||||
|
new BeanContainer.LifecycleOptions() {
|
||||||
|
@Override
|
||||||
|
public boolean canUseCachedReferences() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean useJpaCompliantCreation() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new BeanInstanceProducer() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <B> B produceBeanInstance(Class<B> beanType) {
|
||||||
|
return (B) noAppropriateConnectionProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <B> B produceBeanInstance(String name, Class<B> beanType) {
|
||||||
|
return (B) noAppropriateConnectionProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
).getBeanInstance();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return noAppropriateConnectionProvider();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ConnectionProvider noAppropriateConnectionProvider() {
|
||||||
|
LOG.noAppropriateConnectionProvider();
|
||||||
|
return new UserSuppliedConnectionProviderImpl();
|
||||||
|
}
|
||||||
|
|
||||||
private Class<? extends ConnectionProvider> getSingleRegisteredProvider(StrategySelector strategySelector) {
|
private Class<? extends ConnectionProvider> getSingleRegisteredProvider(StrategySelector strategySelector) {
|
||||||
final Collection<Class<? extends ConnectionProvider>> implementors =
|
final Collection<Class<? extends ConnectionProvider>> implementors =
|
||||||
strategySelector.getRegisteredStrategyImplementors( ConnectionProvider.class );
|
strategySelector.getRegisteredStrategyImplementors( ConnectionProvider.class );
|
||||||
|
@ -190,9 +233,28 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConnectionProvider instantiateExplicitConnectionProvider(Class<?> providerClass) {
|
private ConnectionProvider instantiateExplicitConnectionProvider(Class<?> providerClass, BeanContainer beanContainer) {
|
||||||
try {
|
try {
|
||||||
return (ConnectionProvider) providerClass.newInstance();
|
if ( beanContainer != null ) {
|
||||||
|
return (ConnectionProvider) beanContainer.getBean(
|
||||||
|
providerClass,
|
||||||
|
new BeanContainer.LifecycleOptions() {
|
||||||
|
@Override
|
||||||
|
public boolean canUseCachedReferences() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean useJpaCompliantCreation() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
FallbackBeanInstanceProducer.INSTANCE
|
||||||
|
).getBeanInstance();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (ConnectionProvider) providerClass.getConstructor().newInstance();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
throw new HibernateException( "Could not instantiate connection provider [" + providerClass.getName() + "]", e );
|
throw new HibernateException( "Could not instantiate connection provider [" + providerClass.getName() + "]", e );
|
||||||
|
@ -201,7 +263,7 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
|
||||||
|
|
||||||
private static ConnectionProvider instantiateProvider(StrategySelector selector, String strategy) {
|
private static ConnectionProvider instantiateProvider(StrategySelector selector, String strategy) {
|
||||||
try {
|
try {
|
||||||
return selector.selectStrategyImplementor( ConnectionProvider.class, strategy ).newInstance();
|
return selector.selectStrategyImplementor( ConnectionProvider.class, strategy ).getConstructor().newInstance();
|
||||||
}
|
}
|
||||||
catch ( Exception e ) {
|
catch ( Exception e ) {
|
||||||
LOG.providerClassNotFound(strategy);
|
LOG.providerClassNotFound(strategy);
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
* Copyright Red Hat Inc. and Hibernate Authors
|
||||||
|
*/
|
||||||
|
package org.hibernate.orm.test.connections;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.dialect.H2Dialect;
|
||||||
|
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||||
|
import org.hibernate.resource.beans.container.spi.BeanContainer;
|
||||||
|
import org.hibernate.resource.beans.container.spi.ContainedBean;
|
||||||
|
import org.hibernate.resource.beans.spi.BeanInstanceProducer;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
|
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||||
|
import org.hibernate.testing.util.ServiceRegistryUtil;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hibernate.cfg.JdbcSettings.CONNECTION_PROVIDER;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Yanming Zhou
|
||||||
|
*/
|
||||||
|
@RequiresDialect(H2Dialect.class)
|
||||||
|
public class ConnectionProviderFromBeanContainerTest extends BaseUnitTestCase {
|
||||||
|
|
||||||
|
private final ConnectionProvider dummyConnectionProvider = new DummyConnectionProvider();
|
||||||
|
|
||||||
|
private Map<String, Object> createSettings() {
|
||||||
|
Map<String, Object> settings = new HashMap<>();
|
||||||
|
settings.put( AvailableSettings.ALLOW_EXTENSIONS_IN_CDI, "true" );
|
||||||
|
settings.put( AvailableSettings.BEAN_CONTAINER, new BeanContainer() {
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <B> ContainedBean<B> getBean(
|
||||||
|
Class<B> beanType,
|
||||||
|
LifecycleOptions lifecycleOptions,
|
||||||
|
BeanInstanceProducer fallbackProducer) {
|
||||||
|
return () -> (B) ( beanType == DummyConnectionProvider.class ?
|
||||||
|
dummyConnectionProvider : fallbackProducer.produceBeanInstance( beanType ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <B> ContainedBean<B> getBean(
|
||||||
|
String name,
|
||||||
|
Class<B> beanType,
|
||||||
|
LifecycleOptions lifecycleOptions,
|
||||||
|
BeanInstanceProducer fallbackProducer) {
|
||||||
|
return () -> (B) fallbackProducer.produceBeanInstance( beanType );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProviderFromBeanContainerInUse() {
|
||||||
|
Map<String, Object> settings = createSettings();
|
||||||
|
settings.putIfAbsent( CONNECTION_PROVIDER, DummyConnectionProvider.class.getName() );
|
||||||
|
try ( ServiceRegistry serviceRegistry = ServiceRegistryUtil.serviceRegistryBuilder()
|
||||||
|
.applySettings( settings ).build() ) {
|
||||||
|
ConnectionProvider providerInUse = serviceRegistry.getService( ConnectionProvider.class );
|
||||||
|
assertSame( dummyConnectionProvider, providerInUse );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DummyConnectionProvider implements ConnectionProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUnwrappableAs(Class<?> unwrapType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T unwrap(Class<T> unwrapType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection getConnection() throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeConnection(Connection connection) throws SQLException {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsAggressiveRelease() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue