Skip to content

Commit 942353e

Browse files
committed
HHH-15422 Pick up ConnectionProvider from BeanContainer if not explicit set
1 parent 7582932 commit 942353e

File tree

2 files changed

+180
-13
lines changed

2 files changed

+180
-13
lines changed

hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/ConnectionProviderInitiator.java

Lines changed: 76 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package org.hibernate.engine.jdbc.connections.internal;
66

7+
import java.lang.reflect.InvocationTargetException;
78
import java.sql.Connection;
89
import java.util.Collection;
910
import java.util.HashSet;
@@ -19,6 +20,11 @@
1920
import org.hibernate.internal.CoreLogging;
2021
import org.hibernate.internal.CoreMessageLogger;
2122
import org.hibernate.internal.util.StringHelper;
23+
import org.hibernate.resource.beans.container.spi.BeanContainer;
24+
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
25+
import org.hibernate.resource.beans.internal.Helper;
26+
import org.hibernate.resource.beans.spi.BeanInstanceProducer;
27+
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
2228
import org.hibernate.service.spi.ServiceRegistryImplementor;
2329

2430
import static java.sql.Connection.TRANSACTION_NONE;
@@ -50,6 +56,7 @@
5056
* @author Steve Ebersole
5157
* @author Brett Meyer
5258
*/
59+
@SuppressWarnings( {"deprecation", "unchecked"} )
5360
public class ConnectionProviderInitiator implements StandardServiceInitiator<ConnectionProvider> {
5461
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( ConnectionProviderInitiator.class );
5562

@@ -102,6 +109,7 @@ public ConnectionProvider initiateService(
102109
return null;
103110
}
104111

112+
final BeanContainer beanContainer = Helper.allowExtensionsInCdi( registry ) ? registry.requireService( ManagedBeanRegistry.class ).getBeanContainer() : null;
105113
final StrategySelector strategySelector = registry.requireService( StrategySelector.class );
106114
final Object explicitSetting = configurationValues.get( CONNECTION_PROVIDER );
107115
if ( explicitSetting != null ) {
@@ -111,25 +119,25 @@ public ConnectionProvider initiateService(
111119
}
112120
else if ( explicitSetting instanceof Class<?> providerClass ) {
113121
LOG.instantiatingExplicitConnectionProvider( providerClass.getName() );
114-
return instantiateExplicitConnectionProvider( providerClass );
122+
return instantiateExplicitConnectionProvider( providerClass, beanContainer );
115123
}
116124
else {
117125
final String providerName = nullIfEmpty( explicitSetting.toString() );
118126
if ( providerName != null ) {
119-
return instantiateNamedConnectionProvider(providerName, strategySelector);
127+
return instantiateNamedConnectionProvider(providerName, strategySelector, beanContainer);
120128
}
121129
}
122130
}
123131

124-
return instantiateConnectionProvider( configurationValues, strategySelector );
132+
return instantiateConnectionProvider( configurationValues, strategySelector, beanContainer );
125133
}
126134

127-
private ConnectionProvider instantiateNamedConnectionProvider(String providerName, StrategySelector strategySelector) {
135+
private ConnectionProvider instantiateNamedConnectionProvider(String providerName, StrategySelector strategySelector, BeanContainer beanContainer) {
128136
LOG.instantiatingExplicitConnectionProvider( providerName );
129137
final Class<?> providerClass =
130138
strategySelector.selectStrategyImplementor( ConnectionProvider.class, providerName );
131139
try {
132-
return instantiateExplicitConnectionProvider( providerClass );
140+
return instantiateExplicitConnectionProvider( providerClass, beanContainer );
133141
}
134142
catch (Exception e) {
135143
throw new HibernateException(
@@ -140,7 +148,7 @@ private ConnectionProvider instantiateNamedConnectionProvider(String providerNam
140148
}
141149

142150
private ConnectionProvider instantiateConnectionProvider(
143-
Map<String, Object> configurationValues, StrategySelector strategySelector) {
151+
Map<String, Object> configurationValues, StrategySelector strategySelector, BeanContainer beanContainer) {
144152
if ( configurationValues.containsKey( DATASOURCE ) ) {
145153
return new DatasourceConnectionProviderImpl();
146154
}
@@ -149,9 +157,9 @@ private ConnectionProvider instantiateConnectionProvider(
149157
getSingleRegisteredProvider( strategySelector );
150158
if ( singleRegisteredProvider != null ) {
151159
try {
152-
return singleRegisteredProvider.newInstance();
160+
return singleRegisteredProvider.getConstructor().newInstance();
153161
}
154-
catch (IllegalAccessException | InstantiationException e) {
162+
catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException | InstantiationException e) {
155163
throw new HibernateException( "Could not instantiate singular-registered ConnectionProvider", e );
156164
}
157165
}
@@ -177,11 +185,47 @@ else if ( configurationValues.containsKey( URL ) ) {
177185
return new DriverManagerConnectionProviderImpl();
178186
}
179187
else {
180-
LOG.noAppropriateConnectionProvider();
181-
return new UserSuppliedConnectionProviderImpl();
188+
if (beanContainer != null) {
189+
return beanContainer.getBean(
190+
ConnectionProvider.class,
191+
new BeanContainer.LifecycleOptions() {
192+
@Override
193+
public boolean canUseCachedReferences() {
194+
return true;
195+
}
196+
197+
@Override
198+
public boolean useJpaCompliantCreation() {
199+
return true;
200+
}
201+
},
202+
new BeanInstanceProducer() {
203+
204+
@Override
205+
public <B> B produceBeanInstance(Class<B> beanType) {
206+
return (B) noAppropriateConnectionProvider();
207+
}
208+
209+
@Override
210+
public <B> B produceBeanInstance(String name, Class<B> beanType) {
211+
return (B) noAppropriateConnectionProvider();
212+
}
213+
214+
}
215+
).getBeanInstance();
216+
}
217+
else {
218+
return noAppropriateConnectionProvider();
219+
}
220+
182221
}
183222
}
184223

224+
private ConnectionProvider noAppropriateConnectionProvider() {
225+
LOG.noAppropriateConnectionProvider();
226+
return new UserSuppliedConnectionProviderImpl();
227+
}
228+
185229
private Class<? extends ConnectionProvider> getSingleRegisteredProvider(StrategySelector strategySelector) {
186230
final Collection<Class<? extends ConnectionProvider>> implementors =
187231
strategySelector.getRegisteredStrategyImplementors( ConnectionProvider.class );
@@ -190,9 +234,28 @@ private Class<? extends ConnectionProvider> getSingleRegisteredProvider(Strategy
190234
: null;
191235
}
192236

193-
private ConnectionProvider instantiateExplicitConnectionProvider(Class<?> providerClass) {
237+
private ConnectionProvider instantiateExplicitConnectionProvider(Class<?> providerClass, BeanContainer beanContainer) {
194238
try {
195-
return (ConnectionProvider) providerClass.newInstance();
239+
if ( beanContainer != null ) {
240+
return (ConnectionProvider) beanContainer.getBean(
241+
providerClass,
242+
new BeanContainer.LifecycleOptions() {
243+
@Override
244+
public boolean canUseCachedReferences() {
245+
return true;
246+
}
247+
248+
@Override
249+
public boolean useJpaCompliantCreation() {
250+
return true;
251+
}
252+
},
253+
FallbackBeanInstanceProducer.INSTANCE
254+
).getBeanInstance();
255+
}
256+
else {
257+
return (ConnectionProvider) providerClass.getConstructor().newInstance();
258+
}
196259
}
197260
catch (Exception e) {
198261
throw new HibernateException( "Could not instantiate connection provider [" + providerClass.getName() + "]", e );
@@ -201,7 +264,7 @@ private ConnectionProvider instantiateExplicitConnectionProvider(Class<?> provid
201264

202265
private static ConnectionProvider instantiateProvider(StrategySelector selector, String strategy) {
203266
try {
204-
return selector.selectStrategyImplementor( ConnectionProvider.class, strategy ).newInstance();
267+
return selector.selectStrategyImplementor( ConnectionProvider.class, strategy ).getConstructor().newInstance();
205268
}
206269
catch ( Exception e ) {
207270
LOG.providerClassNotFound(strategy);
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.connections;
6+
7+
import org.hibernate.cfg.AvailableSettings;
8+
import org.hibernate.dialect.H2Dialect;
9+
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
10+
import org.hibernate.resource.beans.container.spi.BeanContainer;
11+
import org.hibernate.resource.beans.container.spi.ContainedBean;
12+
import org.hibernate.resource.beans.spi.BeanInstanceProducer;
13+
import org.hibernate.service.ServiceRegistry;
14+
import org.hibernate.testing.junit4.BaseUnitTestCase;
15+
import org.hibernate.testing.orm.junit.RequiresDialect;
16+
import org.hibernate.testing.util.ServiceRegistryUtil;
17+
import org.junit.Test;
18+
19+
import java.sql.Connection;
20+
import java.sql.SQLException;
21+
import java.util.HashMap;
22+
import java.util.Map;
23+
24+
import static org.hibernate.cfg.JdbcSettings.CONNECTION_PROVIDER;
25+
import static org.junit.Assert.assertSame;
26+
27+
/**
28+
* @author Yanming Zhou
29+
*/
30+
@RequiresDialect(H2Dialect.class)
31+
public class ConnectionProviderFromBeanContainerTest extends BaseUnitTestCase {
32+
33+
private final ConnectionProvider dummyConnectionProvider = new DummyConnectionProvider();
34+
35+
private Map<String, Object> createSettings() {
36+
Map<String, Object> settings = new HashMap<>();
37+
settings.put( AvailableSettings.ALLOW_EXTENSIONS_IN_CDI, "true" );
38+
settings.put( AvailableSettings.BEAN_CONTAINER, new BeanContainer() {
39+
@Override
40+
@SuppressWarnings("unchecked")
41+
public <B> ContainedBean<B> getBean(
42+
Class<B> beanType,
43+
LifecycleOptions lifecycleOptions,
44+
BeanInstanceProducer fallbackProducer) {
45+
return () -> (B) ( beanType == DummyConnectionProvider.class ?
46+
dummyConnectionProvider : fallbackProducer.produceBeanInstance( beanType ) );
47+
}
48+
49+
@Override
50+
public <B> ContainedBean<B> getBean(
51+
String name,
52+
Class<B> beanType,
53+
LifecycleOptions lifecycleOptions,
54+
BeanInstanceProducer fallbackProducer) {
55+
return () -> (B) fallbackProducer.produceBeanInstance( beanType );
56+
}
57+
58+
@Override
59+
public void stop() {
60+
61+
}
62+
} );
63+
return settings;
64+
}
65+
66+
@Test
67+
public void testProviderFromBeanContainerInUse() {
68+
Map<String, Object> settings = createSettings();
69+
settings.putIfAbsent( CONNECTION_PROVIDER, DummyConnectionProvider.class.getName() );
70+
try ( ServiceRegistry serviceRegistry = ServiceRegistryUtil.serviceRegistryBuilder()
71+
.applySettings( settings ).build() ) {
72+
ConnectionProvider providerInUse = serviceRegistry.getService( ConnectionProvider.class );
73+
assertSame( dummyConnectionProvider, providerInUse );
74+
}
75+
}
76+
77+
public static class DummyConnectionProvider implements ConnectionProvider {
78+
79+
@Override
80+
public boolean isUnwrappableAs(Class<?> unwrapType) {
81+
return false;
82+
}
83+
84+
@Override
85+
public <T> T unwrap(Class<T> unwrapType) {
86+
return null;
87+
}
88+
89+
@Override
90+
public Connection getConnection() throws SQLException {
91+
return null;
92+
}
93+
94+
@Override
95+
public void closeConnection(Connection connection) throws SQLException {
96+
97+
}
98+
99+
@Override
100+
public boolean supportsAggressiveRelease() {
101+
return false;
102+
}
103+
};
104+
}

0 commit comments

Comments
 (0)