diff --git a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/ConnectionNotifier.java b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/ConnectionNotifier.java
deleted file mode 100644
index 58a6c8e88..000000000
--- a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/ConnectionNotifier.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2023 - Manifold Systems LLC
- *
- * 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 manifold.sql.rt.api;
-
-import manifold.rt.api.util.ServiceUtil;
-import manifold.util.concurrent.LocklessLazyVar;
-
-import java.sql.Connection;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Notifies implementors immediately after a JDBC connection is established. Useful for testing, debugging, and connection
- * related environment setup.
- *
- * Note, implement {@link manifold.sql.rt.api.ConnectionProvider} to control the Connection itself.
- */
-public interface ConnectionNotifier
-{
- LocklessLazyVar> PROVIDERS =
- LocklessLazyVar.make( () -> {
- Set registered = new HashSet<>();
- ServiceUtil.loadRegisteredServices( registered, ConnectionNotifier.class, ConnectionNotifier.class.getClassLoader() );
- return registered;
- } );
-
- /**
- * Invoked immediately after a JDBC connection is established.
- */
- void init( Connection c );
-}
diff --git a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/ConnectionProvider.java b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/ConnectionProvider.java
index 2463f4823..b6cf1fa64 100644
--- a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/ConnectionProvider.java
+++ b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/ConnectionProvider.java
@@ -16,38 +16,14 @@
package manifold.sql.rt.api;
-import manifold.rt.api.util.ServiceUtil;
-import manifold.util.concurrent.LocklessLazyVar;
-
import java.sql.Connection;
-import java.sql.Driver;
import java.sql.SQLException;
-import java.util.HashSet;
-import java.util.Set;
/**
* Implementors provide JDBC connections for all manifold-sql JDBC operations.
*/
public interface ConnectionProvider
{
- LocklessLazyVar> PROVIDERS =
- LocklessLazyVar.make( () -> {
- // first, ensure jdbc drivers are loaded
- Set drivers = new HashSet<>();
- ServiceUtil.loadRegisteredServices( drivers, Driver.class, ConnectionProvider.class.getClassLoader() );
-
- Set registered = new HashSet<>();
- ServiceUtil.loadRegisteredServices( registered, ConnectionProvider.class, ConnectionProvider.class.getClassLoader() );
- return registered;
- } );
-
- static ConnectionProvider findFirst()
- {
- return ConnectionProvider.PROVIDERS.get().stream()
- .findFirst()
- .orElseThrow( () -> new RuntimeException( "Could not find SQL connection provider" ) );
- }
-
/**
* Provides a JDBC connection corresponding with the {@code configName} {@link DbConfig} and optional {@code classContext}.
* A standard implementation sources the {@code configName} DbConfig in the following order:
diff --git a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/CrudProvider.java b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/CrudProvider.java
index 0fd4acb89..b52ed47f1 100644
--- a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/CrudProvider.java
+++ b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/CrudProvider.java
@@ -16,44 +16,12 @@
package manifold.sql.rt.api;
-import manifold.rt.api.util.ServiceUtil;
-import manifold.util.concurrent.LocklessLazyVar;
-
import java.sql.Connection;
-import java.util.*;
-import java.util.function.Supplier;
public interface CrudProvider
{
- LocklessLazyVar> PROVIDERS =
- LocklessLazyVar.make( () -> {
- Set registered = new HashSet<>();
- ServiceUtil.loadRegisteredServices( registered, CrudProvider.class, CrudProvider.class.getClassLoader() );
- return registered;
- } );
-
- LocklessLazyVar BY_PRIORITY =
- LocklessLazyVar.make( () ->
- PROVIDERS.get().stream().max( Comparator.comparingInt( CrudProvider::getPriority ) )
- .orElseThrow( () -> new IllegalStateException() ) );
-
- static CrudProvider instance()
- {
- return BY_PRIORITY.get();
- }
-
-
void create( Connection c, UpdateContext ctx );
T read( QueryContext ctx );
void update( Connection c, UpdateContext ctx );
void delete( Connection c, UpdateContext ctx );
-
- /**
- * Greater = higher priority. Higher priority overrides lower. Default implementations are lowest priority. They can be
- * overridden.
- */
- default int getPriority()
- {
- return Integer.MIN_VALUE;
- }
}
diff --git a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/DbConfigProvider.java b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/DbConfigProvider.java
index b7660e992..99e9d2cb0 100644
--- a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/DbConfigProvider.java
+++ b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/DbConfigProvider.java
@@ -16,20 +16,7 @@
package manifold.sql.rt.api;
-import manifold.rt.api.util.ServiceUtil;
-import manifold.util.concurrent.LocklessLazyVar;
-
-import java.util.HashSet;
-import java.util.Set;
-
public interface DbConfigProvider
{
- LocklessLazyVar> PROVIDERS =
- LocklessLazyVar.make( () -> {
- Set registered = new HashSet<>();
- ServiceUtil.loadRegisteredServices( registered, DbConfigProvider.class, DbConfigProvider.class.getClassLoader() );
- return registered;
- } );
-
DbConfig loadDbConfig( String configName, Class> ctx );
}
diff --git a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/DbLocationProvider.java b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/DbLocationProvider.java
index 4cc8b4993..84d5facc8 100644
--- a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/DbLocationProvider.java
+++ b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/DbLocationProvider.java
@@ -18,25 +18,17 @@
import manifold.api.fs.IFile;
import manifold.api.util.cache.FqnCache;
-import manifold.rt.api.util.ServiceUtil;
-import manifold.util.concurrent.LocklessLazyVar;
-import java.util.HashSet;
-import java.util.Set;
import java.util.function.Function;
+/**
+ * Note, implementers must chain/forward to the default provider to fall back on existing behavior.
+ */
public interface DbLocationProvider
{
String PROVIDED = "#";
Object UNHANDLED = new Object() {};
- LocklessLazyVar> PROVIDERS =
- LocklessLazyVar.make( () -> {
- Set registered = new HashSet<>();
- ServiceUtil.loadRegisteredServices( registered, DbLocationProvider.class, DbLocationProvider.class.getClassLoader() );
- return registered;
- } );
-
enum Mode {CompileTime, DesignTime, Runtime, Unknown}
Object getLocation( Function> resByExt, Mode mode, String tag, String... args );
diff --git a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/Dependencies.java b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/Dependencies.java
new file mode 100644
index 000000000..b1e927bab
--- /dev/null
+++ b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/Dependencies.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 - Manifold Systems LLC
+ *
+ * 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 manifold.sql.rt.api;
+
+import manifold.rt.api.util.ServiceUtil;
+import manifold.sql.rt.config.DefaultDependencies;
+import manifold.util.concurrent.LocklessLazyVar;
+
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public interface Dependencies
+{
+ LocklessLazyVar> PROVIDERS =
+ LocklessLazyVar.make( () -> {
+ Set registered = new LinkedHashSet<>();
+ ServiceUtil.loadRegisteredServices( registered, Dependencies.class, Dependencies.class.getClassLoader() );
+ return registered;
+ } );
+
+ static Dependencies instance()
+ {
+ if( PROVIDERS.get().isEmpty() )
+ {
+ throw new RuntimeException( "Could not find Dependencies service provider" );
+ }
+
+ Dependencies result = null;
+ for( Dependencies dependencies : PROVIDERS.get() )
+ {
+ // favor non-default dependencies
+ if( result == null || result instanceof DefaultDependencies )
+ {
+ result = dependencies;
+ }
+ }
+ return result;
+ }
+
+ DbConfigProvider getDbConfigProvider();
+
+ ConnectionProvider getConnectionProvider();
+
+ CrudProvider getCrudProvider();
+
+ DbLocationProvider getDbLocationProvider();
+
+ TxScopeProvider getTxScopeProvider();
+
+ ValueAccessorProvider getValueAccessorProvider();
+
+ T fetch( Class cls );
+}
diff --git a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/Result.java b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/Result.java
index bdcc3b80a..fba6b86bd 100644
--- a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/Result.java
+++ b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/Result.java
@@ -56,10 +56,11 @@ private void rip( ResultSet resultSet, Function ctx, String sqlQuery )
@SuppressWarnings( "unused" )
public Result run()
{
- ConnectionProvider cp = ConnectionProvider.findFirst();
+ ConnectionProvider cp = Dependencies.instance().getConnectionProvider();
try( Connection c = cp.getConnection( _ctx.getConfigName(), _ctx.getQueryClass() ) )
{
- for( ConnectionNotifier p : ConnectionNotifier.PROVIDERS.get() )
- {
- p.init( c );
- }
-
try( PreparedStatement ps = c.prepareStatement( _sqlQuery ) )
{
setParameters( ps );
try( ResultSet resultSet = ps.executeQuery() )
{
- return new Result( _ctx.getTxScope(), resultSet, _ctx.getRowMaker() );
+ return new Result<>( _ctx.getTxScope(), resultSet, _ctx.getRowMaker() );
}
}
}
@@ -60,9 +55,10 @@ public Result run()
private void setParameters( PreparedStatement ps ) throws SQLException
{
int i = 0;
+ ValueAccessorProvider accProvider = Dependencies.instance().getValueAccessorProvider();
for( Object param : _ctx.getParams().values() )
{
- ValueAccessor accessor = ValueAccessor.get( _ctx.getJdbcParamTypes()[i] );
+ ValueAccessor accessor = accProvider.get( _ctx.getJdbcParamTypes()[i] );
accessor.setParameter( ps, ++i, param );
}
}
diff --git a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/TxScopeProvider.java b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/TxScopeProvider.java
index 2a19d376a..43316a881 100644
--- a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/TxScopeProvider.java
+++ b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/TxScopeProvider.java
@@ -16,42 +16,7 @@
package manifold.sql.rt.api;
-import manifold.rt.api.util.ServiceUtil;
-import manifold.util.concurrent.LocklessLazyVar;
-
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.Set;
-
public interface TxScopeProvider
{
- LocklessLazyVar> PROVIDERS =
- LocklessLazyVar.make( () -> {
- Set registered = new HashSet<>();
- ServiceUtil.loadRegisteredServices( registered, TxScopeProvider.class, TxScopeProvider.class.getClassLoader() );
- return registered;
- } );
-
- LocklessLazyVar BY_PRIORITY =
- LocklessLazyVar.make( () ->
- PROVIDERS.get().stream().max( Comparator.comparingInt( TxScopeProvider::getPriority ) )
- .orElseThrow( () -> new IllegalStateException( "No " + TxScopeProvider.class.getSimpleName() + "'s found." ) ) );
-
- static TxScope newScope( Class extends SchemaType> schemaClass )
- {
- return BY_PRIORITY.get().create( schemaClass );
- }
-
-
- TxScope create( Class extends SchemaType> schemaClass );
-
-
- /**
- * Greater = higher priority. Higher priority overrides lower. Default implementations are lowest priority. They can be
- * overridden.
- */
- default int getPriority()
- {
- return Integer.MIN_VALUE;
- }
+ TxScope newScope( Class extends SchemaType> schemaClass );
}
diff --git a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/ValueAccessor.java b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/ValueAccessor.java
index 29dba775d..c93a5bc51 100644
--- a/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/ValueAccessor.java
+++ b/manifold-deps-parent/manifold-sql-rt/src/main/java/manifold/sql/rt/api/ValueAccessor.java
@@ -16,23 +16,13 @@
package manifold.sql.rt.api;
-import manifold.rt.api.util.ServiceUtil;
-import manifold.util.concurrent.LocklessLazyVar;
-
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
/**
- * Each implementation of this interface handles a JDBC type from {@link java.sql.Types} and must be registered as a Java
- * Service Provider. The value returned from {@link #getJdbcType()} indicates the JDBC type handled by the SPI implementation.
- * Manifold provides default implementations that are suitable for most use-cases, however these implementations can be
- * overridden by custom implementations, a higher priority from {@link #getPriority()} overrides lower priority implementations.
- * All Manifold implementations default to the lowest priority.
+ * The value returned from {@link #getJdbcType()} indicates the JDBC type handled by the implementation.
+ * Manifold provides default implementations that are suitable for most use-cases.
*
* This interface performs the following:
* - resolves the Java type corresponding with the JDBC type from {@link java.sql.Types}
@@ -42,47 +32,11 @@
*/
public interface ValueAccessor
{
- LocklessLazyVar> ACCESSORS =
- LocklessLazyVar.make( () -> {
- Set registered = new HashSet<>();
- ServiceUtil.loadRegisteredServices( registered, ValueAccessor.class, ValueAccessor.class.getClassLoader() );
- return registered;
- } );
-
- LocklessLazyVar