Skip to content

Commit

Permalink
feat(jdbc): Remove MySQL ConnectorJ and use MariaDb instead (#2502)
Browse files Browse the repository at this point in the history
* feat(jdbc): Remove MySQL ConnectorJ and use MariaDb instead

* feat(jdbc): Fix license text

* feat(jdbc): Refacotr Using variables

---------

Co-authored-by: Ev <[email protected]>
  • Loading branch information
johnBgood and ev-codes authored May 8, 2024
1 parent 67361cc commit fd3a16d
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 36 deletions.
19 changes: 13 additions & 6 deletions connectors/jdbc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,25 @@
<version>12.6.1.jre11</version>
</dependency>

<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.4.0</version>
</dependency>

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.3</version>
</dependency>

<!-- Mariadb is used because of an issue with the MySQL ConnectorJ licence (GPL). We're not mentioning Mariadb in our docs -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.3.3</version>
</dependency>

<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

public enum SupportedDatabase {
MSSQL("com.microsoft.sqlserver.jdbc.SQLServerDriver", "jdbc:sqlserver://"),
MYSQL("com.mysql.cj.jdbc.Driver", "jdbc:mysql://"),
MYSQL("org.mariadb.jdbc.Driver", "jdbc:mysql://"),
POSTGRESQL("org.postgresql.Driver", "jdbc:postgresql://");

private final String driverClassName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

import io.camunda.connector.api.error.ConnectorException;
import io.camunda.connector.jdbc.model.request.JdbcRequest;
import io.camunda.connector.jdbc.model.request.SupportedDatabase;
import io.camunda.connector.jdbc.model.request.connection.JdbcConnection;
import java.net.URISyntaxException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
Expand All @@ -20,20 +22,41 @@ public class ConnectionHelper {
private static final Logger LOG = LoggerFactory.getLogger(ConnectionHelper.class);

public static Connection openConnection(JdbcRequest request) {
SupportedDatabase database = request.database();
String driverClassName = database.getDriverClassName();
try {
LOG.debug("Executing JDBC request: {}", request);
LOG.debug("Loading JDBC driver: {}", request.database().getDriverClassName());
Class.forName(request.database().getDriverClassName());
LOG.debug("Loading JDBC driver: {}", driverClassName);
Class.forName(driverClassName);
JdbcConnection connection = request.connection();
Connection conn =
DriverManager.getConnection(
connection.getConnectionString(request.database()), connection.getProperties());
LOG.debug("Connection established for Database {}: {}", request.database(), conn);
ensureMySQLCompatibleUrl(connection.getConnectionString(database), database),
connection.getProperties());
LOG.debug("Connection established for Database {}: {}", database, conn);
return conn;
} catch (ClassNotFoundException e) {
throw new ConnectorException("Cannot find class: " + request.database().getDriverClassName());
throw new ConnectorException("Cannot find class: " + driverClassName);
} catch (URISyntaxException e) {
throw new ConnectorException("Cannot parse the Database connection URL: " + e.getMessage());
} catch (SQLException e) {
throw new ConnectorException("Cannot create the Database connection: " + e.getMessage());
}
}

/**
* Ensure MySQL compatibility as we are using MariaDB driver for MySQL.
*
* @return Properties with permitMysqlScheme set to true if the database is MySQL.
* @see <a
* href="https://mariadb.com/kb/en/about-mariadb-connector-j/#jdbcmysql-scheme-compatibility">Compatibility
* details</a>
*/
private static String ensureMySQLCompatibleUrl(String url, SupportedDatabase database)
throws URISyntaxException {
if (database == SupportedDatabase.MYSQL) {
return ConnectionParameterHelper.addQueryParameterToURL(url, "permitMysqlScheme");
}
return url;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. Licensed under a proprietary license.
* See the License.txt file for more information. You may not use this file
* except in compliance with the proprietary license.
*/
package io.camunda.connector.jdbc.utils;

import java.net.URI;
import java.net.URISyntaxException;

/**
* Helper class to add parameters to a URL. Parameters values can be added to the URL as well, but
* it is optional.
*
* @see ConnectionParameterHelperTest for usage examples.
*/
public class ConnectionParameterHelper {

public static String addQueryParameterToURL(String urlString, String paramName)
throws URISyntaxException {
return addQueryParameterToURL(urlString, paramName, null);
}

public static String addQueryParameterToURL(String urlString, String paramName, String paramValue)
throws URISyntaxException {
URI uri = new URI(urlString);
// Check if the URL already has query parameters
int queryParamsIndex = urlString.indexOf('?');
String query;
if (queryParamsIndex == -1) {
// No query parameters
query = "?";
} else {
// Query parameters already exist let's add the new one
query = "&";
}
query += paramName;
// Value is optional
if (paramValue != null) {
query += "=" + paramValue;
}
// jdbc:mysql//localhost:3306?paramName=paramValue for instance is not detected as a regular
// URI,
// so we need to reconstruct the URI using the scheme and the scheme specific part
return new URI(uri.getScheme() + ":" + uri.getSchemeSpecificPart() + query).toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,13 @@ public class ConnectionStringHelper {
public static String buildConnectionString(
SupportedDatabase database, DetailedConnection connection) {
return switch (database) {
case MYSQL -> buildMySqlConnectionString(database, connection);
case POSTGRESQL -> buildPostgresConnectionString(database, connection);
case MYSQL, POSTGRESQL -> buildCommonConnectionString(database, connection);
case MSSQL -> buildMssqlConnectionString(database, connection);
default -> throw new ConnectorException("Unsupported database: " + database);
};
}

private static String buildMySqlConnectionString(
SupportedDatabase database, DetailedConnection connection) {
String host = connection.host();
String port = connection.port();
String username = connection.username();
String password = connection.password();
String databaseName = connection.databaseName();
String authentication = "";
if (username != null && !username.isEmpty()) {
authentication += username;
if (password != null && !password.isEmpty()) {
authentication += ":" + password + "@";
}
}
String connectionString = database.getUrlSchema() + authentication + host + ":" + port;
if (databaseName != null && !databaseName.isEmpty()) {
connectionString += "/" + databaseName;
}
return connectionString;
}

private static String buildPostgresConnectionString(
private static String buildCommonConnectionString(
SupportedDatabase database, DetailedConnection connection) {
String host = connection.host();
String port = connection.port();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. Licensed under a proprietary license.
* See the License.txt file for more information. You may not use this file
* except in compliance with the proprietary license.
*/
package io.camunda.connector.jdbc.utils;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

public class ConnectionParameterHelperTest {
@Test
void shouldCreateQueryParameters_whenNoExistingQueryParameters() throws Exception {
String urlString = "jdbc:mysql//localhost:3306";
String paramName = "paramName";
String paramValue = "paramValue";
String result =
ConnectionParameterHelper.addQueryParameterToURL(urlString, paramName, paramValue);
assertThat(result).isEqualTo(urlString + "?paramName=paramValue");
}

@Test
void shouldNotCreateQueryParameters_whenExistingQueryParameters() throws Exception {
String urlString = "jdbc:mysql//localhost:3306?existingParam=existingValue";
String paramName = "paramName";
String paramValue = "paramValue";
String result =
ConnectionParameterHelper.addQueryParameterToURL(urlString, paramName, paramValue);
assertThat(result).isEqualTo(urlString + "&paramName=paramValue");
}

@Test
void shouldCreateQueryParameters_whenNoParamValue() throws Exception {
String urlString = "jdbc:mysql//localhost:3306";
String paramName = "paramName";
String result = ConnectionParameterHelper.addQueryParameterToURL(urlString, paramName);
assertThat(result).isEqualTo(urlString + "?paramName");
}

@Test
void shouldCreateQueryParameters_whenNoParamValueAndExistingQueryParameters() throws Exception {
String urlString = "jdbc:mysql//localhost:3306?existingParam=existingValue";
String paramName = "paramName";
String result = ConnectionParameterHelper.addQueryParameterToURL(urlString, paramName);
assertThat(result).isEqualTo(urlString + "&paramName");
}

@Test
void shouldCreateQueryParametersAfterPath_whenQueryPathExistsAndNoParamValue() throws Exception {
String urlString = "jdbc:mysql//localhost:3306/database";
String paramName = "paramName";
String result = ConnectionParameterHelper.addQueryParameterToURL(urlString, paramName);
assertThat(result).isEqualTo(urlString + "?paramName");
}

@Test
void shouldCreateQueryParametersAfterPath_whenQueryPathExistsAndQueryParametersExist()
throws Exception {
String urlString = "jdbc:mysql//localhost:3306/database?existingParam=existingValue";
String paramName = "paramName";
String result = ConnectionParameterHelper.addQueryParameterToURL(urlString, paramName);
assertThat(result).isEqualTo(urlString + "&paramName");
}

@Test
void shouldCreateQueryParametersAfterPath_whenEmptyPath() throws Exception {
String urlString = "jdbc:mysql//localhost:3306/";
String paramName = "paramName";
String result = ConnectionParameterHelper.addQueryParameterToURL(urlString, paramName);
assertThat(result).isEqualTo(urlString + "?paramName");
}
}

0 comments on commit fd3a16d

Please sign in to comment.