diff --git a/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlConnection.java b/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlConnection.java index 3fae417c7..178a34171 100644 --- a/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlConnection.java +++ b/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlConnection.java @@ -53,7 +53,7 @@ public class MySqlConnection extends JdbcConnection { private static final String SQL_SHOW_SESSION_VARIABLE_SSL_VERSION = "SHOW SESSION STATUS LIKE 'Ssl_version'"; private static final String QUOTED_CHARACTER = "`"; - protected static final String URL_PATTERN = "jdbc:mysql://${hostname}:${port}/?useInformationSchema=true&nullCatalogMeansCurrent=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=CONVERT_TO_NULL&connectTimeout=${connectTimeout}"; + protected static final String URL_PATTERN = "${protocol}://${hostname}:${port}/?useInformationSchema=true&nullCatalogMeansCurrent=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=CONVERT_TO_NULL&connectTimeout=${connectTimeout}"; private final Map originalSystemProperties = new HashMap<>(); private final MySqlConnectionConfiguration connectionConfig; @@ -498,6 +498,7 @@ public MySqlConnectionConfiguration(Configuration config) { final Configuration dbConfig = config .edit() .withDefault(MySqlConnectorConfig.PORT, MySqlConnectorConfig.PORT.defaultValue()) + .withDefault(MySqlConnectorConfig.JDBC_PROTOCOL, MySqlConnectorConfig.JDBC_PROTOCOL.defaultValue()) .build() .subset(DATABASE_CONFIG_PREFIX, true) .merge(config.subset(DRIVER_CONFIG_PREFIX, true)); @@ -532,8 +533,10 @@ public MySqlConnectionConfiguration(Configuration config) { .without("queryInterceptors"); this.jdbcConfig = JdbcConfiguration.adapt(jdbcConfigBuilder.build()); - String driverClassName = this.jdbcConfig.getString(MySqlConnectorConfig.JDBC_DRIVER); - factory = JdbcConnection.patternBasedFactory(MySqlConnection.URL_PATTERN, driverClassName, getClass().getClassLoader()); + String driverClassName = this.config.getString(MySqlConnectorConfig.JDBC_DRIVER); + Field protocol = MySqlConnectorConfig.JDBC_PROTOCOL; + + factory = JdbcConnection.patternBasedFactory(MySqlConnection.URL_PATTERN, driverClassName, getClass().getClassLoader(), protocol); } private static String determineConnectionTimeZone(final Configuration dbConfig) { diff --git a/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlConnectorConfig.java b/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlConnectorConfig.java index 38ab7e695..81670c9cc 100644 --- a/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlConnectorConfig.java +++ b/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlConnectorConfig.java @@ -614,8 +614,8 @@ public static SecureConnectionMode parse(String value, String defaultValue) { public static final Field TABLES_IGNORE_BUILTIN = RelationalDatabaseConnectorConfig.TABLE_IGNORE_BUILTIN .withDependents(DATABASE_INCLUDE_LIST_NAME); - public static final Field JDBC_DRIVER = Field.create("database.jdbc.driver") - .withDisplayName("Jdbc Driver Class Name") + public static final Field JDBC_DRIVER = Field.create(DATABASE_CONFIG_PREFIX + "jdbc.driver") + .withDisplayName("JDBC Driver Class Name") .withType(Type.CLASS) .withGroup(Field.createGroupEntry(Field.Group.CONNECTION, 41)) .withWidth(Width.MEDIUM) @@ -624,6 +624,15 @@ public static SecureConnectionMode parse(String value, String defaultValue) { .withValidation(Field::isClassName) .withDescription("JDBC Driver class name used to connect to the MySQL database server."); + public static final Field JDBC_PROTOCOL = Field.create(DATABASE_CONFIG_PREFIX + "protocol") + .withDisplayName("JDBC Protocol") + .withType(Type.STRING) + .withGroup(Field.createGroupEntry(Field.Group.CONNECTION, 42)) + .withWidth(Width.MEDIUM) + .withDefault("jdbc:mysql") + .withImportance(Importance.LOW) + .withDescription("JDBC protocol to use with the driver."); + /** * A comma-separated list of regular expressions that match source UUIDs in the GTID set used to find the binlog * position in the MySQL server. Only the GTID ranges that have sources matching one of these include patterns will diff --git a/debezium-connector-mysql/src/test/java/io/debezium/connector/mysql/MySqlConnectorIT.java b/debezium-connector-mysql/src/test/java/io/debezium/connector/mysql/MySqlConnectorIT.java index eff566ba8..f5b1bf674 100644 --- a/debezium-connector-mysql/src/test/java/io/debezium/connector/mysql/MySqlConnectorIT.java +++ b/debezium-connector-mysql/src/test/java/io/debezium/connector/mysql/MySqlConnectorIT.java @@ -22,6 +22,8 @@ import java.util.Optional; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -121,6 +123,42 @@ public void shouldNotStartWithInvalidConfiguration() { assertConnectorNotRunning(); } + @Test + public void shouldNotStartWithUnknownJdbcDriver() { + config = DATABASE.defaultConfig() + .with(MySqlConnectorConfig.JDBC_DRIVER, "foo.bar") + .build(); + + final AtomicBoolean successResult = new AtomicBoolean(); + final AtomicReference message = new AtomicReference<>(); + start(MySqlConnector.class, config, (success, msg, error) -> { + successResult.set(success); + message.set(msg); + }); + + assertThat(successResult.get()).isEqualTo(false); + assertThat(message.get()).contains("java.lang.ClassNotFoundException: foo.bar"); + assertConnectorNotRunning(); + } + + @Test + public void shouldNotStartWithWrongProtocol() { + config = DATABASE.defaultConfig() + .with(MySqlConnectorConfig.JDBC_PROTOCOL, "foo:bar") + .build(); + + final AtomicBoolean successResult = new AtomicBoolean(); + final AtomicReference message = new AtomicReference<>(); + start(MySqlConnector.class, config, (success, msg, error) -> { + successResult.set(success); + message.set(msg); + }); + + assertThat(successResult.get()).isEqualTo(false); + assertThat(message.get()).contains("Unable to obtain a JDBC connection"); + assertConnectorNotRunning(); + } + @Test public void shouldFailToValidateInvalidConfiguration() { Configuration config = Configuration.create() diff --git a/documentation/modules/ROOT/pages/connectors/mysql.adoc b/documentation/modules/ROOT/pages/connectors/mysql.adoc index 2c8ddbe97..127a732c9 100644 --- a/documentation/modules/ROOT/pages/connectors/mysql.adoc +++ b/documentation/modules/ROOT/pages/connectors/mysql.adoc @@ -2727,6 +2727,15 @@ The following configuration properties are _required_ unless a default value is |`1` |The maximum number of tasks that should be created for this connector. The MySQL connector always uses a single task and therefore does not use this value, so the default is always acceptable. +|[[mysql-property-database-protocol]]<> +|jdbc:mysql +|JDBC protocol used by the driver connection string for connecting to the database. + +|[[mysql-property-database-jdbc-driver]]<> +|com.mysql.cj.jdbc.Driver +|The driver class name to use. This can be useful when using an alternative driver to the one packaged with the connector. + + |[[mysql-property-database-hostname]]<> |No default |IP address or host name of the MySQL database server.