diff --git a/CHANGELOG.md b/CHANGELOG.md index f287cceba..d1857ca55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -416,7 +416,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [2.2.2] - 2023-07-05 ### :magic_wand: Added -- Official support for Amazon Aurora with MySQL compatibility. The AWS Advanced JDBC Wrapper has been validated to support [MySQL JDBC Driver](https://github.com/mysql/mysql-connector-j) and [MariaDB JDBC Driver](https://github.com/mariadb-corporation/mariadb-connector-j). +- Official support for Amazon Aurora with MySQL compatibility. The AWS Advanced JDBC Wrapper has been validated to support [MySQL JDBC Driver](https://github.com/mysql/mysql-connector-j) and version 2.x of the [MariaDB JDBC Driver](https://github.com/mariadb-corporation/mariadb-connector-j). See [here](./README.md#mariadb) for some limitations and caveats with the MariaDB driver. - Documentation: - Maintenance and release policy ([PR #442](https://github.com/aws/aws-advanced-jdbc-wrapper/pull/442) and [PR #507](https://github.com/aws/aws-advanced-jdbc-wrapper/pull/507)). - Migration guide for moving from the AWS Advanced JDBC Wrapper for MySQL to the AWS Advanced JDBC Wrapper ([PR #510](https://github.com/aws/aws-advanced-jdbc-wrapper/pull/510)). diff --git a/README.md b/README.md index 2cff94a62..db833db4a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ The **Amazon Web Services (AWS) JDBC Driver** has been redesigned as an advanced The wrapper is complementary to an existing JDBC driver and aims to extend the functionality of the driver to enable applications to take full advantage of the features of clustered databases such as Amazon Aurora. In other words, the AWS Advanced JDBC Wrapper does not connect directly to any database, but enables support of AWS and Aurora functionalities on top of an underlying JDBC driver of the user's choice. This approach enables service-specific enhancements, without requiring users to change their workflow and existing JDBC driver tooling. -The AWS Advanced JDBC Wrapper is targeted to work with **any** existing JDBC driver. Currently, the AWS Advanced JDBC Wrapper has been validated to support the [PostgreSQL JDBC Driver](https://github.com/pgjdbc/pgjdbc), [MySQL JDBC Driver](https://github.com/mysql/mysql-connector-j), and [MariaDB JDBC Driver](https://github.com/mariadb-corporation/mariadb-connector-j). +The AWS Advanced JDBC Wrapper is targeted to work with **any** existing JDBC driver. Currently, the AWS Advanced JDBC Wrapper has been validated to support the [PostgreSQL JDBC Driver](https://github.com/pgjdbc/pgjdbc), [MySQL JDBC Driver](https://github.com/mysql/mysql-connector-j), and version 2.x of the [MariaDB JDBC Driver](https://github.com/mariadb-corporation/mariadb-connector-j) (with some caveats, see [below](#mariadb)). The AWS Advanced JDBC Wrapper provides modular functionality through feature plugins, with each plugin being relevant to specific database services based on their architecture and capabilities. For example, [AWS Identity and Access Management (IAM)](https://aws.amazon.com/iam/) authentication is supported across multiple services, while [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) applies to services that support password-based authentication. The fast failover plugin provides reduced recovery time during failover for Aurora PostgreSQL and Aurora MySQL clusters. @@ -139,6 +139,16 @@ To find all the documentation and concrete examples on how to use the AWS Advanc ### Known Limitations +#### MariaDB + +If you would like to use the MariaDB driver, you should use version 2.x. Version 3.x uses pipelining, which is not compatible with Aurora. Additionally, you should set the following properties, because they also use pipelining. + +```java +Properties props = new Properties(); +props.setProperty("usePipelineAuth", "false"); +props.setProperty("useBatchMultiSend", "false"); +``` + #### Amazon RDS Blue/Green Deployments Support for Blue/Green deployments using the AWS Advanced JDBC Wrapper requires specific metadata tables. The following service versions provide support for Blue/Green Deployments: diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 359765fe5..8dc960e45 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -22,7 +22,7 @@ dependencies { jmhImplementation(project(":aws-advanced-jdbc-wrapper")) implementation("org.postgresql:postgresql:42.7.7") implementation("com.mysql:mysql-connector-j:9.4.0") - implementation("org.mariadb.jdbc:mariadb-java-client:3.5.6") + implementation("org.mariadb.jdbc:mariadb-java-client:2.7.12") implementation("com.zaxxer:HikariCP:4.0.3") implementation("org.checkerframework:checker-qual:3.49.5") diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md index d66b844ca..0558220ac 100644 --- a/docs/GettingStarted.md +++ b/docs/GettingStarted.md @@ -8,7 +8,7 @@ Before using the AWS Advanced JDBC Wrapper, you must install: - The AWS Advanced JDBC Wrapper. - Your choice of underlying JDBC driver. - To use the wrapper with Aurora with PostgreSQL compatibility, install the [PostgreSQL JDBC Driver](https://github.com/pgjdbc/pgjdbc). - - To use the wrapper with Aurora with MySQL compatibility, install the [MySQL JDBC Driver](https://github.com/mysql/mysql-connector-j) or [MariaDB JDBC Driver](https://github.com/mariadb-corporation/mariadb-connector-j). + - To use the wrapper with Aurora with MySQL compatibility, install the [MySQL JDBC Driver](https://github.com/mysql/mysql-connector-j) or version 2.x of the [MariaDB JDBC Driver](https://github.com/mariadb-corporation/mariadb-connector-j). See [here](../README.md#mariadb) for some limitations and caveats with the MariaDB driver. If you are using the AWS Advanced JDBC Wrapper as part of a Gradle project, include the wrapper and underlying driver as dependencies. For example, to include the AWS Advanced JDBC Wrapper and the PostgreSQL JDBC Driver as dependencies in a Gradle project, update the ```build.gradle``` file as follows: diff --git a/docs/using-the-jdbc-driver/TargetDriverDialects.md b/docs/using-the-jdbc-driver/TargetDriverDialects.md index 11b3694a6..0a60a20fb 100644 --- a/docs/using-the-jdbc-driver/TargetDriverDialects.md +++ b/docs/using-the-jdbc-driver/TargetDriverDialects.md @@ -17,12 +17,12 @@ By default, target driver dialect is determined based on used target driver clas ### List of Available Target Driver Codes Target Driver Dialect codes specify what target driver dialect class to use. -| Dialect Code Reference | Value | Target driver or DataSource class names | -|-----------------------------|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------| +| Dialect Code Reference | Value | Target driver or DataSource class names | +|-----------------------------|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| | `PG_JDBC` | `pgjdbc` | org.postgresql.Driver,
org.postgresql.ds.PGSimpleDataSource,
org.postgresql.ds.PGPoolingDataSource,
org.postgresql.ds.PGConnectionPoolDataSource | -| `MYSQL_CONNECTOR_J` | `mysql-connector-j` | com.mysql.cj.jdbc.Driver,
com.mysql.cj.jdbc.MysqlDataSource,
com.mysql.cj.jdbc.MysqlConnectionPoolDataSource | -| `MARIADB_CONNECTOR_J_VER_3` | `mariadb-connector-j-3` | org.mariadb.jdbc.Driver (ver. 3+),
org.mariadb.jdbc.MariaDbDataSource,
org.mariadb.jdbc.MariaDbPoolDataSource | -| `GENERIC` | `generic` | Any other JDBC driver | +| `MYSQL_CONNECTOR_J` | `mysql-connector-j` | com.mysql.cj.jdbc.Driver,
com.mysql.cj.jdbc.MysqlDataSource,
com.mysql.cj.jdbc.MysqlConnectionPoolDataSource | +| `MARIADB_CONNECTOR_J_VER_2` | `mariadb-connector-j-2` | org.mariadb.jdbc.Driver (ver. 2.x),
org.mariadb.jdbc.MariaDbDataSource,
org.mariadb.jdbc.MariaDbPoolDataSource | +| `GENERIC` | `generic` | Any other JDBC driver | ## Custom Target Driver Dialects If you are interested in using the AWS Advanced JDBC Wrapper but your desired target driver has unique features so the existing generic dialect doesn't work well with it, it is possible to create a custom target driver dialect. diff --git a/docs/using-the-jdbc-driver/UsingTheJdbcDriver.md b/docs/using-the-jdbc-driver/UsingTheJdbcDriver.md index 829b4f38a..d0ac9a382 100644 --- a/docs/using-the-jdbc-driver/UsingTheJdbcDriver.md +++ b/docs/using-the-jdbc-driver/UsingTheJdbcDriver.md @@ -1,5 +1,5 @@ # Using the AWS Advanced JDBC Wrapper -The AWS Advanced JDBC Wrapper leverages community JDBC drivers and enables support of AWS and Aurora functionalities. Currently, the [PostgreSQL JDBC Driver](https://github.com/pgjdbc/pgjdbc), [MySQL JDBC Driver](https://github.com/mysql/mysql-connector-j), and [MariaDB JDBC Driver](https://github.com/mariadb-corporation/mariadb-connector-j) are supported. +The AWS Advanced JDBC Wrapper leverages community JDBC drivers and enables support of AWS and Aurora functionalities. Currently, the [PostgreSQL JDBC Driver](https://github.com/pgjdbc/pgjdbc), [MySQL JDBC Driver](https://github.com/mysql/mysql-connector-j), and version 2.x of the [MariaDB JDBC Driver](https://github.com/mariadb-corporation/mariadb-connector-j) are supported. See [here](../../README.md#mariadb) for some limitations and caveats with the MariaDB driver. The JDBC Wrapper also supports [connection pooling](./DataSource.md#Using-the-AwsWrapperDataSource-with-Connection-Pooling-Frameworks). ## Using the AWS Advanced JDBC Wrapper with plain RDS databases diff --git a/examples/AWSDriverExample/src/main/java/software/amazon/AwsIamAuthenticationMariadbExample.java b/examples/AWSDriverExample/src/main/java/software/amazon/AwsIamAuthenticationMariadbExample.java index 81d01a8c6..ecea46ada 100644 --- a/examples/AWSDriverExample/src/main/java/software/amazon/AwsIamAuthenticationMariadbExample.java +++ b/examples/AWSDriverExample/src/main/java/software/amazon/AwsIamAuthenticationMariadbExample.java @@ -38,6 +38,12 @@ public static void main(String[] args) throws SQLException { properties.setProperty(PropertyDefinition.USER.name, USERNAME); properties.setProperty(PropertyDefinition.PLUGINS.name, "iam"); + // Aurora is not compatible with pipelining, so these properties should be set. Additionally, MariaDB 3.x uses + // pipelining extensively, so 2.x should be used instead. + // See https://github.com/aws/aws-advanced-jdbc-wrapper?tab=readme-ov-file#mariadb for more information. + properties.setProperty("usePipelineAuth", "false"); + properties.setProperty("useBatchMultiSend", "false"); + // The properties sslMode and severSslCert are required when using the IAM Authentication plugin with the MariaDB driver. properties.setProperty("sslMode", "verify-ca"); diff --git a/wrapper/build.gradle.kts b/wrapper/build.gradle.kts index 0e6fb29f1..fc456239f 100644 --- a/wrapper/build.gradle.kts +++ b/wrapper/build.gradle.kts @@ -53,7 +53,7 @@ dependencies { compileOnly("org.checkerframework:checker-qual:3.49.5") compileOnly("com.mysql:mysql-connector-j:9.4.0") compileOnly("org.postgresql:postgresql:42.7.7") - compileOnly("org.mariadb.jdbc:mariadb-java-client:3.5.6") + compileOnly("org.mariadb.jdbc:mariadb-java-client:2.7.12") compileOnly("org.osgi:org.osgi.core:6.0.0") compileOnly("org.jetbrains.kotlin:kotlin-stdlib:2.2.20") @@ -75,7 +75,7 @@ dependencies { testImplementation("org.apache.commons:commons-dbcp2:2.13.0") testImplementation("org.postgresql:postgresql:42.7.7") testImplementation("com.mysql:mysql-connector-j:9.4.0") - testImplementation("org.mariadb.jdbc:mariadb-java-client:3.5.6") + testImplementation("org.mariadb.jdbc:mariadb-java-client:2.7.12") testImplementation("com.zaxxer:HikariCP:4.0.3") // Version 4.+ is compatible with Java 8 testImplementation("com.mchange:c3p0:0.11.0") testImplementation("org.springframework.boot:spring-boot-starter-jdbc:2.7.13") // 2.7.13 is the last version compatible with Java 8 diff --git a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbTargetDriverDialect.java b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbTargetDriverDialect.java index 506a249d2..d469145e2 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbTargetDriverDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbTargetDriverDialect.java @@ -109,9 +109,10 @@ public boolean isDialect(String dataSourceClass) { } @Override - public ConnectInfo prepareConnectInfo(final @NonNull String protocol, + public ConnectInfo prepareConnectInfo( + final @NonNull String protocol, final @NonNull HostSpec hostSpec, - final @NonNull Properties props) throws SQLException { + final @NonNull Properties props) { final String databaseName = PropertyDefinition.DATABASE.getString(props) != null diff --git a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialectCodes.java b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialectCodes.java index b1ccd71f8..ec8de3c2a 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialectCodes.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialectCodes.java @@ -19,6 +19,6 @@ public class TargetDriverDialectCodes { public static final String PG_JDBC = "pgjdbc"; public static final String MYSQL_CONNECTOR_J = "mysql-connector-j"; - public static final String MARIADB_CONNECTOR_J_VER_3 = "mariadb-connector-j-3"; // ver 3.0.3+ + public static final String MARIADB_CONNECTOR_J_VER_2 = "mariadb-connector-j-2"; // ver 2.x public static final String GENERIC = "generic"; } diff --git a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialectManager.java b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialectManager.java index 865dbfe7e..669a69d60 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialectManager.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialectManager.java @@ -52,7 +52,7 @@ public class TargetDriverDialectManager implements TargetDriverDialectProvider { { put(TargetDriverDialectCodes.PG_JDBC, new PgTargetDriverDialect()); put(TargetDriverDialectCodes.MYSQL_CONNECTOR_J, new MysqlConnectorJTargetDriverDialect()); - put(TargetDriverDialectCodes.MARIADB_CONNECTOR_J_VER_3, new MariadbTargetDriverDialect()); + put(TargetDriverDialectCodes.MARIADB_CONNECTOR_J_VER_2, new MariadbTargetDriverDialect()); put(TargetDriverDialectCodes.GENERIC, new GenericTargetDriverDialect()); } }; @@ -62,7 +62,7 @@ public class TargetDriverDialectManager implements TargetDriverDialectProvider { { put("jdbc:postgresql://", TargetDriverDialectCodes.PG_JDBC); put("jdbc:mysql://", TargetDriverDialectCodes.MYSQL_CONNECTOR_J); - put("jdbc:mariadb://", TargetDriverDialectCodes.MARIADB_CONNECTOR_J_VER_3); + put("jdbc:mariadb://", TargetDriverDialectCodes.MARIADB_CONNECTOR_J_VER_2); } }; diff --git a/wrapper/src/test/build.gradle.kts b/wrapper/src/test/build.gradle.kts index 3d26591e6..c21afa23b 100644 --- a/wrapper/src/test/build.gradle.kts +++ b/wrapper/src/test/build.gradle.kts @@ -37,7 +37,7 @@ dependencies { testImplementation("org.apache.commons:commons-dbcp2:2.12.0") testImplementation("org.postgresql:postgresql:42.7.4") testImplementation("com.mysql:mysql-connector-j:9.1.0") - testImplementation("org.mariadb.jdbc:mariadb-java-client:3.5.6") + testImplementation("org.mariadb.jdbc:mariadb-java-client:2.7.12") testImplementation("com.zaxxer:HikariCP:4.0.3") // Version 4.+ is compatible with Java 8 testImplementation("org.springframework.boot:spring-boot-starter-jdbc:2.7.13") // 2.7.13 is the last version compatible with Java 8 testImplementation("org.mockito:mockito-inline:4.11.0") // 4.11.0 is the last version compatible with Java 8 diff --git a/wrapper/src/test/java/integration/DriverHelper.java b/wrapper/src/test/java/integration/DriverHelper.java index 44ccc32c8..021efa3a0 100644 --- a/wrapper/src/test/java/integration/DriverHelper.java +++ b/wrapper/src/test/java/integration/DriverHelper.java @@ -161,7 +161,7 @@ public static Class getConnectionClass(TestDriver testDriver) { case PG: return org.postgresql.PGConnection.class; case MARIADB: - return org.mariadb.jdbc.Connection.class; + return org.mariadb.jdbc.MariaDbConnection.class; default: throw new NotImplementedException(testDriver.toString()); } @@ -181,7 +181,7 @@ public static String getDriverRequiredParameters(TestDriver testDriver) { public static String getDriverRequiredParameters( DatabaseEngine databaseEngine, TestDriver testDriver) { if (testDriver == TestDriver.MARIADB && databaseEngine == DatabaseEngine.MYSQL) { - return "?permitMysqlScheme"; + return "?usePipelineAuth=false&useBatchMultiSend=false&permitMysqlScheme"; } return ""; } diff --git a/wrapper/src/test/java/integration/container/ConnectionStringHelper.java b/wrapper/src/test/java/integration/container/ConnectionStringHelper.java index ba3ab227f..586dc9493 100644 --- a/wrapper/src/test/java/integration/container/ConnectionStringHelper.java +++ b/wrapper/src/test/java/integration/container/ConnectionStringHelper.java @@ -213,6 +213,11 @@ public static Properties getDefaultProperties() { // will get the error "RSA public key is not available client side" when connecting. The mariadb driver may not // fully support mysql 8.4's SSL mechanisms, which is why this property is only required for newer mysql versions. props.setProperty("allowPublicKeyRetrieval", "true"); + if (TestEnvironment.getCurrent().getInfo().getRequest().getDatabaseEngine() != DatabaseEngine.MARIADB) { + // These options may cause issues on non-MariaDB databases. + props.setProperty("usePipelineAuth", "false"); + props.setProperty("useBatchMultiSend", "false"); + } } return props; diff --git a/wrapper/src/test/java/integration/container/tests/BasicConnectivityTests.java b/wrapper/src/test/java/integration/container/tests/BasicConnectivityTests.java index 3c94f4536..c90335f52 100644 --- a/wrapper/src/test/java/integration/container/tests/BasicConnectivityTests.java +++ b/wrapper/src/test/java/integration/container/tests/BasicConnectivityTests.java @@ -293,6 +293,11 @@ public void testFailedProperties( if (testDriver == TestDriver.MARIADB) { // If this property is true the driver will still be able to connect, causing the test to fail. props.setProperty("allowPublicKeyRetrieval", "false"); + if (TestEnvironment.getCurrent().getInfo().getRequest().getDatabaseEngine() != DatabaseEngine.MARIADB) { + // These options may cause issues on non-MariaDB databases. + props.setProperty("usePipelineAuth", "false"); + props.setProperty("useBatchMultiSend", "false"); + } } LOGGER.finest("Connecting to " + url); diff --git a/wrapper/src/test/java/integration/container/tests/FailoverTest.java b/wrapper/src/test/java/integration/container/tests/FailoverTest.java index 347264561..7585c2ebc 100644 --- a/wrapper/src/test/java/integration/container/tests/FailoverTest.java +++ b/wrapper/src/test/java/integration/container/tests/FailoverTest.java @@ -718,6 +718,9 @@ protected Connection createDataSourceConnectionWithFailoverUsingInstanceId( == DatabaseEngine.MYSQL) { // Connecting to Mysql database with MariaDb driver requires a configuration parameter: "permitMysqlScheme" targetDataSourceProps.setProperty("permitMysqlScheme", "1"); + // These options may cause issues for non-MariaDB databases. + targetDataSourceProps.setProperty("usePipelineAuth", "false"); + targetDataSourceProps.setProperty("useBatchMultiSend", "false"); } ds.setTargetDataSourceProperties(targetDataSourceProps); diff --git a/wrapper/src/test/java/integration/container/tests/HikariTests.java b/wrapper/src/test/java/integration/container/tests/HikariTests.java index 2be676fec..8b9aebc13 100644 --- a/wrapper/src/test/java/integration/container/tests/HikariTests.java +++ b/wrapper/src/test/java/integration/container/tests/HikariTests.java @@ -154,6 +154,9 @@ public void testOpenConnectionWithDataSourceClassName() throws SQLException { // Connecting to Mysql database with MariaDb driver requires a configuration parameter // "permitMysqlScheme" targetDataSourceProps.setProperty("permitMysqlScheme", "1"); + // These options may cause issues for non-MariaDB databases. + targetDataSourceProps.setProperty("usePipelineAuth", "false"); + targetDataSourceProps.setProperty("useBatchMultiSend", "false"); } dataSource.addDataSourceProperty("targetDataSourceProperties", targetDataSourceProps); @@ -411,6 +414,9 @@ private AwsWrapperDataSource createWrapperDataSource(TestInstanceInfo instanceIn if (TestEnvironment.getCurrent().getCurrentDriver() == TestDriver.MARIADB && TestEnvironment.getCurrent().getInfo().getRequest().getDatabaseEngine() == DatabaseEngine.MYSQL) { targetDataSourceProps.setProperty("permitMysqlScheme", "1"); + // These options may cause issues for non-MariaDB databases. + targetDataSourceProps.setProperty("usePipelineAuth", "false"); + targetDataSourceProps.setProperty("useBatchMultiSend", "false"); } AwsWrapperDataSource ds = new AwsWrapperDataSource(); @@ -528,6 +534,9 @@ configured host (provider with "serverName" property), these attempts may fail. // Connecting to Mysql database with MariaDb driver requires a configuration parameter // "permitMysqlScheme" targetDataSourceProps.setProperty("permitMysqlScheme", "1"); + // These options may cause issues for non-MariaDB databases. + targetDataSourceProps.setProperty("usePipelineAuth", "false"); + targetDataSourceProps.setProperty("useBatchMultiSend", "false"); } targetDataSourceProps.setProperty("monitoring-" + PropertyDefinition.CONNECT_TIMEOUT.name, "3000"); diff --git a/wrapper/src/test/java/integration/container/tests/hibernate/HibernateTests.java b/wrapper/src/test/java/integration/container/tests/hibernate/HibernateTests.java index a8a5bb4a8..70fd8b762 100644 --- a/wrapper/src/test/java/integration/container/tests/hibernate/HibernateTests.java +++ b/wrapper/src/test/java/integration/container/tests/hibernate/HibernateTests.java @@ -253,6 +253,11 @@ private Configuration getConfiguration() { // will get the error "RSA public key is not available client side" when connecting. The mariadb driver may not // fully support mysql 8.4's SSL mechanisms, which is why this property is only required for newer mysql versions. configuration.setProperty("hibernate.connection.allowPublicKeyRetrieval", "true"); + if (TestEnvironment.getCurrent().getInfo().getRequest().getDatabaseEngine() != DatabaseEngine.MARIADB) { + // These options may cause issues on non-MariaDB databases. + configuration.setProperty("hibernate.connection.usePipelineAuth", "false"); + configuration.setProperty("hibernate.connection.useBatchMultiSend", "false"); + } } return configuration;