From c9fdc1e6b1ca5adcf959c545bd110f9d0288124e Mon Sep 17 00:00:00 2001 From: Greg Meyer Date: Mon, 13 Jun 2022 10:40:59 -0500 Subject: [PATCH] Adding logic to flex the MySQL r2dbc connection sting based on classpath (#73) * Adding logic to flex the MySQL jdbc and r2dbc connection sting based on classpath This PR is related to issue #72. Co-authored-by: gm2552 --- README.md | 6 ++-- pom.xml | 7 ++++ .../MySqlBindingsPropertiesProcessor.java | 36 +++++++++++++++++-- .../MySqlBindingsPropertiesProcessorTest.java | 4 +-- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ed368c1..eae573f 100644 --- a/README.md +++ b/README.md @@ -168,12 +168,14 @@ Disable Property: `org.springframework.cloud.bindings.boot.mysql.enable` | -------- | ------------------ | `spring.datasource.driver-class-name` | `org.mariadb.jdbc.Driver` or `com.mysql.cj.jdbc.Driver` depending on classpath | `spring.datasource.password` | `{password}` -| `spring.datasource.url` | `{jdbc-url}` or if not set then `jdbc:mysql://{host}:{port}/{database}` +| `spring.datasource.url` | `{jdbc-url}` or if not set then `jdbc:mysql://{host}:{port}/{database}` or `jdbc:mariadb://{host}:{port}/{database}` depending on classpath | `spring.datasource.username` | `{username}` -| `spring.r2dbc.url` | `{r2dbc-url}` or if not set then `r2dbc:mysql://{host}:{port}/{database}` +| `spring.r2dbc.url` | `{r2dbc-url}` or if not set then `r2dbc:mysql://{host}:{port}/{database}` or `r2dbc:mariadb//{host}:{port}/{database}` depending on classpath | `spring.r2dbc.password` | `{password}` | `spring.r2dbc.username` | `{username}` +**Note:** Libraries on the classpath are examined for the purpose of evaluating the appropriate `jdbc` and `r2dbc` URLs. The existence of both MySQL and MariaDB libraries on the classpath is not supported and may lead to non-deterministic results. + ### Neo4J Type: `neo4j` Disable Property: `org.springframework.cloud.bindings.boot.neo4j.enable` diff --git a/pom.xml b/pom.xml index e8447b7..3b582f3 100644 --- a/pom.xml +++ b/pom.xml @@ -26,6 +26,7 @@ 1.8 3.0.2 + 1.0.3 2.3.3.RELEASE @@ -69,6 +70,12 @@ mariadb-java-client test + + org.mariadb + r2dbc-mariadb + ${mariadb-r2dbc.version} + test + org.mockito mockito-core diff --git a/src/main/java/org/springframework/cloud/bindings/boot/MySqlBindingsPropertiesProcessor.java b/src/main/java/org/springframework/cloud/bindings/boot/MySqlBindingsPropertiesProcessor.java index 39174c3..12b136d 100644 --- a/src/main/java/org/springframework/cloud/bindings/boot/MySqlBindingsPropertiesProcessor.java +++ b/src/main/java/org/springframework/cloud/bindings/boot/MySqlBindingsPropertiesProcessor.java @@ -36,6 +36,16 @@ public final class MySqlBindingsPropertiesProcessor implements BindingsPropertie **/ public static final String TYPE = "mysql"; + /** + * MySQL connection protocol constant. + */ + private static final String MYSQL_PROTOCOL = "mysql"; + + /** + * MariaDB connection protocol constant. + */ + private static final String MARIADB_PROTOCOL = "mariadb"; + @Override public void process(Environment environment, Bindings bindings, Map properties) { if (!isTypeEnabled(environment, TYPE)) { @@ -49,7 +59,7 @@ public final class MySqlBindingsPropertiesProcessor implements BindingsPropertie map.from("username").to("spring.datasource.username"); map.from("password").to("spring.datasource.password"); map.from("host", "port", "database").to("spring.datasource.url", - (host, port, database) -> String.format("jdbc:mysql://%s:%s/%s", host, port, database)); + (host, port, database) -> String.format("jdbc:%s://%s:%s/%s", evalProtocol(), host, port, database)); // jdbcURL takes precedence map.from("jdbc-url").to("spring.datasource.url"); @@ -68,12 +78,34 @@ public final class MySqlBindingsPropertiesProcessor implements BindingsPropertie //r2dbc properties map.from("password").to("spring.r2dbc.password"); map.from("host", "port", "database").to("spring.r2dbc.url", - (host, port, database) -> String.format("r2dbc:mysql://%s:%s/%s", host, port, database)); + (host, port, database) -> String.format("r2dbc:%s://%s:%s/%s", evalProtocol(), host, port, database)); map.from("username").to("spring.r2dbc.username"); // r2dbcURL takes precedence map.from("r2dbc-url").to("spring.r2dbc.url"); }); } + + private String evalProtocol() + { + // Default to "mysql" + String connectionProtocol = MYSQL_PROTOCOL; + + /* Starting with Spring Boot 2.7.0, the previous MySQL r2dbc driver is no longer supported and + * documentation suggests using the MariaDB R2DBC driver as an alternative. Some versions + * of the MariaDB R2DBC driver do not support "mysql" as part of the connection + * protocol; "mariadb" should be used instead when the MariaDB R2DBC driver class is on + * the classpath. + */ + + try { + Class.forName("org.mariadb.r2dbc.MariadbConnection"); + connectionProtocol = MARIADB_PROTOCOL; + } + catch (ClassNotFoundException ignored) { + } + + return connectionProtocol; + } } diff --git a/src/test/java/org/springframework/cloud/bindings/boot/MySqlBindingsPropertiesProcessorTest.java b/src/test/java/org/springframework/cloud/bindings/boot/MySqlBindingsPropertiesProcessorTest.java index 3de73bd..52e0acb 100644 --- a/src/test/java/org/springframework/cloud/bindings/boot/MySqlBindingsPropertiesProcessorTest.java +++ b/src/test/java/org/springframework/cloud/bindings/boot/MySqlBindingsPropertiesProcessorTest.java @@ -54,7 +54,7 @@ final class MySqlBindingsPropertiesProcessorTest { assertThat(properties) .containsEntry("spring.datasource.driver-class-name", "org.mariadb.jdbc.Driver") .containsEntry("spring.datasource.password", "test-password") - .containsEntry("spring.datasource.url", "jdbc:mysql://test-host:test-port/test-database") + .containsEntry("spring.datasource.url", "jdbc:mariadb://test-host:test-port/test-database") .containsEntry("spring.datasource.username", "test-username"); } @@ -81,7 +81,7 @@ final class MySqlBindingsPropertiesProcessorTest { new MySqlBindingsPropertiesProcessor().process(environment, bindings, properties); assertThat(properties) .containsEntry("spring.r2dbc.password", "test-password") - .containsEntry("spring.r2dbc.url", "r2dbc:mysql://test-host:test-port/test-database") + .containsEntry("spring.r2dbc.url", "r2dbc:mariadb://test-host:test-port/test-database") .containsEntry("spring.r2dbc.username", "test-username"); }