From 5b0a3607f655b5d4756987dfbf9baaa678ef8c37 Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Mon, 6 Nov 2023 12:14:27 +1300 Subject: [PATCH 1/2] Fix to return DataSourceBuilder.Settings for getDataSourceConfig() and getReadOnlyDataSourceConfig() That is, existing code using DataSourceConfig has access to the getter methods of DataSourceConfig. The DataSourceBuilder interface only has the setter methods and DataSourceBuilder.Settings has both getters and setter methods. That is, the refactor to extract the DataSourceBuilder interface also split off the getter methods to the DataSourceBuilder.Settings interface (because most of the time when using the builder we only need the setter methods and effectively hiding the getter methods behind the settings() is useful to simplify the API for users). --- .../main/java/io/ebean/DatabaseBuilder.java | 27 +++++++++++++++++-- .../java/io/ebean/config/DatabaseConfig.java | 23 ++++++++++------ .../server/core/DatabasePlatformFactory.java | 2 +- .../server/core/DefaultContainer.java | 2 +- .../server/core/InitDataSource.java | 18 ++++++------- .../server/core/InitDataSourceTest.java | 2 +- .../test/config/AutoConfigureForTesting.java | 4 +-- 7 files changed, 53 insertions(+), 25 deletions(-) diff --git a/ebean-api/src/main/java/io/ebean/DatabaseBuilder.java b/ebean-api/src/main/java/io/ebean/DatabaseBuilder.java index f3350d8581..a9a856bedc 100644 --- a/ebean-api/src/main/java/io/ebean/DatabaseBuilder.java +++ b/ebean-api/src/main/java/io/ebean/DatabaseBuilder.java @@ -20,10 +20,16 @@ import javax.sql.DataSource; import java.time.Clock; import java.util.*; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; import java.util.function.Function; /** * Build a Database instance. + *

+ * Note that {@link #settings()} provides access to read the builder configuration + * (the getters). The DatabaseBuilder only has the methods to set builder configuration + * (the setters) so use {@link #settings()} to access to everything. * *

{@code
  *
@@ -64,6 +70,23 @@ public interface DatabaseBuilder {
    */
   Settings settings();
 
+  /**
+   * Apply configuration to this builder using a lambda.
+   */
+  DatabaseBuilder apply(Consumer applyConfiguration);
+
+  /**
+   * Conditionally apply configuration to this builder via a lambda.
+   *
+   * @param predicate The condition to apply configuration when true.
+   * @param apply     The configuration to apply to this builder.
+   */
+  default DatabaseBuilder alsoIf(BooleanSupplier predicate, Consumer apply) {
+    if (predicate.getAsBoolean()) {
+      apply(apply);
+    }
+    return this;
+  }
   /**
    * Set the name of the Database.
    */
@@ -2598,7 +2621,7 @@ interface Settings extends DatabaseBuilder {
      * Return the configuration to build a DataSource using Ebean's own DataSource
      * implementation.
      */
-    DataSourceBuilder getDataSourceConfig();
+    DataSourceBuilder.Settings getDataSourceConfig();
 
     /**
      * Return true if Ebean should create a DataSource for use with implicit read only transactions.
@@ -2614,7 +2637,7 @@ interface Settings extends DatabaseBuilder {
      * set on this configuration. This means there is actually no need to set any configuration here and we only
      * set configuration for url, username and password etc if it is different from the main DataSource.
      */
-    DataSourceBuilder getReadOnlyDataSourceConfig();
+    DataSourceBuilder.Settings getReadOnlyDataSourceConfig();
 
     /**
      * Return a value used to represent TRUE in the database.
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 f7c6336814..30d72e55e5 100644
--- a/ebean-api/src/main/java/io/ebean/config/DatabaseConfig.java
+++ b/ebean-api/src/main/java/io/ebean/config/DatabaseConfig.java
@@ -27,6 +27,7 @@
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.function.Consumer;
 import java.util.function.Function;
 
 /**
@@ -316,7 +317,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
   /**
    * The data source config.
    */
-  private DataSourceBuilder dataSourceConfig = DataSourceBuilder.create();
+  private DataSourceBuilder.Settings dataSourceConfig = DataSourceBuilder.create().settings();
 
   /**
    * When true create a read only DataSource using readOnlyDataSourceConfig defaulting values from dataSourceConfig.
@@ -329,7 +330,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
   /**
    * Optional configuration for a read only data source.
    */
-  private DataSourceBuilder readOnlyDataSourceConfig = DataSourceBuilder.create();
+  private DataSourceBuilder.Settings readOnlyDataSourceConfig = DataSourceBuilder.create().settings();
 
   /**
    * Optional - the database schema that should be used to own the tables etc.
@@ -560,6 +561,12 @@ public Settings settings() {
     return this;
   }
 
+  @Override
+  public DatabaseBuilder apply(Consumer applyConfiguration) {
+    applyConfiguration.accept(this);
+    return this;
+  }
+
   @Override
   public Clock getClock() {
     return clock;
@@ -1359,13 +1366,13 @@ public DatabaseConfig setReadOnlyDataSource(DataSource readOnlyDataSource) {
   }
 
   @Override
-  public DataSourceBuilder getDataSourceConfig() {
+  public DataSourceBuilder.Settings getDataSourceConfig() {
     return dataSourceConfig;
   }
 
   @Override
   public DatabaseConfig setDataSourceConfig(DataSourceBuilder dataSourceConfig) {
-    this.dataSourceConfig = dataSourceConfig;
+    this.dataSourceConfig = dataSourceConfig.settings();
     return this;
   }
 
@@ -1381,13 +1388,13 @@ public DatabaseConfig setAutoReadOnlyDataSource(boolean autoReadOnlyDataSource)
   }
 
   @Override
-  public DataSourceBuilder getReadOnlyDataSourceConfig() {
+  public DataSourceBuilder.Settings getReadOnlyDataSourceConfig() {
     return readOnlyDataSourceConfig;
   }
 
   @Override
-  public DatabaseConfig setReadOnlyDataSourceConfig(DataSourceBuilder readOnlyDataSourceConfig) {
-    this.readOnlyDataSourceConfig = readOnlyDataSourceConfig;
+  public DatabaseConfig setReadOnlyDataSourceConfig(DataSourceBuilder readOnly) {
+    this.readOnlyDataSourceConfig = readOnly == null ? null : readOnly.settings();
     return this;
   }
 
@@ -2098,7 +2105,7 @@ protected void loadSettings(PropertiesWrapper p) {
     loadAutoTuneSettings(p);
 
     if (dataSourceConfig == null) {
-      dataSourceConfig = DataSourceBuilder.create();
+      dataSourceConfig = DataSourceBuilder.create().settings();
     }
     loadDataSourceSettings(p);
 
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/DatabasePlatformFactory.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/DatabasePlatformFactory.java
index 20a693e6e8..d0b0d17759 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/core/DatabasePlatformFactory.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/DatabasePlatformFactory.java
@@ -48,7 +48,7 @@ public DatabasePlatform create(DatabaseBuilder.Settings config) {
         // choose based on dbName
         return byDatabaseName(config.getDatabasePlatformName());
       }
-      if (config.getDataSourceConfig().settings().isOffline()) {
+      if (config.getDataSourceConfig().isOffline()) {
         throw new PersistenceException("DatabasePlatformName must be specified with offline mode");
       }
       // guess using meta data from driver
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultContainer.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultContainer.java
index 70cb3ce52a..30817020ad 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultContainer.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultContainer.java
@@ -243,7 +243,7 @@ private boolean checkDataSource(DatabaseBuilder.Settings config) {
       return false;
     }
     if (config.getDataSource() == null) {
-      if (config.getDataSourceConfig().settings().isOffline()) {
+      if (config.getDataSourceConfig().isOffline()) {
         // this is ok - offline DDL generation etc
         return false;
       }
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 b40b740e9b..c5fead0da8 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
@@ -49,18 +49,17 @@ private DataSource initReadOnlyDataSource() {
     return roConfig == null ? null : createFromConfig(roConfig, true);
   }
 
-  DataSourceBuilder readOnlyConfig() {
+  DataSourceBuilder.Settings readOnlyConfig() {
     var roConfig = config.getReadOnlyDataSourceConfig();
     if (roConfig == null) {
       // it has explicitly been set to null, not expected but ok
       return null;
     }
-    var roSettings = roConfig.settings();
-    if (urlSet(roSettings.getUrl())) {
+    if (urlSet(roConfig.getUrl())) {
       return roConfig;
     }
     // convenient alternate place to set the read-only url
-    final String readOnlyUrl = config.getDataSourceConfig().settings().getReadOnlyUrl();
+    final String readOnlyUrl = config.getDataSourceConfig().getReadOnlyUrl();
     if (urlSet(readOnlyUrl)) {
       roConfig.url(readOnlyUrl);
       return roConfig;
@@ -77,23 +76,22 @@ private boolean urlSet(String url) {
     return url != null && !"none".equalsIgnoreCase(url) && !url.trim().isEmpty();
   }
 
-  private DataSource createFromConfig(DataSourceBuilder dsConfig, boolean readOnly) {
+  private DataSource createFromConfig(DataSourceBuilder.Settings dsConfig, boolean readOnly) {
     if (dsConfig == null) {
       throw new PersistenceException("No  DataSourceBuilder defined for " + config.getName());
     }
-    var dsSettings = dsConfig.settings();
-    if (dsSettings.isOffline()) {
+    if (dsConfig.isOffline()) {
       if (config.getDatabasePlatformName() == null) {
         throw new PersistenceException("You MUST specify a DatabasePlatformName on DatabaseConfig when offline");
       }
     }
 
-    attachAlert(dsSettings);
-    attachListener(dsSettings);
+    attachAlert(dsConfig);
+    attachListener(dsConfig);
 
     if (readOnly) {
       // setup to use AutoCommit such that we skip explicit commit
-      var mainSettings = config.getDataSourceConfig().settings();
+      var mainSettings = config.getDataSourceConfig();
       dsConfig.autoCommit(true);
       dsConfig.readOnly(true);
       dsConfig.setDefaults(mainSettings);
diff --git a/ebean-core/src/test/java/io/ebeaninternal/server/core/InitDataSourceTest.java b/ebean-core/src/test/java/io/ebeaninternal/server/core/InitDataSourceTest.java
index 824477d43b..3d77ca813d 100644
--- a/ebean-core/src/test/java/io/ebeaninternal/server/core/InitDataSourceTest.java
+++ b/ebean-core/src/test/java/io/ebeaninternal/server/core/InitDataSourceTest.java
@@ -127,7 +127,7 @@ public void readOnlyConfig_when_readOnlyUrlSetOnMain_withNoneNone() {
   @Test
   public void readOnlyConfig_when_urlSet_2() {
     DatabaseConfig config = new DatabaseConfig();
-    config.settings().getReadOnlyDataSourceConfig().url("foo");
+    config.getReadOnlyDataSourceConfig().url("foo");
 
     final DataSourceBuilder roConfig = new InitDataSource(config).readOnlyConfig();
     assertNotNull(roConfig);
diff --git a/ebean-test/src/main/java/io/ebean/test/config/AutoConfigureForTesting.java b/ebean-test/src/main/java/io/ebean/test/config/AutoConfigureForTesting.java
index 668eb86bfa..be41a5e222 100644
--- a/ebean-test/src/main/java/io/ebean/test/config/AutoConfigureForTesting.java
+++ b/ebean-test/src/main/java/io/ebean/test/config/AutoConfigureForTesting.java
@@ -71,11 +71,11 @@ public void postConfigure(DatabaseBuilder builder) {
     }
   }
 
-  private void makeV1Compatible(DataSourceBuilder ds) {
+  private void makeV1Compatible(DataSourceBuilder.Settings ds) {
     if (ds == null) {
       return;
     }
-    String url = ds.settings().getUrl();
+    String url = ds.getUrl();
     if (url == null || !url.startsWith("jdbc:h2:")) {
       return;
     }

From a2551ce71851452c560354c043673391bcad7ff8 Mon Sep 17 00:00:00 2001
From: Rob Bygrave 
Date: Mon, 6 Nov 2023 12:50:14 +1300
Subject: [PATCH 2/2] Bump ebean-datasource to 8.9

---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 3ecc6faf3d..acf5f046ba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -52,7 +52,7 @@
     1.2
     13.11.1
     7.1
-    8.8
+    8.9
     13.24.0
     13.24.0
     false