diff --git a/ebean-api/src/main/java/io/ebean/config/DatabaseConfig.java b/ebean-api/src/main/java/io/ebean/config/DatabaseConfig.java index ca778d02c..0a1bb0472 100644 --- a/ebean-api/src/main/java/io/ebean/config/DatabaseConfig.java +++ b/ebean-api/src/main/java/io/ebean/config/DatabaseConfig.java @@ -615,7 +615,7 @@ public class DatabaseConfig { } /** - * Put a service object into configuration such that it can be passed to a plugin. + * Put a service object into configuration such that it can be used by ebean or a plugin. *

* For example, put IgniteConfiguration in to be passed to the Ignite plugin. */ @@ -623,6 +623,28 @@ public class DatabaseConfig { serviceObject.put(key, configObject); } + /** + * Put a service object into configuration such that it can be used by ebean or a plugin. + *

+ * For example, put IgniteConfiguration in to be passed to the Ignite plugin. + * You can also override some SPI objects that should be used for that Database. Currently, the following + * objects are possible. + *

+ */ + public void putServiceObject(Class iface, T configObject) { + serviceObject.put(serviceObjectKey(iface), configObject); + } + /** * Return the service object given the key. */ @@ -631,7 +653,7 @@ public class DatabaseConfig { } /** - * Put a service object into configuration such that it can be passed to a plugin. + * Put a service object into configuration such that it can be used by ebean or a plugin. * *
{@code
    *
@@ -656,7 +678,7 @@ public class DatabaseConfig {
   }
 
   /**
-   * Used by plugins to obtain service objects.
+   * Used by ebean or plugins to obtain service objects.
    *
    * 
{@code
    *
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java
index 2c604ed98..07e3ccaf0 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java
@@ -307,7 +307,10 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
    */
   public void start() {
     if (config.isRunMigration() && TenantMode.DB != config.getTenantMode()) {
-      final AutoMigrationRunner migrationRunner = ServiceUtil.service(AutoMigrationRunner.class);
+      AutoMigrationRunner migrationRunner = config.getServiceObject(AutoMigrationRunner.class);
+      if (migrationRunner == null) {
+        migrationRunner = ServiceUtil.service(AutoMigrationRunner.class);
+      }
       if (migrationRunner == null) {
         throw new IllegalStateException("No AutoMigrationRunner found. Probably ebean-migration is not in the classpath?");
       }
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/InitDataSource.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/InitDataSource.java
index 3eb6dfe3a..7dddf0d12 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/core/InitDataSource.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/InitDataSource.java
@@ -117,7 +117,10 @@ final class InitDataSource {
    * Attach DataSourceAlert via service loader if present.
    */
   private void attachAlert(DataSourceConfig dsConfig) {
-    DataSourceAlertFactory alertFactory = ServiceUtil.service(DataSourceAlertFactory.class);
+    DataSourceAlertFactory alertFactory = config.getServiceObject(DataSourceAlertFactory.class);
+    if (alertFactory == null) {
+      alertFactory = ServiceUtil.service(DataSourceAlertFactory.class);
+    }
     if (alertFactory != null) {
       dsConfig.setAlert(alertFactory.createAlert());
     }
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java
index bce133978..080d95560 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java
@@ -144,7 +144,12 @@ public final class InternalConfiguration {
   }
 
   private  S service(Class cls) {
-    return ServiceUtil.service(cls);
+    S service = config.getServiceObject(cls);
+    if (service != null) {
+      return service;
+    } else {
+      return ServiceUtil.service(cls);
+    }
   }
 
   private List readExternalMapping() {
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java
index c60386f30..9177eed46 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java
@@ -111,7 +111,10 @@ public final class DefaultTypeManager implements TypeManager {
   }
 
   private void loadGeoTypeBinder(DatabaseConfig config) {
-    final GeoTypeProvider provider = ServiceUtil.service(GeoTypeProvider.class);
+    GeoTypeProvider provider = config.getServiceObject(GeoTypeProvider.class);
+    if (provider == null) {
+      provider = ServiceUtil.service(GeoTypeProvider.class);
+    }
     if (provider != null) {
       geoTypeBinder = provider.createBinder(config);
     }
diff --git a/ebean-test/src/test/java/io/ebean/xtest/base/EbeanServerFactory_ServerConfigStart_Test.java b/ebean-test/src/test/java/io/ebean/xtest/base/EbeanServerFactory_ServerConfigStart_Test.java
index e48034d9c..113596331 100644
--- a/ebean-test/src/test/java/io/ebean/xtest/base/EbeanServerFactory_ServerConfigStart_Test.java
+++ b/ebean-test/src/test/java/io/ebean/xtest/base/EbeanServerFactory_ServerConfigStart_Test.java
@@ -4,13 +4,53 @@ import io.ebean.Database;
 import io.ebean.DatabaseFactory;
 import io.ebean.config.DatabaseConfig;
 import io.ebean.event.ServerConfigStartup;
+import io.ebeaninternal.api.SpiLogger;
+import io.ebeaninternal.api.SpiLoggerFactory;
 import org.junit.jupiter.api.Test;
 import org.tests.model.basic.UTDetail;
 
+import java.util.HashSet;
+import java.util.Set;
+
 import static org.assertj.core.api.Assertions.assertThat;
 
 public class EbeanServerFactory_ServerConfigStart_Test {
 
+
+  /**
+   * Demo, how to intercept logging for a certain database.
+   * In conjunction to ServiceLoader, you can add different loggers to different databases
+   */
+  private static class MySpiLoggerFactory implements SpiLoggerFactory {
+    Set loggers = new HashSet<>();
+
+    @Override
+    public SpiLogger create(String name) {
+      loggers.add(name);
+      // just return a dummy here
+      return new SpiLogger() {
+        @Override
+        public boolean isDebug() {
+          return false;
+        }
+
+        @Override
+        public boolean isTrace() {
+          return false;
+        }
+
+        @Override
+        public void debug(String msg) {
+        }
+
+        @Override
+        public void trace(String msg) {
+        }
+      };
+
+    }
+  }
+
   @Test
   public void test() throws InterruptedException {
 
@@ -30,9 +70,13 @@ public class EbeanServerFactory_ServerConfigStart_Test {
     // act - register an instance
     OnStartup onStartup = new OnStartup();
     config.addServerConfigStartup(onStartup);
+    MySpiLoggerFactory loggerFactory = new MySpiLoggerFactory();
+    config.putServiceObject(SpiLoggerFactory.class, loggerFactory);
 
     Database db = DatabaseFactory.create(config);
 
+    assertThat(loggerFactory.loggers).containsExactlyInAnyOrder("io.ebean.SQL", "io.ebean.SUM", "io.ebean.TXN");
+
     assertThat(onStartup.calledWithConfig).isSameAs(config);
     assertThat(OnStartupViaClass.calledWithConfig).isSameAs(config);