diff --git a/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/PluginBenchmarks.java b/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/PluginBenchmarks.java index 22148f312..35932705c 100644 --- a/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/PluginBenchmarks.java +++ b/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/PluginBenchmarks.java @@ -63,7 +63,6 @@ import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.monitoring.MonitorService; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.GaugeCallable; @@ -94,7 +93,6 @@ public class PluginBenchmarks { @Mock private StorageService mockStorageService; @Mock private MonitorService mockMonitorService; - @Mock private ConnectionService mockConnectionService; @Mock private PluginService mockPluginService; @Mock private TargetDriverDialect mockTargetDriverDialect; @Mock private Dialect mockDialect; @@ -183,8 +181,7 @@ private ConnectionWrapper getConnectionWrapper(Properties props, String connStri mockHostListProviderService, mockPluginManagerService, mockStorageService, - mockMonitorService, - mockConnectionService); + mockMonitorService); } @Benchmark diff --git a/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/testplugin/TestConnectionWrapper.java b/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/testplugin/TestConnectionWrapper.java index d0ec5c063..4323d1ae6 100644 --- a/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/testplugin/TestConnectionWrapper.java +++ b/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/testplugin/TestConnectionWrapper.java @@ -25,7 +25,6 @@ import software.amazon.jdbc.PluginManagerService; import software.amazon.jdbc.PluginService; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.monitoring.MonitorService; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -45,8 +44,7 @@ public TestConnectionWrapper( @NonNull final HostListProviderService hostListProviderService, @NonNull final PluginManagerService pluginManagerService, @NonNull final StorageService storageService, - @NonNull final MonitorService monitorService, - @NonNull final ConnectionService connectionService) + @NonNull final MonitorService monitorService) throws SQLException { super( props, @@ -58,6 +56,7 @@ public TestConnectionWrapper( pluginService, hostListProviderService, pluginManagerService, - storageService, monitorService, connectionService); + storageService, + monitorService); } } diff --git a/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingPostgresExample.java b/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingPostgresExample.java index 1a4b42cf7..c4a273dc9 100644 --- a/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingPostgresExample.java +++ b/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingPostgresExample.java @@ -23,8 +23,6 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; -import software.amazon.jdbc.ConnectionProviderManager; -import software.amazon.jdbc.HikariPooledConnectionProvider; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.PropertyDefinition; import software.amazon.jdbc.plugin.failover.FailoverFailedSQLException; diff --git a/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingSpringJdbcTemplateMySQLExample.java b/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingSpringJdbcTemplateMySQLExample.java index ead361b58..ea914e72e 100644 --- a/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingSpringJdbcTemplateMySQLExample.java +++ b/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingSpringJdbcTemplateMySQLExample.java @@ -16,7 +16,6 @@ package software.amazon; -import com.mysql.cj.jdbc.MysqlDataSource; import com.zaxxer.hikari.HikariDataSource; import java.sql.Connection; import java.sql.SQLException; diff --git a/examples/HikariExample/src/main/java/software/amazon/HikariExample.java b/examples/HikariExample/src/main/java/software/amazon/HikariExample.java index 9bbfa03c9..8f6607798 100644 --- a/examples/HikariExample/src/main/java/software/amazon/HikariExample.java +++ b/examples/HikariExample/src/main/java/software/amazon/HikariExample.java @@ -22,7 +22,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.util.Properties; public class HikariExample { diff --git a/examples/SpringHibernateBalancedReaderTwoDataSourceExample/src/main/java/example/spring/Config.java b/examples/SpringHibernateBalancedReaderTwoDataSourceExample/src/main/java/example/spring/Config.java index bc404df52..d6b30ffa8 100644 --- a/examples/SpringHibernateBalancedReaderTwoDataSourceExample/src/main/java/example/spring/Config.java +++ b/examples/SpringHibernateBalancedReaderTwoDataSourceExample/src/main/java/example/spring/Config.java @@ -16,10 +16,7 @@ package example.spring; -import com.zaxxer.hikari.HikariConfig; -import java.util.Arrays; import java.util.Properties; -import java.util.concurrent.TimeUnit; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import org.hibernate.exception.JDBCConnectionException; @@ -40,10 +37,6 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; -import software.amazon.jdbc.HikariPooledConnectionProvider; -import software.amazon.jdbc.HostSpec; -import software.amazon.jdbc.profile.ConfigurationProfileBuilder; -import software.amazon.jdbc.profile.ConfigurationProfilePresetCodes; @Configuration @EnableTransactionManagement diff --git a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginChainBuilder.java b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginChainBuilder.java index 411e40cd8..943e6397e 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginChainBuilder.java +++ b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginChainBuilder.java @@ -148,8 +148,7 @@ public List getPlugins( final ConnectionProvider effectiveConnProvider, final PluginManagerService pluginManagerService, final Properties props, - @Nullable ConfigurationProfile configurationProfile) - throws SQLException { + @Nullable ConfigurationProfile configurationProfile) throws SQLException { List plugins; List pluginFactories; diff --git a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginManager.java b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginManager.java index 8757e2c0a..4a4c7b20e 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginManager.java +++ b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginManager.java @@ -29,7 +29,6 @@ import java.util.logging.Logger; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.jetbrains.annotations.NotNull; import software.amazon.jdbc.cleanup.CanReleaseResources; import software.amazon.jdbc.plugin.AuroraConnectionTrackerPlugin; import software.amazon.jdbc.plugin.AuroraInitialConnectionStrategyPlugin; @@ -180,8 +179,7 @@ public void init( final FullServicesContainer servicesContainer, final Properties props, final PluginManagerService pluginManagerService, - @Nullable ConfigurationProfile configurationProfile) - throws SQLException { + @Nullable ConfigurationProfile configurationProfile) throws SQLException { this.props = props; this.servicesContainer = servicesContainer; diff --git a/wrapper/src/main/java/software/amazon/jdbc/Driver.java b/wrapper/src/main/java/software/amazon/jdbc/Driver.java index e4f5a14af..6d18d9af2 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/Driver.java +++ b/wrapper/src/main/java/software/amazon/jdbc/Driver.java @@ -239,8 +239,8 @@ public Connection connect(final String url, final Properties info) throws SQLExc effectiveConnectionProvider = configurationProfile.getConnectionProvider(); } - FullServicesContainer - servicesContainer = new FullServicesContainerImpl(storageService, monitorService, telemetryFactory); + FullServicesContainer servicesContainer = + new FullServicesContainerImpl(storageService, monitorService, defaultConnectionProvider, telemetryFactory); return new ConnectionWrapper( servicesContainer, diff --git a/wrapper/src/main/java/software/amazon/jdbc/HostSpecBuilder.java b/wrapper/src/main/java/software/amazon/jdbc/HostSpecBuilder.java index a84920637..ec6abdbee 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/HostSpecBuilder.java +++ b/wrapper/src/main/java/software/amazon/jdbc/HostSpecBuilder.java @@ -17,7 +17,6 @@ package software.amazon.jdbc; import java.sql.Timestamp; -import java.time.Instant; import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.hostavailability.HostAvailabilityStrategy; diff --git a/wrapper/src/main/java/software/amazon/jdbc/PartialPluginService.java b/wrapper/src/main/java/software/amazon/jdbc/PartialPluginService.java index 36a0dc0b1..df034895d 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/PartialPluginService.java +++ b/wrapper/src/main/java/software/amazon/jdbc/PartialPluginService.java @@ -510,8 +510,7 @@ public Connection forceConnect( final HostSpec hostSpec, final Properties props) throws SQLException { - throw new UnsupportedOperationException( - Messages.get("PartialPluginService.unexpectedMethodCall", new Object[] {"forceConnect"})); + return this.forceConnect(hostSpec, props, null); } @Override @@ -520,8 +519,8 @@ public Connection forceConnect( final Properties props, final @Nullable ConnectionPlugin pluginToSkip) throws SQLException { - throw new UnsupportedOperationException( - Messages.get("PartialPluginService.unexpectedMethodCall", new Object[] {"forceConnect"})); + return this.pluginManager.forceConnect( + this.driverProtocol, hostSpec, props, true, pluginToSkip); } private void updateHostAvailability(final List hosts) { diff --git a/wrapper/src/main/java/software/amazon/jdbc/authentication/AwsCredentialsManager.java b/wrapper/src/main/java/software/amazon/jdbc/authentication/AwsCredentialsManager.java index eb463a7aa..c562dd48e 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/authentication/AwsCredentialsManager.java +++ b/wrapper/src/main/java/software/amazon/jdbc/authentication/AwsCredentialsManager.java @@ -23,7 +23,6 @@ import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.PropertyDefinition; -import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.StringUtils; public class AwsCredentialsManager { diff --git a/wrapper/src/main/java/software/amazon/jdbc/ds/AwsWrapperDataSource.java b/wrapper/src/main/java/software/amazon/jdbc/ds/AwsWrapperDataSource.java index 0c54e018e..440a8870b 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/ds/AwsWrapperDataSource.java +++ b/wrapper/src/main/java/software/amazon/jdbc/ds/AwsWrapperDataSource.java @@ -281,8 +281,8 @@ ConnectionWrapper createConnectionWrapper( final @NonNull TargetDriverDialect targetDriverDialect, final @Nullable ConfigurationProfile configurationProfile, final TelemetryFactory telemetryFactory) throws SQLException { - FullServicesContainer - servicesContainer = new FullServicesContainerImpl(storageService, monitorService, telemetryFactory); + FullServicesContainer servicesContainer = + new FullServicesContainerImpl(storageService, monitorService, defaultProvider, telemetryFactory); return new ConnectionWrapper( servicesContainer, props, diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostavailability/HostAvailabilityStrategy.java b/wrapper/src/main/java/software/amazon/jdbc/hostavailability/HostAvailabilityStrategy.java index 659fdae2b..9f04b54c6 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostavailability/HostAvailabilityStrategy.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostavailability/HostAvailabilityStrategy.java @@ -16,8 +16,6 @@ package software.amazon.jdbc.hostavailability; -import software.amazon.jdbc.AwsWrapperProperty; - public interface HostAvailabilityStrategy { void setHostAvailability(HostAvailability hostAvailability); diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/ClusterTopologyMonitorImpl.java b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/ClusterTopologyMonitorImpl.java index 4e7b62de1..18d766146 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/ClusterTopologyMonitorImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/ClusterTopologyMonitorImpl.java @@ -42,22 +42,21 @@ import java.util.stream.Collectors; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import software.amazon.jdbc.HostListProviderService; import software.amazon.jdbc.HostRole; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.PropertyDefinition; import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.hostlistprovider.Topology; import software.amazon.jdbc.util.ExecutorFactory; +import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; import software.amazon.jdbc.util.RdsUtils; +import software.amazon.jdbc.util.ServiceUtility; import software.amazon.jdbc.util.StringUtils; import software.amazon.jdbc.util.SynchronousExecutor; import software.amazon.jdbc.util.Utils; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.monitoring.AbstractMonitor; -import software.amazon.jdbc.util.storage.StorageService; public class ClusterTopologyMonitorImpl extends AbstractMonitor implements ClusterTopologyMonitor { @@ -80,15 +79,13 @@ public class ClusterTopologyMonitorImpl extends AbstractMonitor implements Clust protected final long refreshRateNano; protected final long highRefreshRateNano; + protected final FullServicesContainer servicesContainer; protected final Properties properties; protected final Properties monitoringProperties; protected final HostSpec initialHostSpec; - protected final StorageService storageService; - protected final ConnectionService connectionService; protected final String topologyQuery; protected final String nodeIdQuery; protected final String writerTopologyQuery; - protected final HostListProviderService hostListProviderService; protected final HostSpec clusterInstanceTemplate; protected String clusterId; @@ -109,12 +106,10 @@ public class ClusterTopologyMonitorImpl extends AbstractMonitor implements Clust protected final AtomicReference> nodeThreadsLatestTopology = new AtomicReference<>(null); public ClusterTopologyMonitorImpl( + final FullServicesContainer servicesContainer, final String clusterId, - final StorageService storageService, - final ConnectionService connectionService, final HostSpec initialHostSpec, final Properties properties, - final HostListProviderService hostListProviderService, final HostSpec clusterInstanceTemplate, final long refreshRateNano, final long highRefreshRateNano, @@ -124,9 +119,7 @@ public ClusterTopologyMonitorImpl( super(monitorTerminationTimeoutSec); this.clusterId = clusterId; - this.storageService = storageService; - this.connectionService = connectionService; - this.hostListProviderService = hostListProviderService; + this.servicesContainer = servicesContainer; this.initialHostSpec = initialHostSpec; this.clusterInstanceTemplate = clusterInstanceTemplate; this.properties = properties; @@ -251,7 +244,7 @@ protected List waitTillTopologyGetsUpdated(final long timeoutMs) throw } private List getStoredHosts() { - Topology topology = storageService.get(Topology.class, this.clusterId); + Topology topology = this.servicesContainer.getStorageService().get(Topology.class, this.clusterId); return topology == null ? null : topology.getHosts(); } @@ -277,7 +270,7 @@ public void close() { } @Override - public void monitor() { + public void monitor() throws Exception { try { LOGGER.finest(() -> Messages.get( "ClusterTopologyMonitorImpl.startMonitoringThread", @@ -309,15 +302,27 @@ public void monitor() { if (hosts != null && !this.isVerifiedWriterConnection) { for (HostSpec hostSpec : hosts) { + // A list is used to store the exception since lambdas require references to outer variables to be + // final. This allows us to identify if an error occurred while creating the node monitoring worker. + final List exceptionList = new ArrayList<>(); this.submittedNodes.computeIfAbsent(hostSpec.getHost(), (key) -> { final ExecutorService nodeExecutorServiceCopy = this.nodeExecutorService; if (nodeExecutorServiceCopy != null) { - this.nodeExecutorService.submit( - this.getNodeMonitoringWorker(hostSpec, this.writerHostSpec.get())); + try { + this.nodeExecutorService.submit( + this.getNodeMonitoringWorker(hostSpec, this.writerHostSpec.get())); + } catch (SQLException e) { + exceptionList.add(e); + return null; + } } return true; }); + + if (!exceptionList.isEmpty()) { + throw exceptionList.get(0); + } } // It's not possible to call shutdown() on this.nodeExecutorService since more node may be added later. } @@ -358,12 +363,25 @@ public void monitor() { List hosts = this.nodeThreadsLatestTopology.get(); if (hosts != null && !this.nodeThreadsStop.get()) { for (HostSpec hostSpec : hosts) { + // A list is used to store the exception since lambdas require references to outer variables to be + // final. This allows us to identify if an error occurred while creating the node monitoring worker. + final List exceptionList = new ArrayList<>(); this.submittedNodes.computeIfAbsent(hostSpec.getHost(), (key) -> { - this.nodeExecutorService.submit( - this.getNodeMonitoringWorker(hostSpec, this.writerHostSpec.get())); + try { + this.nodeExecutorService.submit( + this.getNodeMonitoringWorker(hostSpec, this.writerHostSpec.get())); + } catch (SQLException e) { + exceptionList.add(e); + return null; + } + return true; }); + + if (!exceptionList.isEmpty()) { + throw exceptionList.get(0); + } } // It's not possible to call shutdown() on this.nodeExecutorService since more node may be added later. } @@ -423,6 +441,7 @@ public void monitor() { ex); } + throw ex; } finally { this.stop.set(true); this.shutdownNodeExecutorService(); @@ -480,8 +499,11 @@ protected boolean isInPanicMode() { || !this.isVerifiedWriterConnection; } - protected Runnable getNodeMonitoringWorker(final HostSpec hostSpec, final @Nullable HostSpec writerHostSpec) { - return new NodeMonitoringWorker(this, hostSpec, writerHostSpec); + protected Runnable getNodeMonitoringWorker( + final HostSpec hostSpec, final @Nullable HostSpec writerHostSpec) throws SQLException { + FullServicesContainer newServiceContainer = + ServiceUtility.getInstance().createServiceContainer(this.servicesContainer, this.properties); + return new NodeMonitoringWorker(newServiceContainer, this, hostSpec, writerHostSpec); } protected List openAnyConnectionAndUpdateTopology() { @@ -492,7 +514,7 @@ protected List openAnyConnectionAndUpdateTopology() { // open a new connection try { - conn = this.connectionService.open(this.initialHostSpec, this.monitoringProperties); + conn = this.servicesContainer.getPluginService().forceConnect(this.initialHostSpec, this.monitoringProperties); } catch (SQLException ex) { // can't connect return null; @@ -625,7 +647,7 @@ protected void delay(boolean useHighRefreshRate) throws InterruptedException { protected void updateTopologyCache(final @NonNull List hosts) { synchronized (this.requestToUpdateTopology) { - storageService.set(this.clusterId, new Topology(hosts)); + this.servicesContainer.getStorageService().set(this.clusterId, new Topology(hosts)); synchronized (this.topologyUpdated) { this.requestToUpdateTopology.set(false); @@ -769,7 +791,7 @@ protected HostSpec createHost( ? this.clusterInstanceTemplate.getPort() : this.initialHostSpec.getPort(); - final HostSpec hostSpec = this.hostListProviderService.getHostSpecBuilder() + final HostSpec hostSpec = this.servicesContainer.getHostListProviderService().getHostSpecBuilder() .host(endpoint) .port(port) .role(isWriter ? HostRole.WRITER : HostRole.READER) @@ -791,16 +813,19 @@ private static class NodeMonitoringWorker implements Runnable { private static final Logger LOGGER = Logger.getLogger(NodeMonitoringWorker.class.getName()); + protected final FullServicesContainer servicesContainer; protected final ClusterTopologyMonitorImpl monitor; protected final HostSpec hostSpec; protected final @Nullable HostSpec writerHostSpec; protected boolean writerChanged = false; public NodeMonitoringWorker( + final FullServicesContainer servicesContainer, final ClusterTopologyMonitorImpl monitor, final HostSpec hostSpec, final @Nullable HostSpec writerHostSpec ) { + this.servicesContainer = servicesContainer; this.monitor = monitor; this.hostSpec = hostSpec; this.writerHostSpec = writerHostSpec; @@ -818,7 +843,7 @@ public void run() { if (connection == null) { try { - connection = this.monitor.connectionService.open( + connection = this.servicesContainer.getPluginService().forceConnect( hostSpec, this.monitor.monitoringProperties); } catch (SQLException ex) { // A problem occurred while connecting. We will try again on the next iteration. diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsHostListProvider.java b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsHostListProvider.java index df1c140a6..5fd965006 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsHostListProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsHostListProvider.java @@ -32,7 +32,6 @@ import software.amazon.jdbc.hostlistprovider.RdsHostListProvider; import software.amazon.jdbc.hostlistprovider.Topology; import software.amazon.jdbc.util.FullServicesContainer; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.monitoring.MonitorService; import software.amazon.jdbc.util.storage.StorageService; @@ -86,20 +85,18 @@ protected ClusterTopologyMonitor initMonitor() throws SQLException { ClusterTopologyMonitorImpl.class, this.clusterId, this.servicesContainer.getStorageService(), - this.pluginService.getTelemetryFactory(), - this.pluginService.getDefaultConnectionProvider(), + this.servicesContainer.getTelemetryFactory(), + this.servicesContainer.getDefaultConnectionProvider(), this.originalUrl, this.pluginService.getDriverProtocol(), this.pluginService.getTargetDriverDialect(), this.pluginService.getDialect(), this.properties, - (ConnectionService connectionService, PluginService monitorPluginService) -> new ClusterTopologyMonitorImpl( + (servicesContainer) -> new ClusterTopologyMonitorImpl( + this.servicesContainer, this.clusterId, - this.servicesContainer.getStorageService(), - connectionService, this.initialHostSpec, this.properties, - this.servicesContainer.getHostListProviderService(), this.clusterInstanceTemplate, this.refreshRateNano, this.highRefreshRateNano, @@ -133,14 +130,14 @@ protected void clusterIdChanged(final String oldClusterId) throws SQLException { ClusterTopologyMonitorImpl.class, this.clusterId, this.servicesContainer.getStorageService(), - this.pluginService.getTelemetryFactory(), - this.pluginService.getDefaultConnectionProvider(), + this.servicesContainer.getTelemetryFactory(), + this.servicesContainer.getDefaultConnectionProvider(), this.originalUrl, this.pluginService.getDriverProtocol(), this.pluginService.getTargetDriverDialect(), this.pluginService.getDialect(), this.properties, - (connectionService, pluginService) -> existingMonitor); + (servicesContainer) -> existingMonitor); assert monitorService.get(ClusterTopologyMonitorImpl.class, this.clusterId) == existingMonitor; existingMonitor.setClusterId(this.clusterId); monitorService.remove(ClusterTopologyMonitorImpl.class, oldClusterId); diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsMultiAzHostListProvider.java b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsMultiAzHostListProvider.java index ab1eb9b23..730d15e7a 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsMultiAzHostListProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsMultiAzHostListProvider.java @@ -54,17 +54,16 @@ protected ClusterTopologyMonitor initMonitor() throws SQLException { return this.servicesContainer.getMonitorService().runIfAbsent(MultiAzClusterTopologyMonitorImpl.class, this.clusterId, this.servicesContainer.getStorageService(), - this.pluginService.getTelemetryFactory(), - this.pluginService.getDefaultConnectionProvider(), + this.servicesContainer.getTelemetryFactory(), + this.servicesContainer.getDefaultConnectionProvider(), this.originalUrl, this.pluginService.getDriverProtocol(), this.pluginService.getTargetDriverDialect(), this.pluginService.getDialect(), this.properties, - (connectionService, pluginService) -> new MultiAzClusterTopologyMonitorImpl( + (servicesContainer) -> new MultiAzClusterTopologyMonitorImpl( + servicesContainer, this.clusterId, - this.servicesContainer.getStorageService(), - connectionService, this.initialHostSpec, this.properties, this.hostListProviderService, diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MultiAzClusterTopologyMonitorImpl.java b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MultiAzClusterTopologyMonitorImpl.java index 6e3c3b388..36bab8f90 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MultiAzClusterTopologyMonitorImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MultiAzClusterTopologyMonitorImpl.java @@ -26,9 +26,8 @@ import java.util.logging.Logger; import software.amazon.jdbc.HostListProviderService; import software.amazon.jdbc.HostSpec; +import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.StringUtils; -import software.amazon.jdbc.util.connection.ConnectionService; -import software.amazon.jdbc.util.storage.StorageService; public class MultiAzClusterTopologyMonitorImpl extends ClusterTopologyMonitorImpl { @@ -38,9 +37,8 @@ public class MultiAzClusterTopologyMonitorImpl extends ClusterTopologyMonitorImp protected final String fetchWriterNodeColumnName; public MultiAzClusterTopologyMonitorImpl( + final FullServicesContainer servicesContainer, final String clusterId, - final StorageService storageService, - final ConnectionService connectionService, final HostSpec initialHostSpec, final Properties properties, final HostListProviderService hostListProviderService, @@ -53,12 +51,10 @@ public MultiAzClusterTopologyMonitorImpl( final String fetchWriterNodeQuery, final String fetchWriterNodeColumnName) { super( + servicesContainer, clusterId, - storageService, - connectionService, initialHostSpec, properties, - hostListProviderService, clusterInstanceTemplate, refreshRateNano, highRefreshRateNano, diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/customendpoint/CustomEndpointPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/customendpoint/CustomEndpointPlugin.java index 22b385923..5a272e922 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/customendpoint/CustomEndpointPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/customendpoint/CustomEndpointPlugin.java @@ -223,9 +223,9 @@ protected CustomEndpointMonitor createMonitorIfAbsent(Properties props) throws S this.pluginService.getTargetDriverDialect(), this.pluginService.getDialect(), this.props, - (connectionService, pluginService) -> new CustomEndpointMonitorImpl( - this.servicesContainer.getStorageService(), - this.servicesContainer.getTelemetryFactory(), + (servicesContainer) -> new CustomEndpointMonitorImpl( + servicesContainer.getStorageService(), + servicesContainer.getTelemetryFactory(), this.customEndpointHostSpec, this.customEndpointId, this.region, diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorImpl.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorImpl.java index 5a858b856..7f13420b8 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorImpl.java @@ -33,9 +33,9 @@ import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.util.ExecutorFactory; +import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.monitoring.AbstractMonitor; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryCounter; @@ -59,7 +59,7 @@ public class HostMonitorImpl extends AbstractMonitor implements HostMonitor { private final Queue> activeContexts = new ConcurrentLinkedQueue<>(); private final Map>> newContexts = new ConcurrentHashMap<>(); - private final ConnectionService connectionService; + private final FullServicesContainer servicesContainer; private final TelemetryFactory telemetryFactory; private final Properties properties; private final HostSpec hostSpec; @@ -78,8 +78,7 @@ public class HostMonitorImpl extends AbstractMonitor implements HostMonitor { /** * Store the monitoring configuration for a connection. * - * @param connectionService The service to use to create the monitoring connection. - * @param telemetryFactory The telemetry factory to use to create telemetry data. + * @param servicesContainer The telemetry factory to use to create telemetry data. * @param hostSpec The {@link HostSpec} of the server this {@link HostMonitorImpl} * instance is monitoring. * @param properties The {@link Properties} containing additional monitoring @@ -90,8 +89,7 @@ public class HostMonitorImpl extends AbstractMonitor implements HostMonitor { * @param abortedConnectionsCounter Aborted connection telemetry counter. */ public HostMonitorImpl( - final @NonNull ConnectionService connectionService, - final @NonNull TelemetryFactory telemetryFactory, + final @NonNull FullServicesContainer servicesContainer, final @NonNull HostSpec hostSpec, final @NonNull Properties properties, final int failureDetectionTimeMillis, @@ -99,9 +97,8 @@ public HostMonitorImpl( final int failureDetectionCount, final TelemetryCounter abortedConnectionsCounter) { super(TERMINATION_TIMEOUT_SEC, ExecutorFactory.newFixedThreadPool(2, "efm2-monitor")); - - this.connectionService = connectionService; - this.telemetryFactory = telemetryFactory; + this.servicesContainer = servicesContainer; + this.telemetryFactory = servicesContainer.getTelemetryFactory(); this.hostSpec = hostSpec; this.properties = properties; this.failureDetectionTimeNano = TimeUnit.MILLISECONDS.toNanos(failureDetectionTimeMillis); @@ -317,7 +314,8 @@ boolean checkConnectionStatus() { }); LOGGER.finest(() -> "Opening a monitoring connection to " + this.hostSpec.getUrl()); - this.monitoringConn = this.connectionService.open(this.hostSpec, monitoringConnProperties); + this.monitoringConn = + this.servicesContainer.getPluginService().forceConnect(this.hostSpec, monitoringConnProperties); LOGGER.finest(() -> "Opened monitoring connection: " + this.monitoringConn); return true; } diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorServiceImpl.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorServiceImpl.java index a0ca9f14f..e0853e2d9 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorServiceImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorServiceImpl.java @@ -161,9 +161,8 @@ protected HostMonitor getMonitor( this.pluginService.getTargetDriverDialect(), this.pluginService.getDialect(), this.pluginService.getProperties(), - (connectionService, pluginService) -> new HostMonitorImpl( - connectionService, - pluginService.getTelemetryFactory(), + (servicesContainer) -> new HostMonitorImpl( + servicesContainer, hostSpec, properties, failureDetectionTimeMillis, diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandler.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandler.java index 7cb4f7b5a..e2776c146 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandler.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandler.java @@ -33,19 +33,16 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.logging.Logger; -import software.amazon.jdbc.ConnectionPluginManager; import software.amazon.jdbc.HostRole; import software.amazon.jdbc.HostSpec; -import software.amazon.jdbc.PartialPluginService; import software.amazon.jdbc.PluginService; import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.util.ExecutorFactory; import software.amazon.jdbc.util.FullServicesContainer; -import software.amazon.jdbc.util.FullServicesContainerImpl; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; +import software.amazon.jdbc.util.ServiceUtility; import software.amazon.jdbc.util.Utils; -import software.amazon.jdbc.util.connection.ConnectionService; /** * An implementation of ReaderFailoverHandler. @@ -67,7 +64,6 @@ public class ClusterAwareReaderFailoverHandler implements ReaderFailoverHandler protected static final int DEFAULT_READER_CONNECT_TIMEOUT = 30000; // 30 sec protected final Map hostAvailabilityMap = new ConcurrentHashMap<>(); protected final FullServicesContainer servicesContainer; - protected final ConnectionService connectionService; protected final PluginService pluginService; protected Properties props; protected int maxFailoverTimeoutMs; @@ -78,16 +74,13 @@ public class ClusterAwareReaderFailoverHandler implements ReaderFailoverHandler * ClusterAwareReaderFailoverHandler constructor. * * @param servicesContainer the service container for the services required by this class. - * @param connectionService the service to use to create new connections during failover. * @param props the initial connection properties to copy over to the new reader. */ public ClusterAwareReaderFailoverHandler( final FullServicesContainer servicesContainer, - final ConnectionService connectionService, final Properties props) { this( servicesContainer, - connectionService, props, DEFAULT_FAILOVER_TIMEOUT, DEFAULT_READER_CONNECT_TIMEOUT, @@ -98,7 +91,6 @@ public ClusterAwareReaderFailoverHandler( * ClusterAwareReaderFailoverHandler constructor. * * @param servicesContainer the service container for the services required by this class. - * @param connectionService the service to use to create new connections during failover. * @param props the initial connection properties to copy over to the new reader. * @param maxFailoverTimeoutMs maximum allowed time for the entire reader failover process. * @param timeoutMs maximum allowed time in milliseconds for each reader connection attempt during @@ -107,13 +99,11 @@ public ClusterAwareReaderFailoverHandler( */ public ClusterAwareReaderFailoverHandler( final FullServicesContainer servicesContainer, - final ConnectionService connectionService, final Properties props, final int maxFailoverTimeoutMs, final int timeoutMs, final boolean isStrictReaderRequired) { this.servicesContainer = servicesContainer; - this.connectionService = connectionService; this.pluginService = servicesContainer.getPluginService(); this.props = props; this.maxFailoverTimeoutMs = maxFailoverTimeoutMs; @@ -307,11 +297,14 @@ private ReaderFailoverResult getConnectionFromHostGroup(final List hos final ExecutorService executor = ExecutorFactory.newFixedThreadPool(2, "failover"); final CompletionService completionService = new ExecutorCompletionService<>(executor); + final FullServicesContainer servicesContainer1 = newServicesContainer(); + final FullServicesContainer servicesContainer2 = newServicesContainer(); + try { for (int i = 0; i < hosts.size(); i += 2) { // submit connection attempt tasks in batches of 2 final ReaderFailoverResult result = - getResultFromNextTaskBatch(hosts, executor, completionService, i); + getResultFromNextTaskBatch(hosts, executor, completionService, servicesContainer1, servicesContainer2, i); if (result.isConnected() || result.getException() != null) { return result; } @@ -330,17 +323,22 @@ private ReaderFailoverResult getConnectionFromHostGroup(final List hos } } + protected FullServicesContainer newServicesContainer() throws SQLException { + return ServiceUtility.getInstance().createServiceContainer(this.servicesContainer, this.props); + } + private ReaderFailoverResult getResultFromNextTaskBatch( final List hosts, final ExecutorService executor, final CompletionService completionService, + final FullServicesContainer servicesContainer1, + final FullServicesContainer servicesContainer2, final int i) throws SQLException { ReaderFailoverResult result; final int numTasks = i + 1 < hosts.size() ? 2 : 1; completionService.submit( new ConnectionAttemptTask( - this.connectionService, - getNewPluginService(), + servicesContainer1, this.hostAvailabilityMap, hosts.get(i), this.props, @@ -348,8 +346,7 @@ private ReaderFailoverResult getResultFromNextTaskBatch( if (numTasks == 2) { completionService.submit( new ConnectionAttemptTask( - this.connectionService, - getNewPluginService(), + servicesContainer2, this.hostAvailabilityMap, hosts.get(i + 1), this.props, @@ -392,33 +389,7 @@ private ReaderFailoverResult getNextResult(final CompletionService { - private final ConnectionService connectionService; private final PluginService pluginService; private final Map availabilityMap; private final HostSpec newHost; @@ -426,14 +397,12 @@ private static class ConnectionAttemptTask implements Callable availabilityMap, final HostSpec newHost, final Properties props, final boolean isStrictReaderRequired) { - this.connectionService = connectionService; - this.pluginService = pluginService; + this.pluginService = servicesContainer.getPluginService(); this.availabilityMap = availabilityMap; this.newHost = newHost; this.props = props; @@ -454,7 +423,7 @@ public ReaderFailoverResult call() { final Properties copy = new Properties(); copy.putAll(props); - final Connection conn = this.connectionService.open(this.newHost, copy); + final Connection conn = this.pluginService.forceConnect(this.newHost, copy); this.availabilityMap.put(this.newHost.getHost(), HostAvailability.AVAILABLE); if (this.isStrictReaderRequired) { diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandler.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandler.java index b01f249a2..d8fde43ee 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandler.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandler.java @@ -32,18 +32,15 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; -import software.amazon.jdbc.ConnectionPluginManager; import software.amazon.jdbc.HostSpec; -import software.amazon.jdbc.PartialPluginService; import software.amazon.jdbc.PluginService; import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.util.ExecutorFactory; import software.amazon.jdbc.util.FullServicesContainer; -import software.amazon.jdbc.util.FullServicesContainerImpl; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; +import software.amazon.jdbc.util.ServiceUtility; import software.amazon.jdbc.util.Utils; -import software.amazon.jdbc.util.connection.ConnectionService; /** * An implementation of WriterFailoverHandler. @@ -60,7 +57,6 @@ public class ClusterAwareWriterFailoverHandler implements WriterFailoverHandler protected final Properties initialConnectionProps; protected final FullServicesContainer servicesContainer; - protected final ConnectionService connectionService; protected final PluginService pluginService; protected final ReaderFailoverHandler readerFailoverHandler; protected final Map hostAvailabilityMap = new ConcurrentHashMap<>(); @@ -70,11 +66,9 @@ public class ClusterAwareWriterFailoverHandler implements WriterFailoverHandler public ClusterAwareWriterFailoverHandler( final FullServicesContainer servicesContainer, - final ConnectionService connectionService, final ReaderFailoverHandler readerFailoverHandler, final Properties initialConnectionProps) { this.servicesContainer = servicesContainer; - this.connectionService = connectionService; this.pluginService = servicesContainer.getPluginService(); this.readerFailoverHandler = readerFailoverHandler; this.initialConnectionProps = initialConnectionProps; @@ -82,7 +76,6 @@ public ClusterAwareWriterFailoverHandler( public ClusterAwareWriterFailoverHandler( final FullServicesContainer servicesContainer, - final ConnectionService connectionService, final ReaderFailoverHandler readerFailoverHandler, final Properties initialConnectionProps, final int failoverTimeoutMs, @@ -90,7 +83,6 @@ public ClusterAwareWriterFailoverHandler( final int reconnectWriterIntervalMs) { this( servicesContainer, - connectionService, readerFailoverHandler, initialConnectionProps); this.maxFailoverTimeoutMs = failoverTimeoutMs; @@ -104,8 +96,7 @@ public Map getHostAvailabilityMap() { } @Override - public WriterFailoverResult failover(final List currentTopology) - throws SQLException { + public WriterFailoverResult failover(final List currentTopology) throws SQLException { if (Utils.isNullOrEmpty(currentTopology)) { LOGGER.severe(() -> Messages.get("ClusterAwareWriterFailoverHandler.failoverCalledWithInvalidTopology")); return DEFAULT_RESULT; @@ -152,11 +143,12 @@ private void submitTasks( final CompletionService completionService, final boolean singleTask) throws SQLException { final HostSpec writerHost = Utils.getWriter(currentTopology); + // Each task should get its own service container since they execute concurrently and PluginService was not + // designed to be thread-safe if (!singleTask) { completionService.submit( new ReconnectToWriterHandler( - this.connectionService, - this.getNewPluginService(), + newServicesContainer(), this.hostAvailabilityMap, writerHost, this.initialConnectionProps, @@ -165,8 +157,7 @@ private void submitTasks( completionService.submit( new WaitForNewWriterHandler( - this.connectionService, - this.getNewPluginService(), + newServicesContainer(), this.hostAvailabilityMap, this.readerFailoverHandler, writerHost, @@ -177,29 +168,8 @@ private void submitTasks( executorService.shutdown(); } - // Each task should get its own PluginService since they execute concurrently and PluginService was not designed to - // be thread-safe. - protected PluginService getNewPluginService() throws SQLException { - FullServicesContainer newServicesContainer = new FullServicesContainerImpl( - this.servicesContainer.getStorageService(), - this.servicesContainer.getMonitorService(), - this.servicesContainer.getTelemetryFactory() - ); - - ConnectionPluginManager pluginManager = new ConnectionPluginManager( - this.pluginService.getDefaultConnectionProvider(), null, null, servicesContainer.getTelemetryFactory()); - newServicesContainer.setConnectionPluginManager(pluginManager); - PartialPluginService pluginService = new PartialPluginService( - newServicesContainer, - this.initialConnectionProps, - this.pluginService.getOriginalUrl(), - this.pluginService.getDriverProtocol(), - this.pluginService.getTargetDriverDialect(), - this.pluginService.getDialect() - ); - - pluginManager.init(newServicesContainer, this.initialConnectionProps, pluginService, null); - return pluginService; + protected FullServicesContainer newServicesContainer() throws SQLException { + return ServiceUtility.getInstance().createServiceContainer(this.servicesContainer, this.initialConnectionProps); } private WriterFailoverResult getNextResult( @@ -275,8 +245,6 @@ private SQLException createInterruptedException(final InterruptedException e) { * Internal class responsible for re-connecting to the current writer (aka TaskA). */ private static class ReconnectToWriterHandler implements Callable { - - private final ConnectionService connectionService; private final PluginService pluginService; private final Map availabilityMap; private final HostSpec originalWriterHost; @@ -284,14 +252,12 @@ private static class ReconnectToWriterHandler implements Callable availabilityMap, final HostSpec originalWriterHost, final Properties props, final int reconnectWriterIntervalMs) { - this.connectionService = connectionService; - this.pluginService = pluginService; + this.pluginService = servicesContainer.getPluginService(); this.availabilityMap = availabilityMap; this.originalWriterHost = originalWriterHost; this.props = props; @@ -315,7 +281,7 @@ public WriterFailoverResult call() { conn.close(); } - conn = this.connectionService.open(this.originalWriterHost, this.props); + conn = this.pluginService.forceConnect(this.originalWriterHost, this.props); this.pluginService.forceRefreshHostList(conn); latestTopology = this.pluginService.getAllHosts(); } catch (final SQLException exception) { @@ -358,6 +324,10 @@ public WriterFailoverResult call() { private boolean isCurrentHostWriter(final List latestTopology) { final HostSpec latestWriter = Utils.getWriter(latestTopology); + if (latestWriter == null) { + return false; + } + final Set latestWriterAllAliases = latestWriter.asAliases(); final Set currentAliases = this.originalWriterHost.asAliases(); @@ -371,8 +341,6 @@ private boolean isCurrentHostWriter(final List latestTopology) { * elected writer (aka TaskB). */ private static class WaitForNewWriterHandler implements Callable { - - private final ConnectionService connectionService; private final PluginService pluginService; private final Map availabilityMap; private final ReaderFailoverHandler readerFailoverHandler; @@ -385,16 +353,14 @@ private static class WaitForNewWriterHandler implements Callable availabilityMap, final ReaderFailoverHandler readerFailoverHandler, final HostSpec originalWriterHost, final Properties props, final int readTopologyIntervalMs, final List currentTopology) { - this.connectionService = connectionService; - this.pluginService = pluginService; + this.pluginService = servicesContainer.getPluginService(); this.availabilityMap = availabilityMap; this.readerFailoverHandler = readerFailoverHandler; this.originalWriterHost = originalWriterHost; @@ -537,7 +503,7 @@ private boolean connectToWriter(final HostSpec writerCandidate) { new Object[] {writerCandidate.getUrl()})); try { // connect to the new writer - this.currentConnection = this.connectionService.open(writerCandidate, this.props); + this.currentConnection = this.pluginService.forceConnect(writerCandidate, this.props); this.availabilityMap.put(writerCandidate.getHost(), HostAvailability.AVAILABLE); return true; } catch (final SQLException exception) { diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPlugin.java index c9d90e764..ef2f95550 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPlugin.java @@ -28,7 +28,7 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Function; +import java.util.function.Supplier; import java.util.logging.Level; import java.util.logging.Logger; import org.checkerframework.checker.nullness.qual.Nullable; @@ -53,8 +53,6 @@ import software.amazon.jdbc.util.SqlState; import software.amazon.jdbc.util.Utils; import software.amazon.jdbc.util.WrapperUtils; -import software.amazon.jdbc.util.connection.ConnectionService; -import software.amazon.jdbc.util.connection.ConnectionServiceImpl; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -96,7 +94,6 @@ public class FailoverConnectionPlugin extends AbstractConnectionPlugin { private final Set subscribedMethods; private final PluginService pluginService; private final FullServicesContainer servicesContainer; - private ConnectionService connectionService; protected final Properties properties; protected boolean enableFailoverSetting; protected boolean enableConnectFailover; @@ -119,8 +116,8 @@ public class FailoverConnectionPlugin extends AbstractConnectionPlugin { private RdsUrlType rdsUrlType = null; private HostListProviderService hostListProviderService; private final AuroraStaleDnsHelper staleDnsHelper; - private Function writerFailoverHandlerSupplier; - private Function readerFailoverHandlerSupplier; + private Supplier writerFailoverHandlerSupplier; + private Supplier readerFailoverHandlerSupplier; public static final AwsWrapperProperty FAILOVER_CLUSTER_TOPOLOGY_REFRESH_RATE_MS = new AwsWrapperProperty( @@ -313,18 +310,16 @@ public void initHostProvider( initHostProvider( hostListProviderService, initHostProviderFunc, - (connectionService) -> + () -> new ClusterAwareReaderFailoverHandler( this.servicesContainer, - connectionService, this.properties, this.failoverTimeoutMsSetting, this.failoverReaderConnectTimeoutMsSetting, this.failoverMode == FailoverMode.STRICT_READER), - (connectionService) -> + () -> new ClusterAwareWriterFailoverHandler( this.servicesContainer, - connectionService, this.readerFailoverHandler, this.properties, this.failoverTimeoutMsSetting, @@ -335,8 +330,8 @@ public void initHostProvider( void initHostProvider( final HostListProviderService hostListProviderService, final JdbcCallable initHostProviderFunc, - final Function readerFailoverHandlerSupplier, - final Function writerFailoverHandlerSupplier) + final Supplier readerFailoverHandlerSupplier, + final Supplier writerFailoverHandlerSupplier) throws SQLException { this.readerFailoverHandlerSupplier = readerFailoverHandlerSupplier; this.writerFailoverHandlerSupplier = writerFailoverHandlerSupplier; @@ -603,10 +598,6 @@ protected void failover(@Nullable final HostSpec failedHost) throws SQLException this.pluginService.setAvailability(failedHost.asAliases(), HostAvailability.NOT_AVAILABLE); } - if (this.connectionService == null) { - this.connectionService = getConnectionService(); - } - if (this.failoverMode == FailoverMode.STRICT_WRITER) { failoverWriter(); } else { @@ -614,20 +605,6 @@ protected void failover(@Nullable final HostSpec failedHost) throws SQLException } } - protected ConnectionService getConnectionService() throws SQLException { - return new ConnectionServiceImpl( - servicesContainer.getStorageService(), - servicesContainer.getMonitorService(), - servicesContainer.getTelemetryFactory(), - this.pluginService.getDefaultConnectionProvider(), - this.pluginService.getOriginalUrl(), - this.pluginService.getDriverProtocol(), - this.pluginService.getTargetDriverDialect(), - this.pluginService.getDialect(), - properties - ); - } - protected void failoverReader(final HostSpec failedHostSpec) throws SQLException { TelemetryFactory telemetryFactory = this.pluginService.getTelemetryFactory(); TelemetryContext telemetryContext = telemetryFactory.openTelemetryContext( @@ -640,7 +617,7 @@ protected void failoverReader(final HostSpec failedHostSpec) throws SQLException if (this.readerFailoverHandlerSupplier == null) { throw new SQLException(Messages.get("Failover.nullReaderFailoverHandlerSupplier")); } - this.readerFailoverHandler = this.readerFailoverHandlerSupplier.apply(this.connectionService); + this.readerFailoverHandler = this.readerFailoverHandlerSupplier.get(); } final long failoverStartNano = System.nanoTime(); @@ -743,14 +720,14 @@ protected void failoverWriter() throws SQLException { if (this.readerFailoverHandlerSupplier == null) { throw new SQLException(Messages.get("Failover.nullReaderFailoverHandlerSupplier")); } - this.readerFailoverHandler = this.readerFailoverHandlerSupplier.apply(this.connectionService); + this.readerFailoverHandler = this.readerFailoverHandlerSupplier.get(); } if (this.writerFailoverHandler == null) { if (this.writerFailoverHandlerSupplier == null) { throw new SQLException(Messages.get("Failover.nullWriterFailoverHandlerSupplier")); } - this.writerFailoverHandler = this.writerFailoverHandlerSupplier.apply(this.connectionService); + this.writerFailoverHandler = this.writerFailoverHandlerSupplier.get(); } long failoverStartTimeNano = System.nanoTime(); diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/CredentialsProviderFactory.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/CredentialsProviderFactory.java index a43396bf9..655fbdda4 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/CredentialsProviderFactory.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/CredentialsProviderFactory.java @@ -16,7 +16,6 @@ package software.amazon.jdbc.plugin.federatedauth; -import java.io.Closeable; import java.sql.SQLException; import java.util.Properties; import org.checkerframework.checker.nullness.qual.NonNull; diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterMonitor.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterMonitor.java index cd983896a..f4075a285 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterMonitor.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterMonitor.java @@ -25,11 +25,10 @@ import java.util.logging.Logger; import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.HostSpec; -import software.amazon.jdbc.PluginService; +import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; import software.amazon.jdbc.util.Utils; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.monitoring.AbstractMonitor; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.TelemetryContext; @@ -45,27 +44,24 @@ public class LimitlessRouterMonitor extends AbstractMonitor { protected static final long TERMINATION_TIMEOUT_SEC = 5; protected final int intervalMs; protected final @NonNull HostSpec hostSpec; + protected final @NonNull FullServicesContainer servicesContainer; protected final @NonNull StorageService storageService; protected final @NonNull String limitlessRouterCacheKey; protected final @NonNull Properties props; - protected final @NonNull ConnectionService connectionService; protected final @NonNull LimitlessQueryHelper queryHelper; protected final @NonNull TelemetryFactory telemetryFactory; protected Connection monitoringConn = null; public LimitlessRouterMonitor( - final @NonNull PluginService pluginService, - final @NonNull ConnectionService connectionService, - final @NonNull TelemetryFactory telemetryFactory, + final @NonNull FullServicesContainer servicesContainer, final @NonNull HostSpec hostSpec, - final @NonNull StorageService storageService, final @NonNull String limitlessRouterCacheKey, final @NonNull Properties props, final int intervalMs) { super(TERMINATION_TIMEOUT_SEC); - this.connectionService = connectionService; - this.storageService = storageService; - this.telemetryFactory = telemetryFactory; + this.servicesContainer = servicesContainer; + this.storageService = servicesContainer.getStorageService(); + this.telemetryFactory = servicesContainer.getTelemetryFactory(); this.hostSpec = hostSpec; this.limitlessRouterCacheKey = limitlessRouterCacheKey; this.props = PropertyUtils.copyProperties(props); @@ -81,7 +77,7 @@ public LimitlessRouterMonitor( this.props.setProperty(LimitlessConnectionPlugin.WAIT_FOR_ROUTER_INFO.name, "false"); this.intervalMs = intervalMs; - this.queryHelper = new LimitlessQueryHelper(pluginService); + this.queryHelper = new LimitlessQueryHelper(servicesContainer.getPluginService()); } @Override @@ -170,7 +166,7 @@ private void openConnection() throws SQLException { LOGGER.finest(() -> Messages.get( "LimitlessRouterMonitor.openingConnection", new Object[] {this.hostSpec.getUrl()})); - this.monitoringConn = this.connectionService.open(this.hostSpec, this.props); + this.monitoringConn = this.servicesContainer.getPluginService().forceConnect(this.hostSpec, this.props); LOGGER.finest(() -> Messages.get( "LimitlessRouterMonitor.openedConnection", new Object[] {this.monitoringConn})); diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterService.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterService.java index 2d3d87a08..1e3a04560 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterService.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterService.java @@ -16,9 +16,7 @@ package software.amazon.jdbc.plugin.limitless; -import java.sql.Connection; import java.sql.SQLException; -import java.util.List; import java.util.Properties; import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.HostSpec; diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImpl.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImpl.java index 7b904c57d..b5f3e01a0 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImpl.java @@ -333,12 +333,9 @@ public void startMonitoring(final @NonNull HostSpec hostSpec, this.pluginService.getTargetDriverDialect(), this.pluginService.getDialect(), props, - (connectionService, pluginService) -> new LimitlessRouterMonitor( - pluginService, - connectionService, - this.servicesContainer.getTelemetryFactory(), + (servicesContainer) -> new LimitlessRouterMonitor( + servicesContainer, hostSpec, - this.servicesContainer.getStorageService(), limitlessRouterMonitorKey, props, intervalMs)); diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouters.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouters.java index 0793dbcff..ea7cab3ce 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouters.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouters.java @@ -20,7 +20,6 @@ import java.util.Objects; import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.HostSpec; -import software.amazon.jdbc.hostlistprovider.Topology; public class LimitlessRouters { private final @NonNull List hosts; diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/HostResponseTimeServiceImpl.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/HostResponseTimeServiceImpl.java index 824f1c5d3..ee157b3ea 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/HostResponseTimeServiceImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/HostResponseTimeServiceImpl.java @@ -78,15 +78,14 @@ public void setHosts(final @NonNull List hosts) { hostSpec.getUrl(), servicesContainer.getStorageService(), servicesContainer.getTelemetryFactory(), - this.pluginService.getDefaultConnectionProvider(), + servicesContainer.getDefaultConnectionProvider(), this.pluginService.getOriginalUrl(), this.pluginService.getDriverProtocol(), this.pluginService.getTargetDriverDialect(), this.pluginService.getDialect(), this.props, - (connectionService, pluginService) -> - new NodeResponseTimeMonitor(pluginService, connectionService, hostSpec, this.props, - this.intervalMs)); + (servicesContainer) -> + new NodeResponseTimeMonitor(pluginService, hostSpec, this.props, this.intervalMs)); } catch (SQLException e) { LOGGER.warning( Messages.get("HostResponseTimeServiceImpl.errorStartingMonitor", new Object[] {hostSpec.getUrl(), e})); diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/NodeResponseTimeMonitor.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/NodeResponseTimeMonitor.java index 1b985c03f..36322d9c1 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/NodeResponseTimeMonitor.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/NodeResponseTimeMonitor.java @@ -31,7 +31,6 @@ import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; import software.amazon.jdbc.util.StringUtils; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.monitoring.AbstractMonitor; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -56,7 +55,6 @@ public class NodeResponseTimeMonitor extends AbstractMonitor { private final @NonNull Properties props; private final @NonNull PluginService pluginService; - private final @NonNull ConnectionService connectionService; private final TelemetryFactory telemetryFactory; private final TelemetryGauge responseTimeMsGauge; @@ -65,14 +63,12 @@ public class NodeResponseTimeMonitor extends AbstractMonitor { public NodeResponseTimeMonitor( final @NonNull PluginService pluginService, - final @NonNull ConnectionService connectionService, final @NonNull HostSpec hostSpec, final @NonNull Properties props, int intervalMs) { super(TERMINATION_TIMEOUT_SEC); this.pluginService = pluginService; - this.connectionService = connectionService; this.hostSpec = hostSpec; this.props = props; this.intervalMs = intervalMs; @@ -197,7 +193,7 @@ private void openConnection() { LOGGER.finest(() -> Messages.get( "NodeResponseTimeMonitor.openingConnection", new Object[] {this.hostSpec.getUrl()})); - this.monitoringConn = this.connectionService.open(this.hostSpec, monitoringConnProperties); + this.monitoringConn = this.pluginService.forceConnect(this.hostSpec, monitoringConnProperties); LOGGER.finest(() -> Messages.get( "NodeResponseTimeMonitor.openedConnection", new Object[] {this.monitoringConn})); diff --git a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbDriverHelper.java b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbDriverHelper.java index 8c93819c3..d67638b6b 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbDriverHelper.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbDriverHelper.java @@ -18,7 +18,6 @@ import static software.amazon.jdbc.util.ConnectionUrlBuilder.buildUrl; -import com.mysql.cj.jdbc.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Collections; diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/ConnectionUrlParser.java b/wrapper/src/main/java/software/amazon/jdbc/util/ConnectionUrlParser.java index 81323335b..435907141 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/ConnectionUrlParser.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/ConnectionUrlParser.java @@ -16,7 +16,6 @@ package software.amazon.jdbc.util; -import com.fasterxml.jackson.databind.annotation.JsonAppend.Prop; import java.util.ArrayList; import java.util.List; import java.util.Map; diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainer.java b/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainer.java index e276b4503..7b7857175 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainer.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainer.java @@ -17,6 +17,7 @@ package software.amazon.jdbc.util; import software.amazon.jdbc.ConnectionPluginManager; +import software.amazon.jdbc.ConnectionProvider; import software.amazon.jdbc.HostListProviderService; import software.amazon.jdbc.PluginManagerService; import software.amazon.jdbc.PluginService; @@ -36,6 +37,8 @@ public interface FullServicesContainer { MonitorService getMonitorService(); + ConnectionProvider getDefaultConnectionProvider(); + TelemetryFactory getTelemetryFactory(); ConnectionPluginManager getConnectionPluginManager(); diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainerImpl.java b/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainerImpl.java index ef0a0fc53..db0ea3f57 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainerImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainerImpl.java @@ -17,6 +17,7 @@ package software.amazon.jdbc.util; import software.amazon.jdbc.ConnectionPluginManager; +import software.amazon.jdbc.ConnectionProvider; import software.amazon.jdbc.HostListProviderService; import software.amazon.jdbc.PluginManagerService; import software.amazon.jdbc.PluginService; @@ -27,6 +28,7 @@ public class FullServicesContainerImpl implements FullServicesContainer { private StorageService storageService; private MonitorService monitorService; + private ConnectionProvider defaultConnProvider; private TelemetryFactory telemetryFactory; private ConnectionPluginManager connectionPluginManager; private HostListProviderService hostListProviderService; @@ -36,12 +38,13 @@ public class FullServicesContainerImpl implements FullServicesContainer { public FullServicesContainerImpl( StorageService storageService, MonitorService monitorService, + ConnectionProvider defaultConnProvider, TelemetryFactory telemetryFactory, ConnectionPluginManager connectionPluginManager, HostListProviderService hostListProviderService, PluginService pluginService, PluginManagerService pluginManagerService) { - this(storageService, monitorService, telemetryFactory); + this(storageService, monitorService, defaultConnProvider, telemetryFactory); this.connectionPluginManager = connectionPluginManager; this.hostListProviderService = hostListProviderService; this.pluginService = pluginService; @@ -51,9 +54,11 @@ public FullServicesContainerImpl( public FullServicesContainerImpl( StorageService storageService, MonitorService monitorService, + ConnectionProvider defaultConnProvider, TelemetryFactory telemetryFactory) { this.storageService = storageService; this.monitorService = monitorService; + this.defaultConnProvider = defaultConnProvider; this.telemetryFactory = telemetryFactory; } @@ -67,6 +72,11 @@ public MonitorService getMonitorService() { return this.monitorService; } + @Override + public ConnectionProvider getDefaultConnectionProvider() { + return this.defaultConnProvider; + } + @Override public TelemetryFactory getTelemetryFactory() { return this.telemetryFactory; diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/PropertyUtils.java b/wrapper/src/main/java/software/amazon/jdbc/util/PropertyUtils.java index ce2f66fad..632aaac6c 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/PropertyUtils.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/PropertyUtils.java @@ -28,7 +28,6 @@ import java.util.Set; import java.util.logging.Logger; import org.checkerframework.checker.nullness.qual.NonNull; -import software.amazon.awssdk.services.rds.endpoints.internal.Value.Bool; import software.amazon.jdbc.AwsWrapperProperty; import software.amazon.jdbc.PropertyDefinition; diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/ServiceUtility.java b/wrapper/src/main/java/software/amazon/jdbc/util/ServiceUtility.java new file mode 100644 index 000000000..54a09af23 --- /dev/null +++ b/wrapper/src/main/java/software/amazon/jdbc/util/ServiceUtility.java @@ -0,0 +1,87 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package software.amazon.jdbc.util; + +import java.sql.SQLException; +import java.util.Properties; +import java.util.concurrent.locks.ReentrantLock; +import software.amazon.jdbc.ConnectionPluginManager; +import software.amazon.jdbc.ConnectionProvider; +import software.amazon.jdbc.PartialPluginService; +import software.amazon.jdbc.dialect.Dialect; +import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; +import software.amazon.jdbc.util.monitoring.MonitorService; +import software.amazon.jdbc.util.storage.StorageService; +import software.amazon.jdbc.util.telemetry.TelemetryFactory; + +public class ServiceUtility { + private static final ServiceUtility instance = new ServiceUtility(); + + private ServiceUtility() {} + + public static ServiceUtility getInstance() { + return instance; + } + + public FullServicesContainer createServiceContainer( + StorageService storageService, + MonitorService monitorService, + ConnectionProvider connectionProvider, + TelemetryFactory telemetryFactory, + String originalUrl, + String targetDriverProtocol, + TargetDriverDialect driverDialect, + Dialect dbDialect, + Properties props) throws SQLException { + FullServicesContainer servicesContainer = + new FullServicesContainerImpl(storageService, monitorService, connectionProvider, telemetryFactory); + ConnectionPluginManager pluginManager = new ConnectionPluginManager( + connectionProvider, null, null, telemetryFactory); + servicesContainer.setConnectionPluginManager(pluginManager); + + PartialPluginService partialPluginService = new PartialPluginService( + servicesContainer, + props, + originalUrl, + targetDriverProtocol, + driverDialect, + dbDialect + ); + + servicesContainer.setHostListProviderService(partialPluginService); + servicesContainer.setPluginService(partialPluginService); + servicesContainer.setPluginManagerService(partialPluginService); + + pluginManager.init(servicesContainer, props, partialPluginService, null); + return servicesContainer; + } + + public FullServicesContainer createServiceContainer(FullServicesContainer servicesContainer, Properties props) + throws SQLException { + return createServiceContainer( + servicesContainer.getStorageService(), + servicesContainer.getMonitorService(), + servicesContainer.getPluginService().getDefaultConnectionProvider(), + servicesContainer.getTelemetryFactory(), + servicesContainer.getPluginService().getOriginalUrl(), + servicesContainer.getPluginService().getDriverProtocol(), + servicesContainer.getPluginService().getTargetDriverDialect(), + servicesContainer.getPluginService().getDialect(), + props + ); + } +} diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionService.java b/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionService.java index 5a6f4fcff..e0748bc72 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionService.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionService.java @@ -21,7 +21,16 @@ import java.util.Properties; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.PluginService; +import software.amazon.jdbc.util.FullServicesContainer; +/** + * A service used to open new connections for internal driver use. + * + * @deprecated This interface is deprecated and will be removed in a future version. Use + * {@link software.amazon.jdbc.util.ServiceUtility#createServiceContainer} followed by + * {@link PluginService#forceConnect} instead. + */ +@Deprecated public interface ConnectionService { /** * Creates an auxiliary connection. Auxiliary connections are driver-internal connections that accomplish various @@ -31,8 +40,19 @@ public interface ConnectionService { * @param props the properties for the auxiliary connection. * @return a new connection to the given host using the given props. * @throws SQLException if an error occurs while opening the connection. + * @deprecated Use {@link software.amazon.jdbc.util.ServiceUtility#createServiceContainer} followed by + * {@link PluginService#forceConnect} instead. */ + @Deprecated Connection open(HostSpec hostSpec, Properties props) throws SQLException; + /** + * Get the {@link PluginService} associated with this {@link ConnectionService}. + * + * @return the {@link PluginService} associated with this {@link ConnectionService} + * @deprecated Use {@link software.amazon.jdbc.util.ServiceUtility#createServiceContainer} followed by + * {@link FullServicesContainer#getPluginService()} instead. + */ + @Deprecated PluginService getPluginService(); } diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionServiceImpl.java b/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionServiceImpl.java index 0e506a112..9e8356eb9 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionServiceImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionServiceImpl.java @@ -28,15 +28,30 @@ import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.FullServicesContainerImpl; +import software.amazon.jdbc.util.PropertyUtils; import software.amazon.jdbc.util.monitoring.MonitorService; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.TelemetryFactory; +/** + * A service used to open new connections for internal driver use. + * + * @deprecated This class is deprecated and will be removed in a future version. Use + * {@link software.amazon.jdbc.util.ServiceUtility#createServiceContainer} followed by + * {@link PluginService#forceConnect} instead. + */ +@Deprecated public class ConnectionServiceImpl implements ConnectionService { protected final String targetDriverProtocol; protected final ConnectionPluginManager pluginManager; protected final PluginService pluginService; + /** + * Constructs a {@link ConnectionServiceImpl} instance. + * + * @deprecated Use {@link software.amazon.jdbc.util.ServiceUtility#createServiceContainer} instead. + */ + @Deprecated public ConnectionServiceImpl( StorageService storageService, MonitorService monitorService, @@ -49,8 +64,8 @@ public ConnectionServiceImpl( Properties props) throws SQLException { this.targetDriverProtocol = targetDriverProtocol; - FullServicesContainer - servicesContainer = new FullServicesContainerImpl(storageService, monitorService, telemetryFactory); + FullServicesContainer servicesContainer = + new FullServicesContainerImpl(storageService, monitorService, connectionProvider, telemetryFactory); this.pluginManager = new ConnectionPluginManager( connectionProvider, null, @@ -58,25 +73,32 @@ public ConnectionServiceImpl( telemetryFactory); servicesContainer.setConnectionPluginManager(this.pluginManager); + Properties propsCopy = PropertyUtils.copyProperties(props); PartialPluginService partialPluginService = new PartialPluginService( servicesContainer, - props, + propsCopy, originalUrl, this.targetDriverProtocol, driverDialect, dbDialect ); + servicesContainer.setHostListProviderService(partialPluginService); + servicesContainer.setPluginService(partialPluginService); + servicesContainer.setPluginManagerService(partialPluginService); + this.pluginService = partialPluginService; - this.pluginManager.init(servicesContainer, props, partialPluginService, null); + this.pluginManager.init(servicesContainer, propsCopy, partialPluginService, null); } @Override + @Deprecated public Connection open(HostSpec hostSpec, Properties props) throws SQLException { return this.pluginManager.forceConnect(this.targetDriverProtocol, hostSpec, props, true, null); } @Override + @Deprecated public PluginService getPluginService() { return this.pluginService; } diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/Monitor.java b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/Monitor.java index d4d89dc4c..fbdd55063 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/Monitor.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/Monitor.java @@ -27,7 +27,7 @@ public interface Monitor { * submitted during the call to {@link #start()}. Additionally, the monitoring loop should regularly update the last * activity timestamp so that the {@link MonitorService} can detect whether the monitor is stuck or not. */ - void monitor(); + void monitor() throws Exception; /** * Stops the monitoring tasks for this monitor and closes all resources. diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorInitializer.java b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorInitializer.java index c4f13e6f9..e1cb59a95 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorInitializer.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorInitializer.java @@ -16,10 +16,9 @@ package software.amazon.jdbc.util.monitoring; -import software.amazon.jdbc.PluginService; -import software.amazon.jdbc.util.connection.ConnectionService; +import software.amazon.jdbc.util.FullServicesContainer; +@FunctionalInterface public interface MonitorInitializer { - - Monitor createMonitor(ConnectionService connectionService, PluginService pluginService); + Monitor createMonitor(FullServicesContainer servicesContainer); } diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorServiceImpl.java b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorServiceImpl.java index f9f784208..5e0df4817 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorServiceImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorServiceImpl.java @@ -40,10 +40,10 @@ import software.amazon.jdbc.plugin.strategy.fastestresponse.NodeResponseTimeMonitor; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.ExecutorFactory; +import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; -import software.amazon.jdbc.util.connection.ConnectionService; -import software.amazon.jdbc.util.connection.ConnectionServiceImpl; +import software.amazon.jdbc.util.ServiceUtility; import software.amazon.jdbc.util.events.DataAccessEvent; import software.amazon.jdbc.util.events.Event; import software.amazon.jdbc.util.events.EventPublisher; @@ -204,20 +204,16 @@ public T runIfAbsent( final List exceptionList = new ArrayList<>(1); MonitorItem monitorItem = cacheContainer.getCache().computeIfAbsent(key, k -> { try { - final ConnectionService connectionService = - getConnectionService( - storageService, - telemetryFactory, - defaultConnectionProvider, - originalUrl, - driverProtocol, - driverDialect, - dbDialect, - originalProps); - final MonitorItem monitorItemInner = new MonitorItem(() -> initializer.createMonitor( - connectionService, - connectionService.getPluginService()) - ); + final FullServicesContainer servicesContainer = getNewServicesContainer( + storageService, + defaultConnectionProvider, + telemetryFactory, + originalUrl, + driverProtocol, + driverDialect, + dbDialect, + originalProps); + final MonitorItem monitorItemInner = new MonitorItem(() -> initializer.createMonitor(servicesContainer)); monitorItemInner.getMonitor().start(); return monitorItemInner; } catch (SQLException e) { @@ -239,26 +235,27 @@ public T runIfAbsent( Messages.get("MonitorServiceImpl.unexpectedMonitorClass", new Object[] {monitorClass, monitor})); } - protected ConnectionService getConnectionService( + protected FullServicesContainer getNewServicesContainer( StorageService storageService, + ConnectionProvider connectionProvider, TelemetryFactory telemetryFactory, - ConnectionProvider defaultConnectionProvider, String originalUrl, String driverProtocol, TargetDriverDialect driverDialect, Dialect dbDialect, Properties originalProps) throws SQLException { final Properties propsCopy = PropertyUtils.copyProperties(originalProps); - return new ConnectionServiceImpl( + return ServiceUtility.getInstance().createServiceContainer( storageService, this, + connectionProvider, telemetryFactory, - defaultConnectionProvider, originalUrl, driverProtocol, driverDialect, dbDialect, - propsCopy); + propsCopy + ); } @Override diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/storage/SlidingExpirationCache.java b/wrapper/src/main/java/software/amazon/jdbc/util/storage/SlidingExpirationCache.java index 7f670866e..604b603f2 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/storage/SlidingExpirationCache.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/storage/SlidingExpirationCache.java @@ -20,7 +20,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; diff --git a/wrapper/src/main/java/software/amazon/jdbc/wrapper/ConnectionWrapper.java b/wrapper/src/main/java/software/amazon/jdbc/wrapper/ConnectionWrapper.java index dd99e0fee..90b47ac88 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/wrapper/ConnectionWrapper.java +++ b/wrapper/src/main/java/software/amazon/jdbc/wrapper/ConnectionWrapper.java @@ -58,7 +58,6 @@ import software.amazon.jdbc.util.SqlState; import software.amazon.jdbc.util.StringUtils; import software.amazon.jdbc.util.WrapperUtils; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.monitoring.MonitorService; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -136,8 +135,7 @@ protected ConnectionWrapper( @NonNull final HostListProviderService hostListProviderService, @NonNull final PluginManagerService pluginManagerService, @NonNull final StorageService storageService, - @NonNull final MonitorService monitorService, - @NonNull final ConnectionService connectionService) + @NonNull final MonitorService monitorService) throws SQLException { if (StringUtils.isNullOrEmpty(url)) { @@ -147,6 +145,7 @@ protected ConnectionWrapper( FullServicesContainer servicesContainer = new FullServicesContainerImpl( storageService, monitorService, + defaultConnectionProvider, telemetryFactory, connectionPluginManager, hostListProviderService, diff --git a/wrapper/src/test/java/integration/container/tests/hibernate/HibernateTests.java b/wrapper/src/test/java/integration/container/tests/hibernate/HibernateTests.java index 01d263f6b..fd4e1eac9 100644 --- a/wrapper/src/test/java/integration/container/tests/hibernate/HibernateTests.java +++ b/wrapper/src/test/java/integration/container/tests/hibernate/HibernateTests.java @@ -20,7 +20,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import integration.DatabaseEngine; -import integration.DatabaseEngineDeployment; import integration.DriverHelper; import integration.TestEnvironmentFeatures; import integration.container.ConnectionStringHelper; diff --git a/wrapper/src/test/java/integration/host/TestEnvironment.java b/wrapper/src/test/java/integration/host/TestEnvironment.java index 424b741ea..ce639a152 100644 --- a/wrapper/src/test/java/integration/host/TestEnvironment.java +++ b/wrapper/src/test/java/integration/host/TestEnvironment.java @@ -50,7 +50,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Logger; -import org.testcontainers.containers.BindMode; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; import org.testcontainers.containers.ToxiproxyContainer; diff --git a/wrapper/src/test/java/integration/util/ContainerHelper.java b/wrapper/src/test/java/integration/util/ContainerHelper.java index bc977dcda..6745badd8 100644 --- a/wrapper/src/test/java/integration/util/ContainerHelper.java +++ b/wrapper/src/test/java/integration/util/ContainerHelper.java @@ -42,7 +42,6 @@ import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.output.FrameConsumerResultCallback; import org.testcontainers.containers.output.OutputFrame; -import org.testcontainers.containers.startupcheck.StartupCheckStrategy; import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.builder.ImageFromDockerfile; diff --git a/wrapper/src/test/java/software/amazon/jdbc/ConnectionPluginChainBuilderTests.java b/wrapper/src/test/java/software/amazon/jdbc/ConnectionPluginChainBuilderTests.java index 84efe5ba3..4352d0622 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/ConnectionPluginChainBuilderTests.java +++ b/wrapper/src/test/java/software/amazon/jdbc/ConnectionPluginChainBuilderTests.java @@ -28,7 +28,6 @@ import java.util.HashSet; import java.util.List; import java.util.Properties; -import java.util.Set; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/wrapper/src/test/java/software/amazon/jdbc/DialectTests.java b/wrapper/src/test/java/software/amazon/jdbc/DialectTests.java index 0caefc973..4170f8556 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/DialectTests.java +++ b/wrapper/src/test/java/software/amazon/jdbc/DialectTests.java @@ -35,7 +35,6 @@ import org.mockito.MockitoAnnotations; import software.amazon.jdbc.dialect.AuroraMysqlDialect; import software.amazon.jdbc.dialect.AuroraPgDialect; -import software.amazon.jdbc.dialect.DialectManager; import software.amazon.jdbc.dialect.MariaDbDialect; import software.amazon.jdbc.dialect.MysqlDialect; import software.amazon.jdbc.dialect.PgDialect; diff --git a/wrapper/src/test/java/software/amazon/jdbc/authentication/AwsCredentialsManagerTest.java b/wrapper/src/test/java/software/amazon/jdbc/authentication/AwsCredentialsManagerTest.java index 6028f5706..56d24e076 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/authentication/AwsCredentialsManagerTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/authentication/AwsCredentialsManagerTest.java @@ -17,7 +17,6 @@ package software.amazon.jdbc.authentication; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/dev/DeveloperConnectionPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/dev/DeveloperConnectionPluginTest.java index 638e99a4f..f4cc60fec 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/dev/DeveloperConnectionPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/dev/DeveloperConnectionPluginTest.java @@ -73,7 +73,8 @@ void cleanUp() throws Exception { @BeforeEach void init() throws SQLException { closeable = MockitoAnnotations.openMocks(this); - servicesContainer = new FullServicesContainerImpl(mockStorageService, mockMonitorService, mockTelemetryFactory); + servicesContainer = new FullServicesContainerImpl( + mockStorageService, mockMonitorService, mockConnectionProvider, mockTelemetryFactory); when(mockConnectionProvider.connect(any(), any(), any(), any(), any())).thenReturn(mockConnection); when(mockConnectCallback.getExceptionToRaise(any(), any(), any(), anyBoolean())).thenReturn(null); diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandlerTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandlerTest.java index 89e838acb..fba8a4761 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandlerTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandlerTest.java @@ -48,7 +48,6 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.stubbing.Answer; -import software.amazon.jdbc.ConnectionPluginManager; import software.amazon.jdbc.HostRole; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.HostSpecBuilder; @@ -57,13 +56,11 @@ import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; import software.amazon.jdbc.util.FullServicesContainer; -import software.amazon.jdbc.util.connection.ConnectionService; class ClusterAwareReaderFailoverHandlerTest { - @Mock FullServicesContainer mockContainer; - @Mock ConnectionService mockConnectionService; + @Mock FullServicesContainer mockContainer1; + @Mock FullServicesContainer mockContainer2; @Mock PluginService mockPluginService; - @Mock ConnectionPluginManager mockPluginManager; @Mock Connection mockConnection; private AutoCloseable closeable; @@ -86,8 +83,8 @@ class ClusterAwareReaderFailoverHandlerTest { @BeforeEach void setUp() { closeable = MockitoAnnotations.openMocks(this); - when(mockContainer.getConnectionPluginManager()).thenReturn(mockPluginManager); - when(mockContainer.getPluginService()).thenReturn(mockPluginService); + when(mockContainer1.getPluginService()).thenReturn(mockPluginService); + when(mockContainer2.getPluginService()).thenReturn(mockPluginService); } @AfterEach @@ -108,11 +105,11 @@ public void testFailover() throws SQLException { for (int i = 0; i < hosts.size(); i++) { if (i != successHostIndex) { final SQLException exception = new SQLException("exception", "08S01", null); - when(mockConnectionService.open(hosts.get(i), properties)) + when(mockPluginService.forceConnect(hosts.get(i), properties)) .thenThrow(exception); when(mockPluginService.isNetworkException(exception, null)).thenReturn(true); } else { - when(mockConnectionService.open(hosts.get(i), properties)).thenReturn(mockConnection); + when(mockPluginService.forceConnect(hosts.get(i), properties)).thenReturn(mockConnection); } } @@ -154,7 +151,7 @@ public void testFailover_timeout() throws SQLException { final List hosts = defaultHosts; final int currentHostIndex = 2; for (HostSpec host : hosts) { - when(mockConnectionService.open(host, properties)) + when(mockPluginService.forceConnect(host, properties)) .thenAnswer((Answer) invocation -> { Thread.sleep(20000); return mockConnection; @@ -180,17 +177,17 @@ public void testFailover_timeout() throws SQLException { private ClusterAwareReaderFailoverHandler getSpyFailoverHandler() throws SQLException { ClusterAwareReaderFailoverHandler handler = - spy(new ClusterAwareReaderFailoverHandler(mockContainer, mockConnectionService, properties)); - doReturn(mockPluginService).when(handler).getNewPluginService(); + spy(new ClusterAwareReaderFailoverHandler(mockContainer1, properties)); + doReturn(mockContainer2).when(handler).newServicesContainer(); return handler; } private ClusterAwareReaderFailoverHandler getSpyFailoverHandler( int maxFailoverTimeoutMs, int timeoutMs, boolean isStrictReaderRequired) throws SQLException { ClusterAwareReaderFailoverHandler handler = new ClusterAwareReaderFailoverHandler( - mockContainer, mockConnectionService, properties, maxFailoverTimeoutMs, timeoutMs, isStrictReaderRequired); + mockContainer1, properties, maxFailoverTimeoutMs, timeoutMs, isStrictReaderRequired); ClusterAwareReaderFailoverHandler spyHandler = spy(handler); - doReturn(mockPluginService).when(spyHandler).getNewPluginService(); + doReturn(mockContainer2).when(spyHandler).newServicesContainer(); return spyHandler; } @@ -220,14 +217,14 @@ public void testGetReader_connectionSuccess() throws SQLException { final List hosts = defaultHosts.subList(0, 3); // 2 connection attempts (writer not attempted) final HostSpec slowHost = hosts.get(1); final HostSpec fastHost = hosts.get(2); - when(mockConnectionService.open(slowHost, properties)) + when(mockPluginService.forceConnect(slowHost, properties)) .thenAnswer( (Answer) invocation -> { Thread.sleep(20000); return mockConnection; }); - when(mockConnectionService.open(eq(fastHost), eq(properties))).thenReturn(mockConnection); + when(mockPluginService.forceConnect(eq(fastHost), eq(properties))).thenReturn(mockConnection); Dialect mockDialect = Mockito.mock(Dialect.class); when(mockDialect.getFailoverRestrictions()).thenReturn(EnumSet.noneOf(FailoverRestriction.class)); @@ -251,7 +248,7 @@ public void testGetReader_connectionFailure() throws SQLException { // first connection attempt to return fails // expected test result: failure to get reader final List hosts = defaultHosts.subList(0, 4); // 3 connection attempts (writer not attempted) - when(mockConnectionService.open(any(), eq(properties))).thenThrow(new SQLException("exception", "08S01", null)); + when(mockPluginService.forceConnect(any(), eq(properties))).thenThrow(new SQLException("exception", "08S01", null)); Dialect mockDialect = Mockito.mock(Dialect.class); when(mockDialect.getFailoverRestrictions()).thenReturn(EnumSet.noneOf(FailoverRestriction.class)); @@ -271,7 +268,7 @@ public void testGetReader_connectionAttemptsTimeout() throws SQLException { // first connection attempt to return times out // expected test result: failure to get reader final List hosts = defaultHosts.subList(0, 3); // 2 connection attempts (writer not attempted) - when(mockConnectionService.open(any(), eq(properties))) + when(mockPluginService.forceConnect(any(), eq(properties))) .thenAnswer( (Answer) invocation -> { @@ -384,7 +381,7 @@ public void testHostFailoverStrictReaderEnabled() throws SQLException { List hostsByPriority = target.getHostsByPriority(hosts); assertEquals(expectedHostsByPriority, hostsByPriority); - // Should pick the reader even if unavailable. The unavailable reader will be lower priority than the writer. + // Should pick the reader even if unavailable. The unavailable reader will have lower priority than the writer. reader.setAvailability(HostAvailability.NOT_AVAILABLE); expectedHostsByPriority = Arrays.asList(writer, reader); diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandlerTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandlerTest.java index 902aadfcb..b790cef8c 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandlerTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandlerTest.java @@ -50,11 +50,10 @@ import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; import software.amazon.jdbc.util.FullServicesContainer; -import software.amazon.jdbc.util.connection.ConnectionService; class ClusterAwareWriterFailoverHandlerTest { - @Mock FullServicesContainer mockContainer; - @Mock ConnectionService mockConnectionService; + @Mock FullServicesContainer mockContainer1; + @Mock FullServicesContainer mockContainer2; @Mock PluginService mockPluginService; @Mock Connection mockConnection; @Mock ReaderFailoverHandler mockReaderFailoverHandler; @@ -80,7 +79,8 @@ class ClusterAwareWriterFailoverHandlerTest { @BeforeEach void setUp() { closeable = MockitoAnnotations.openMocks(this); - when(mockContainer.getPluginService()).thenReturn(mockPluginService); + when(mockContainer1.getPluginService()).thenReturn(mockPluginService); + when(mockContainer2.getPluginService()).thenReturn(mockPluginService); writer.addAlias("writer-host"); newWriterHost.addAlias("new-writer-host"); readerA.addAlias("reader-a-host"); @@ -94,9 +94,9 @@ void tearDown() throws Exception { @Test public void testReconnectToWriter_taskBReaderException() throws SQLException { - when(mockConnectionService.open(refEq(writer), eq(properties))).thenReturn(mockConnection); - when(mockConnectionService.open(refEq(readerA), eq(properties))).thenThrow(SQLException.class); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenThrow(SQLException.class); + when(mockPluginService.forceConnect(refEq(writer), eq(properties))).thenReturn(mockConnection); + when(mockPluginService.forceConnect(refEq(readerA), eq(properties))).thenThrow(SQLException.class); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenThrow(SQLException.class); when(mockPluginService.getAllHosts()).thenReturn(topology); @@ -120,8 +120,7 @@ private ClusterAwareWriterFailoverHandler getSpyFailoverHandler( final int readTopologyIntervalMs, final int reconnectWriterIntervalMs) throws SQLException { ClusterAwareWriterFailoverHandler handler = new ClusterAwareWriterFailoverHandler( - mockContainer, - mockConnectionService, + mockContainer1, mockReaderFailoverHandler, properties, failoverTimeoutMs, @@ -129,7 +128,7 @@ private ClusterAwareWriterFailoverHandler getSpyFailoverHandler( reconnectWriterIntervalMs); ClusterAwareWriterFailoverHandler spyHandler = spy(handler); - doReturn(mockPluginService).when(spyHandler).getNewPluginService(); + doReturn(mockContainer2).when(spyHandler).newServicesContainer(); return spyHandler; } @@ -143,9 +142,9 @@ private ClusterAwareWriterFailoverHandler getSpyFailoverHandler( */ @Test public void testReconnectToWriter_SlowReaderA() throws SQLException { - when(mockConnectionService.open(refEq(writer), eq(properties))).thenReturn(mockWriterConnection); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenThrow(SQLException.class); - when(mockConnectionService.open(refEq(newWriterHost), eq(properties))).thenReturn(mockNewWriterConnection); + when(mockPluginService.forceConnect(refEq(writer), eq(properties))).thenReturn(mockWriterConnection); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenThrow(SQLException.class); + when(mockPluginService.forceConnect(refEq(newWriterHost), eq(properties))).thenReturn(mockNewWriterConnection); when(mockPluginService.getAllHosts()).thenReturn(topology).thenReturn(newTopology); when(mockReaderFailoverHandler.getReaderConnection(ArgumentMatchers.anyList())) @@ -178,14 +177,14 @@ public void testReconnectToWriter_SlowReaderA() throws SQLException { */ @Test public void testReconnectToWriter_taskBDefers() throws SQLException { - when(mockConnectionService.open(refEq(writer), eq(properties))) + when(mockPluginService.forceConnect(refEq(writer), eq(properties))) .thenAnswer( (Answer) invocation -> { Thread.sleep(5000); return mockWriterConnection; }); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenThrow(SQLException.class); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenThrow(SQLException.class); when(mockPluginService.getAllHosts()).thenReturn(topology); @@ -215,16 +214,16 @@ public void testReconnectToWriter_taskBDefers() throws SQLException { */ @Test public void testConnectToReaderA_SlowWriter() throws SQLException { - when(mockConnectionService.open(refEq(writer), eq(properties))) + when(mockPluginService.forceConnect(refEq(writer), eq(properties))) .thenAnswer( (Answer) invocation -> { Thread.sleep(5000); return mockWriterConnection; }); - when(mockConnectionService.open(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); - when(mockConnectionService.open(refEq(newWriterHost), eq(properties))).thenReturn(mockNewWriterConnection); + when(mockPluginService.forceConnect(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); + when(mockPluginService.forceConnect(refEq(newWriterHost), eq(properties))).thenReturn(mockNewWriterConnection); when(mockPluginService.getAllHosts()).thenReturn(newTopology); @@ -255,10 +254,10 @@ public void testConnectToReaderA_SlowWriter() throws SQLException { */ @Test public void testConnectToReaderA_taskADefers() throws SQLException { - when(mockConnectionService.open(writer, properties)).thenReturn(mockConnection); - when(mockConnectionService.open(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); - when(mockConnectionService.open(refEq(newWriterHost), eq(properties))) + when(mockPluginService.forceConnect(writer, properties)).thenReturn(mockConnection); + when(mockPluginService.forceConnect(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); + when(mockPluginService.forceConnect(refEq(newWriterHost), eq(properties))) .thenAnswer( (Answer) invocation -> { @@ -298,16 +297,16 @@ public void testConnectToReaderA_taskADefers() throws SQLException { */ @Test public void testFailedToConnect_failoverTimeout() throws SQLException { - when(mockConnectionService.open(refEq(writer), eq(properties))) + when(mockPluginService.forceConnect(refEq(writer), eq(properties))) .thenAnswer( (Answer) invocation -> { Thread.sleep(30000); return mockWriterConnection; }); - when(mockConnectionService.open(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); - when(mockConnectionService.open(refEq(newWriterHost), eq(properties))) + when(mockPluginService.forceConnect(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); + when(mockPluginService.forceConnect(refEq(newWriterHost), eq(properties))) .thenAnswer( (Answer) invocation -> { @@ -348,10 +347,10 @@ public void testFailedToConnect_failoverTimeout() throws SQLException { @Test public void testFailedToConnect_taskAException_taskBWriterException() throws SQLException { final SQLException exception = new SQLException("exception", "08S01", null); - when(mockConnectionService.open(refEq(writer), eq(properties))).thenThrow(exception); - when(mockConnectionService.open(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); - when(mockConnectionService.open(refEq(newWriterHost), eq(properties))).thenThrow(exception); + when(mockPluginService.forceConnect(refEq(writer), eq(properties))).thenThrow(exception); + when(mockPluginService.forceConnect(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); + when(mockPluginService.forceConnect(refEq(newWriterHost), eq(properties))).thenThrow(exception); when(mockPluginService.isNetworkException(eq(exception), any())).thenReturn(true); when(mockPluginService.getAllHosts()).thenReturn(newTopology); diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPluginTest.java index 2be3e2858..637793772 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPluginTest.java @@ -24,7 +24,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -64,7 +63,6 @@ import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.RdsUrlType; import software.amazon.jdbc.util.SqlState; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.telemetry.GaugeCallable; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryCounter; @@ -83,7 +81,6 @@ class FailoverConnectionPluginTest { .host("reader1").port(1234).role(HostRole.READER).build()); @Mock FullServicesContainer mockContainer; - @Mock ConnectionService mockConnectionService; @Mock PluginService mockPluginService; @Mock Connection mockConnection; @Mock HostSpec mockHostSpec; @@ -144,7 +141,7 @@ void init() throws SQLException { } @Test - void test_notifyNodeListChanged_withFailoverDisabled() throws SQLException { + void test_notifyNodeListChanged_withFailoverDisabled() { properties.setProperty(FailoverConnectionPlugin.ENABLE_CLUSTER_AWARE_FAILOVER.name, "false"); final Map> changes = new HashMap<>(); @@ -156,7 +153,7 @@ void test_notifyNodeListChanged_withFailoverDisabled() throws SQLException { } @Test - void test_notifyNodeListChanged_withValidConnectionNotInTopology() throws SQLException { + void test_notifyNodeListChanged_withValidConnectionNotInTopology() { final Map> changes = new HashMap<>(); changes.put("cluster-host/", EnumSet.of(NodeChangeOptions.NODE_DELETED)); changes.put("instance/", EnumSet.of(NodeChangeOptions.NODE_ADDED)); @@ -250,8 +247,8 @@ void test_failoverReader_withValidFailedHostSpec_successFailover() throws SQLExc spyPlugin.initHostProvider( mockHostListProviderService, mockInitHostProviderFunc, - (connectionService) -> mockReaderFailoverHandler, - (connectionService) -> mockWriterFailoverHandler); + () -> mockReaderFailoverHandler, + () -> mockWriterFailoverHandler); final FailoverConnectionPlugin spyPlugin = spy(this.spyPlugin); doNothing().when(spyPlugin).updateTopology(true); @@ -279,8 +276,8 @@ void test_failoverReader_withNoFailedHostSpec_withException() throws SQLExceptio spyPlugin.initHostProvider( mockHostListProviderService, mockInitHostProviderFunc, - (connectionService) -> mockReaderFailoverHandler, - (connectionService) -> mockWriterFailoverHandler); + () -> mockReaderFailoverHandler, + () -> mockWriterFailoverHandler); assertThrows(SQLException.class, () -> spyPlugin.failoverReader(null)); verify(mockReaderFailoverHandler).failover(eq(hosts), eq(null)); @@ -301,8 +298,8 @@ void test_failoverWriter_failedFailover_throwsException() throws SQLException { spyPlugin.initHostProvider( mockHostListProviderService, mockInitHostProviderFunc, - (connectionService) -> mockReaderFailoverHandler, - (connectionService) -> mockWriterFailoverHandler); + () -> mockReaderFailoverHandler, + () -> mockWriterFailoverHandler); assertThrows(SQLException.class, () -> spyPlugin.failoverWriter()); verify(mockWriterFailoverHandler).failover(eq(hosts)); @@ -323,8 +320,8 @@ void test_failoverWriter_failedFailover_withNoResult() throws SQLException { spyPlugin.initHostProvider( mockHostListProviderService, mockInitHostProviderFunc, - (connectionService) -> mockReaderFailoverHandler, - (connectionService) -> mockWriterFailoverHandler); + () -> mockReaderFailoverHandler, + () -> mockWriterFailoverHandler); final SQLException exception = assertThrows(SQLException.class, () -> spyPlugin.failoverWriter()); assertEquals(SqlState.CONNECTION_UNABLE_TO_CONNECT.getState(), exception.getSQLState()); @@ -342,8 +339,8 @@ void test_failoverWriter_successFailover() throws SQLException { spyPlugin.initHostProvider( mockHostListProviderService, mockInitHostProviderFunc, - (connectionService) -> mockReaderFailoverHandler, - (connectionService) -> mockWriterFailoverHandler); + () -> mockReaderFailoverHandler, + () -> mockWriterFailoverHandler); final SQLException exception = assertThrows(FailoverSuccessSQLException.class, () -> spyPlugin.failoverWriter()); assertEquals(SqlState.COMMUNICATION_LINK_CHANGED.getState(), exception.getSQLState()); @@ -352,7 +349,7 @@ void test_failoverWriter_successFailover() throws SQLException { } @Test - void test_invalidCurrentConnection_withNoConnection() throws SQLException { + void test_invalidCurrentConnection_withNoConnection() { when(mockPluginService.getCurrentConnection()).thenReturn(null); initializePlugin(); spyPlugin.invalidateCurrentConnection(); @@ -377,7 +374,7 @@ void test_invalidateCurrentConnection_inTransaction() throws SQLException { } @Test - void test_invalidateCurrentConnection_notInTransaction() throws SQLException { + void test_invalidateCurrentConnection_notInTransaction() { when(mockPluginService.isInTransaction()).thenReturn(false); when(mockHostSpec.getHost()).thenReturn("host"); when(mockHostSpec.getPort()).thenReturn(123); @@ -438,10 +435,9 @@ void test_execute_withDirectExecute() throws SQLException { verify(mockHostListProvider, never()).getRdsUrlType(); } - private void initializePlugin() throws SQLException { + private void initializePlugin() { spyPlugin = spy(new FailoverConnectionPlugin(mockContainer, properties)); spyPlugin.setWriterFailoverHandler(mockWriterFailoverHandler); spyPlugin.setReaderFailoverHandler(mockReaderFailoverHandler); - doReturn(mockConnectionService).when(spyPlugin).getConnectionService(); } } diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/iam/IamAuthConnectionPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/iam/IamAuthConnectionPluginTest.java index 92a0c0ff6..a872ac96c 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/iam/IamAuthConnectionPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/iam/IamAuthConnectionPluginTest.java @@ -44,17 +44,13 @@ import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.rds.RdsUtilities; -import software.amazon.awssdk.services.rds.TestDefaultRdsUtilities; import software.amazon.jdbc.Driver; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.HostSpecBuilder; import software.amazon.jdbc.JdbcCallable; import software.amazon.jdbc.PluginService; import software.amazon.jdbc.PropertyDefinition; -import software.amazon.jdbc.authentication.AwsCredentialsManager; import software.amazon.jdbc.dialect.Dialect; -import software.amazon.jdbc.hostavailability.HostAvailabilityStrategy; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; import software.amazon.jdbc.plugin.TokenInfo; import software.amazon.jdbc.util.RdsUtils; diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImplTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImplTest.java index b37df47a8..7c12f83fb 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImplTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImplTest.java @@ -37,6 +37,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import software.amazon.jdbc.ConnectionProvider; import software.amazon.jdbc.HighestWeightHostSelector; import software.amazon.jdbc.HostListProvider; import software.amazon.jdbc.HostRole; @@ -61,6 +62,7 @@ class LimitlessRouterServiceImplTest { private static final String CLUSTER_ID = "someClusterId"; @Mock private EventPublisher mockEventPublisher; @Mock private MonitorService mockMonitorService; + @Mock private ConnectionProvider mockConnectionProvider; @Mock private TelemetryFactory mockTelemetryFactory; @Mock private PluginService mockPluginService; @Mock private HostListProvider mockHostListProvider; @@ -84,7 +86,8 @@ public void init() throws SQLException { when(mockHostListProvider.getClusterId()).thenReturn(CLUSTER_ID); this.storageService = new StorageServiceImpl(mockEventPublisher); - servicesContainer = new FullServicesContainerImpl(this.storageService, mockMonitorService, mockTelemetryFactory); + servicesContainer = new FullServicesContainerImpl( + this.storageService, mockMonitorService, mockConnectionProvider, mockTelemetryFactory); servicesContainer.setPluginService(mockPluginService); } diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPluginTest.java index ff7282483..c7c7bdc1b 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPluginTest.java @@ -45,7 +45,6 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import software.amazon.jdbc.HikariPooledConnectionProvider; import software.amazon.jdbc.HostListProviderService; import software.amazon.jdbc.HostRole; import software.amazon.jdbc.HostSpec; diff --git a/wrapper/src/test/java/software/amazon/jdbc/states/SessionStateServiceImplTests.java b/wrapper/src/test/java/software/amazon/jdbc/states/SessionStateServiceImplTests.java index 8ab28907d..ed391f4cf 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/states/SessionStateServiceImplTests.java +++ b/wrapper/src/test/java/software/amazon/jdbc/states/SessionStateServiceImplTests.java @@ -17,7 +17,6 @@ package software.amazon.jdbc.states; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; diff --git a/wrapper/src/test/java/software/amazon/jdbc/util/ConnectionUrlParserTest.java b/wrapper/src/test/java/software/amazon/jdbc/util/ConnectionUrlParserTest.java index 082d2f78b..056fccd78 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/util/ConnectionUrlParserTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/util/ConnectionUrlParserTest.java @@ -32,7 +32,6 @@ import software.amazon.jdbc.HostRole; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.HostSpecBuilder; -import software.amazon.jdbc.PropertyDefinition; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; class ConnectionUrlParserTest { diff --git a/wrapper/src/test/java/software/amazon/jdbc/util/monitoring/MonitorServiceImplTest.java b/wrapper/src/test/java/software/amazon/jdbc/util/monitoring/MonitorServiceImplTest.java index 38400e9a6..450b494a7 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/util/monitoring/MonitorServiceImplTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/util/monitoring/MonitorServiceImplTest.java @@ -21,8 +21,8 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; @@ -33,7 +33,6 @@ import java.util.Properties; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; @@ -42,35 +41,39 @@ import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.plugin.customendpoint.CustomEndpointMonitorImpl; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; -import software.amazon.jdbc.util.connection.ConnectionService; +import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.events.EventPublisher; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.TelemetryFactory; class MonitorServiceImplTest { + @Mock FullServicesContainer mockServicesContainer; @Mock StorageService mockStorageService; - @Mock ConnectionService mockConnectionService; @Mock ConnectionProvider mockConnectionProvider; @Mock TelemetryFactory mockTelemetryFactory; @Mock TargetDriverDialect mockTargetDriverDialect; @Mock Dialect mockDbDialect; @Mock EventPublisher mockPublisher; + String url = "jdbc:postgresql://somehost/somedb"; + String protocol = "someProtocol"; + Properties props = new Properties(); MonitorServiceImpl spyMonitorService; private AutoCloseable closeable; @BeforeEach - void setUp() { + void setUp() throws SQLException { closeable = MockitoAnnotations.openMocks(this); spyMonitorService = spy(new MonitorServiceImpl(mockPublisher)); doNothing().when(spyMonitorService).initCleanupThread(anyInt()); - - try { - doReturn(mockConnectionService).when(spyMonitorService) - .getConnectionService(any(), any(), any(), any(), any(), any(), any(), any()); - } catch (SQLException e) { - Assertions.fail( - "Encountered exception while stubbing MonitorServiceImpl#getConnectionService: " + e.getMessage()); - } + doReturn(mockServicesContainer).when(spyMonitorService).getNewServicesContainer( + eq(mockStorageService), + eq(mockConnectionProvider), + eq(mockTelemetryFactory), + eq(url), + eq(protocol), + eq(mockTargetDriverDialect), + eq(mockDbDialect), + eq(props)); } @AfterEach @@ -95,12 +98,12 @@ public void testMonitorError_monitorReCreated() throws SQLException, Interrupted mockStorageService, mockTelemetryFactory, mockConnectionProvider, - "jdbc:postgresql://somehost/somedb", - "someProtocol", + url, + protocol, mockTargetDriverDialect, mockDbDialect, - new Properties(), - (connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30) + props, + (mockServicesContainer) -> new NoOpMonitor(30) ); Monitor storedMonitor = spyMonitorService.get(NoOpMonitor.class, key); @@ -139,12 +142,12 @@ public void testMonitorStuck_monitorReCreated() throws SQLException, Interrupted mockStorageService, mockTelemetryFactory, mockConnectionProvider, - "jdbc:postgresql://somehost/somedb", - "someProtocol", + url, + protocol, mockTargetDriverDialect, mockDbDialect, - new Properties(), - (connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30) + props, + (mockServicesContainer) -> new NoOpMonitor(30) ); Monitor storedMonitor = spyMonitorService.get(NoOpMonitor.class, key); @@ -185,12 +188,12 @@ public void testMonitorExpired() throws SQLException, InterruptedException { mockStorageService, mockTelemetryFactory, mockConnectionProvider, - "jdbc:postgresql://somehost/somedb", - "someProtocol", + url, + protocol, mockTargetDriverDialect, mockDbDialect, - new Properties(), - (connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30) + props, + (mockServicesContainer) -> new NoOpMonitor(30) ); Monitor storedMonitor = spyMonitorService.get(NoOpMonitor.class, key); @@ -218,14 +221,14 @@ public void testMonitorMismatch() { mockStorageService, mockTelemetryFactory, mockConnectionProvider, - "jdbc:postgresql://somehost/somedb", - "someProtocol", + url, + protocol, mockTargetDriverDialect, mockDbDialect, - new Properties(), + props, // indicated monitor class is CustomEndpointMonitorImpl, but actual monitor is NoOpMonitor. The monitor // service should detect this and throw an exception. - (connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30) + (mockServicesContainer) -> new NoOpMonitor(30) )); } @@ -248,12 +251,12 @@ public void testRemove() throws SQLException, InterruptedException { mockStorageService, mockTelemetryFactory, mockConnectionProvider, - "jdbc:postgresql://somehost/somedb", - "someProtocol", + url, + protocol, mockTargetDriverDialect, mockDbDialect, - new Properties(), - (connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30) + props, + (mockServicesContainer) -> new NoOpMonitor(30) ); assertNotNull(monitor); @@ -283,12 +286,12 @@ public void testStopAndRemove() throws SQLException, InterruptedException { mockStorageService, mockTelemetryFactory, mockConnectionProvider, - "jdbc:postgresql://somehost/somedb", - "someProtocol", + url, + protocol, mockTargetDriverDialect, mockDbDialect, - new Properties(), - (connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30) + props, + (mockServicesContainer) -> new NoOpMonitor(30) ); assertNotNull(monitor); @@ -300,9 +303,7 @@ public void testStopAndRemove() throws SQLException, InterruptedException { } static class NoOpMonitor extends AbstractMonitor { - protected NoOpMonitor( - MonitorService monitorService, - long terminationTimeoutSec) { + protected NoOpMonitor(long terminationTimeoutSec) { super(terminationTimeoutSec); }