diff --git a/pom.xml b/pom.xml index 2c60a0816..d2cdc888f 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,7 @@ 0.1.4 + 4.0.2 11.5.0.0 1.4.200 2.2.8 diff --git a/spring-data-jdbc/pom.xml b/spring-data-jdbc/pom.xml index 2fe841462..c172e3e68 100644 --- a/spring-data-jdbc/pom.xml +++ b/spring-data-jdbc/pom.xml @@ -151,6 +151,13 @@ test + + org.awaitility + awaitility + ${awaitility.version} + test + + org.assertj assertj-core @@ -190,6 +197,7 @@ com.ibm.db2 jcc 11.1.4.4 + test diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/Db2DataSourceConfiguration.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/Db2DataSourceConfiguration.java index b025b372d..044f69162 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/Db2DataSourceConfiguration.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/Db2DataSourceConfiguration.java @@ -15,29 +15,35 @@ */ package org.springframework.data.jdbc.testing; +import java.sql.Connection; +import java.sql.SQLException; + import javax.sql.DataSource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.awaitility.Awaitility; + import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; + import org.testcontainers.containers.Db2Container; /** * {@link DataSource} setup for DB2. * * @author Jens Schauder - * @author Oliver Gierke + * @author Mark Paluch */ @Configuration @Profile("db2") class Db2DataSourceConfiguration extends DataSourceConfiguration { - private static final Db2Container DB_2_CONTAINER = new Db2Container(); + private static final Log LOG = LogFactory.getLog(Db2DataSourceConfiguration.class); - static { - DB_2_CONTAINER.start(); - } + private static Db2Container DB_2_CONTAINER; /* * (non-Javadoc) @@ -46,12 +52,38 @@ class Db2DataSourceConfiguration extends DataSourceConfiguration { @Override protected DataSource createDataSource() { + if (DB_2_CONTAINER == null) { + + LOG.info("DB2 starting..."); + Db2Container container = new Db2Container(); + container.start(); + LOG.info("DB2 started"); + + DB_2_CONTAINER = container; + } + DriverManagerDataSource dataSource = new DriverManagerDataSource(DB_2_CONTAINER.getJdbcUrl(), DB_2_CONTAINER.getUsername(), DB_2_CONTAINER.getPassword()); + // DB2 container says its ready but it's like with a cat that denies service and still wants food although it had + // its food. Therefore, we make sure that we can properly establish a connection instead of trusting the cat + // ...err... DB2. + Awaitility.await().ignoreException(SQLException.class).until(() -> { + + try (Connection connection = dataSource.getConnection()) { + return true; + } + }); + + LOG.info("DB2 connectivity verified"); + return dataSource; } + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.testing.customizePopulator#createDataSource(org.springframework.jdbc.datasource.init.ResourceDatabasePopulator) + */ @Override protected void customizePopulator(ResourceDatabasePopulator populator) { populator.setIgnoreFailedDrops(true); diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/LicenseListener.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/LicenseListener.java new file mode 100644 index 000000000..f60d9c964 --- /dev/null +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/LicenseListener.java @@ -0,0 +1,62 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jdbc.testing; + +import org.junit.AssumptionViolatedException; + +import org.springframework.core.annotation.Order; +import org.springframework.core.env.Profiles; +import org.springframework.core.env.StandardEnvironment; +import org.springframework.test.context.TestContext; +import org.springframework.test.context.TestExecutionListener; + +import org.testcontainers.containers.Db2Container; +import org.testcontainers.containers.MSSQLServerContainer; +import org.testcontainers.utility.LicenseAcceptance; + +/** + * {@link TestExecutionListener} to selectively skip tests if the license for a particular database container was not + * accepted. + * + * @author Mark Paluch + */ +@Order(Integer.MIN_VALUE) +public class LicenseListener implements TestExecutionListener { + + @Override + public void prepareTestInstance(TestContext testContext) { + + StandardEnvironment environment = new StandardEnvironment(); + + if (environment.acceptsProfiles(Profiles.of("db2"))) { + assumeLicenseAccepted(Db2Container.DEFAULT_DB2_IMAGE_NAME + ":" + Db2Container.DEFAULT_TAG); + } + + if (environment.acceptsProfiles(Profiles.of("mssql"))) { + assumeLicenseAccepted(MSSQLServerContainer.IMAGE + ":" + MSSQLServerContainer.DEFAULT_TAG); + } + } + + private static void assumeLicenseAccepted(String imageName) { + + try { + LicenseAcceptance.assertLicenseAccepted(imageName); + } catch (IllegalStateException e) { + throw new AssumptionViolatedException(e.getMessage()); + } + } + +} diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MariaDBDataSourceConfiguration.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MariaDBDataSourceConfiguration.java index fa6255e50..a0f3a6e07 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MariaDBDataSourceConfiguration.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MariaDBDataSourceConfiguration.java @@ -15,32 +15,32 @@ */ package org.springframework.data.jdbc.testing; +import java.sql.Connection; import java.sql.SQLException; import javax.annotation.PostConstruct; -import javax.script.ScriptException; import javax.sql.DataSource; import org.mariadb.jdbc.MariaDbDataSource; + import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.jdbc.datasource.init.ScriptUtils; + import org.testcontainers.containers.MariaDBContainer; -import org.testcontainers.jdbc.ext.ScriptUtils; /** * {@link DataSource} setup for MariaDB. Starts a Docker-container with a MariaDB database, and sets up database "test". * * @author Christoph Preißner + * @author Mark Paluch */ @Configuration @Profile("mariadb") class MariaDBDataSourceConfiguration extends DataSourceConfiguration { - private static final MariaDBContainer MARIADB_CONTAINER = new MariaDBContainer().withConfigurationOverride(""); - - static { - MARIADB_CONTAINER.start(); - } + private static MariaDBContainer MARIADB_CONTAINER; /* * (non-Javadoc) @@ -49,6 +49,14 @@ class MariaDBDataSourceConfiguration extends DataSourceConfiguration { @Override protected DataSource createDataSource() { + if (MARIADB_CONTAINER == null) { + + MariaDBContainer container = new MariaDBContainer<>().withConfigurationOverride(""); + container.start(); + + MARIADB_CONTAINER = container; + } + try { MariaDbDataSource dataSource = new MariaDbDataSource(); @@ -62,7 +70,12 @@ class MariaDBDataSourceConfiguration extends DataSourceConfiguration { } @PostConstruct - public void initDatabase() throws SQLException, ScriptException { - ScriptUtils.executeSqlScript(createDataSource().getConnection(), null, "DROP DATABASE test;CREATE DATABASE test;"); + public void initDatabase() throws SQLException { + + try (Connection connection = createDataSource().getConnection()) { + ScriptUtils.executeSqlScript(connection, + new ByteArrayResource("DROP DATABASE test;CREATE DATABASE test;".getBytes())); + } } + } diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MsSqlDataSourceConfiguration.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MsSqlDataSourceConfiguration.java index 64aa23d23..6aab16cca 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MsSqlDataSourceConfiguration.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MsSqlDataSourceConfiguration.java @@ -15,12 +15,14 @@ */ package org.springframework.data.jdbc.testing; -import com.microsoft.sqlserver.jdbc.SQLServerDataSource; +import javax.sql.DataSource; + import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; + import org.testcontainers.containers.MSSQLServerContainer; -import javax.sql.DataSource; +import com.microsoft.sqlserver.jdbc.SQLServerDataSource; /** @@ -29,17 +31,14 @@ import javax.sql.DataSource; * Configuration for a MSSQL Datasource. * * @author Thomas Lang + * @author Mark Paluch * @see */ @Configuration @Profile({"mssql"}) public class MsSqlDataSourceConfiguration extends DataSourceConfiguration { - private static final MSSQLServerContainer mssqlserver = new MSSQLServerContainer(); - - static { - mssqlserver.start(); - } + private static MSSQLServerContainer MSSQL_CONTAINER; /* * (non-Javadoc) @@ -48,10 +47,18 @@ public class MsSqlDataSourceConfiguration extends DataSourceConfiguration { @Override protected DataSource createDataSource() { + if (MSSQL_CONTAINER == null) { + + MSSQLServerContainer container = new MSSQLServerContainer<>(); + container.start(); + + MSSQL_CONTAINER = container; + } + SQLServerDataSource sqlServerDataSource = new SQLServerDataSource(); - sqlServerDataSource.setURL(mssqlserver.getJdbcUrl()); - sqlServerDataSource.setUser(mssqlserver.getUsername()); - sqlServerDataSource.setPassword(mssqlserver.getPassword()); + sqlServerDataSource.setURL(MSSQL_CONTAINER.getJdbcUrl()); + sqlServerDataSource.setUser(MSSQL_CONTAINER.getUsername()); + sqlServerDataSource.setPassword(MSSQL_CONTAINER.getPassword()); return sqlServerDataSource; } } diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MySqlDataSourceConfiguration.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MySqlDataSourceConfiguration.java index 334b06257..d27af0668 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MySqlDataSourceConfiguration.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MySqlDataSourceConfiguration.java @@ -15,19 +15,18 @@ */ package org.springframework.data.jdbc.testing; +import java.sql.Connection; import java.sql.SQLException; import javax.annotation.PostConstruct; -import javax.script.ScriptException; import javax.sql.DataSource; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; -import org.springframework.data.relational.core.dialect.Dialect; -import org.springframework.data.relational.core.dialect.MySqlDialect; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.jdbc.datasource.init.ScriptUtils; + import org.testcontainers.containers.MySQLContainer; -import org.testcontainers.jdbc.ext.ScriptUtils; import com.mysql.jdbc.jdbc2.optional.MysqlDataSource; @@ -38,16 +37,13 @@ import com.mysql.jdbc.jdbc2.optional.MysqlDataSource; * @author Jens Schauder * @author Oliver Gierke * @author Sedat Gokcen + * @author Mark Paluch */ @Configuration @Profile("mysql") class MySqlDataSourceConfiguration extends DataSourceConfiguration { - private static final MySQLContainer MYSQL_CONTAINER = new MySQLContainer().withConfigurationOverride(""); - - static { - MYSQL_CONTAINER.start(); - } + private static MySQLContainer MYSQL_CONTAINER; /* * (non-Javadoc) @@ -56,6 +52,14 @@ class MySqlDataSourceConfiguration extends DataSourceConfiguration { @Override protected DataSource createDataSource() { + if (MYSQL_CONTAINER == null) { + + MySQLContainer container = new MySQLContainer<>().withConfigurationOverride(""); + container.start(); + + MYSQL_CONTAINER = container; + } + MysqlDataSource dataSource = new MysqlDataSource(); dataSource.setUrl(MYSQL_CONTAINER.getJdbcUrl()); dataSource.setUser(MYSQL_CONTAINER.getUsername()); @@ -66,7 +70,11 @@ class MySqlDataSourceConfiguration extends DataSourceConfiguration { } @PostConstruct - public void initDatabase() throws SQLException, ScriptException { - ScriptUtils.executeSqlScript(createDataSource().getConnection(), null, "DROP DATABASE test;CREATE DATABASE test;"); + public void initDatabase() throws SQLException { + + try (Connection connection = createDataSource().getConnection()) { + ScriptUtils.executeSqlScript(connection, + new ByteArrayResource("DROP DATABASE test;CREATE DATABASE test;".getBytes())); + } } } diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/PostgresDataSourceConfiguration.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/PostgresDataSourceConfiguration.java index 1e96041ff..1e720d61d 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/PostgresDataSourceConfiguration.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/PostgresDataSourceConfiguration.java @@ -18,12 +18,11 @@ package org.springframework.data.jdbc.testing; import javax.sql.DataSource; import org.postgresql.ds.PGSimpleDataSource; -import org.springframework.context.annotation.Bean; + import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; -import org.springframework.data.relational.core.dialect.Dialect; -import org.springframework.data.relational.core.dialect.PostgresDialect; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; + import org.testcontainers.containers.PostgreSQLContainer; /** @@ -32,16 +31,13 @@ import org.testcontainers.containers.PostgreSQLContainer; * @author Jens Schauder * @author Oliver Gierke * @author Sedat Gokcen + * @author Mark Paluch */ @Configuration @Profile("postgres") public class PostgresDataSourceConfiguration extends DataSourceConfiguration { - private static final PostgreSQLContainer POSTGRESQL_CONTAINER = new PostgreSQLContainer(); - - static { - POSTGRESQL_CONTAINER.start(); - } + private static PostgreSQLContainer POSTGRESQL_CONTAINER; /* * (non-Javadoc) @@ -50,6 +46,14 @@ public class PostgresDataSourceConfiguration extends DataSourceConfiguration { @Override protected DataSource createDataSource() { + if (POSTGRESQL_CONTAINER == null) { + + PostgreSQLContainer container = new PostgreSQLContainer<>(); + container.start(); + + POSTGRESQL_CONTAINER = container; + } + PGSimpleDataSource dataSource = new PGSimpleDataSource(); dataSource.setUrl(POSTGRESQL_CONTAINER.getJdbcUrl()); dataSource.setUser(POSTGRESQL_CONTAINER.getUsername()); diff --git a/spring-data-jdbc/src/test/resources/META-INF/spring.factories b/spring-data-jdbc/src/test/resources/META-INF/spring.factories new file mode 100644 index 000000000..8116a0925 --- /dev/null +++ b/spring-data-jdbc/src/test/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.test.context.TestExecutionListener=org.springframework.data.jdbc.testing.LicenseListener diff --git a/spring-data-jdbc/src/test/resources/logback.xml b/spring-data-jdbc/src/test/resources/logback.xml index f1bfdbaf3..814c114d0 100644 --- a/spring-data-jdbc/src/test/resources/logback.xml +++ b/spring-data-jdbc/src/test/resources/logback.xml @@ -7,6 +7,7 @@ + @@ -15,4 +16,4 @@ - \ No newline at end of file + diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/Db2Dialect.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/Db2Dialect.java index 7d2fef315..486d49fb1 100644 --- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/Db2Dialect.java +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/Db2Dialect.java @@ -21,7 +21,7 @@ import org.springframework.data.relational.core.sql.IdentifierProcessing; * An SQL dialect for DB2. * * @author Jens Schauder - * @since 2.1 + * @since 2.0 */ public class Db2Dialect extends AbstractDialect { @@ -80,6 +80,10 @@ public class Db2Dialect extends AbstractDialect { return LIMIT_CLAUSE; } + /* + * (non-Javadoc) + * @see org.springframework.data.relational.core.dialect.Dialect#getIdentifierProcessing() + */ @Override public IdentifierProcessing getIdentifierProcessing() { return IdentifierProcessing.ANSI;