'BeanCreationException: Error creating bean with name 'flywayInitializer'
I am trying to run my project tests in a docker container. All of the tests work just fine when running locally. Errors started occurring when I tried to move my testing to docker container. Here is the error message:
java.lang.IllegalStateException: Failed to load ApplicationContext
[...]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.internal.command.DbMigrate$FlywayMigrateException:
Migration V1__initial_user.sql failed
-------------------------------------
SQL State : 42601
Error Code : 0
Message : ERROR: syntax error at or near "GENERATED"
Position: 45
Location : db/migration/V1__initial_user.sql (/Users/villemossip/Desktop/GRP/GRP-SAS/application/build/resources/main/db/migration/V1__initial_user.sql)
Line : 36
Statement : CREATE TABLE revinfo
(
rev INTEGER GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ),
revtstmp BIGINT,
PRIMARY KEY (rev)
)
From the log we can see that container image was created, but it fails to migrate the sql schema:
[...]
2019-10-10 10:36:18.768 INFO 49547 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 5.2.4 by Boxfuse
2019-10-10 10:36:18.777 INFO 49547 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2019-10-10 10:36:18.795 INFO 49547 --- [ main] 🐳 [postgres:9.6.12] : Creating container for image: postgres:9.6.12
2019-10-10 10:36:19.001 INFO 49547 --- [ main] 🐳 [postgres:9.6.12] : Starting container with ID: a32dd0850baf34770cce9bdc81918cd4db40502188b85dfaa90f74e2900f9fa7
2019-10-10 10:36:19.547 INFO 49547 --- [ main] 🐳 [postgres:9.6.12] : Container postgres:9.6.12 is starting: a32dd0850baf34770cce9bdc81918cd4db40502188b85dfaa90f74e2900f9fa7
2019-10-10 10:36:23.342 INFO 49547 --- [ main] 🐳 [postgres:9.6.12] : Container postgres:9.6.12 started
2019-10-10 10:36:23.426 INFO 49547 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2019-10-10 10:36:23.431 INFO 49547 --- [ main] o.f.c.internal.database.DatabaseFactory : Database: jdbc:postgresql://localhost:32834/test (PostgreSQL 9.6)
2019-10-10 10:36:23.488 INFO 49547 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 6 migrations (execution time 00:00.024s)
2019-10-10 10:36:23.501 INFO 49547 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table: "public"."flyway_schema_history"
2019-10-10 10:36:23.519 INFO 49547 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema "public": << Empty Schema >>
2019-10-10 10:36:23.520 INFO 49547 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema "public" to version 1 - initial user
2019-10-10 10:36:23.542 ERROR 49547 --- [ main] o.f.core.internal.command.DbMigrate : Migration of schema "public" to version 1 - initial user failed! Changes successfully rolled back.
2019-10-10 10:36:23.546 WARN 49547 --- [ main] o.s.w.c.s.GenericWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.internal.command.DbMigrate$FlywayMigrateException:
Migration V1__initial_user.sql failed
-------------------------------------
[...]
Here is part of the sql script (app/src/main/resources/db/migration):
[...]
constraint user_aud_pkey primary key (id, rev)
);
CREATE TABLE revinfo
(
rev INTEGER GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ),
revtstmp BIGINT,
PRIMARY KEY (rev)
);
CREATE SEQUENCE hibernate_sequence INCREMENT 1 MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
Here is "application.properties" (app/test/java/resources):
spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver
spring.datasource.url=jdbc:tc:postgresql://localhost:5433/test
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=validate
spring.jackson.default-property-inclusion=NON_NULL
spring.flyway.baselineOnMigrate=true
spring.flyway.check-location=true
spring.flyway.locations=classpath:db/migration
spring.flyway.schemas=public
spring.flyway.enabled=true
Also in the same directory I have container-license-acceptance.txt file.
Inside "build.gradle" I added the following lines (app/build.gradle):
dependencies {
[...]
testImplementation "org.testcontainers:junit-jupiter:1.11.3"
testImplementation "org.testcontainers:postgresql:1.11.3"
}
Inside BaseInitTest file, I have the following lines (app/test/java/com):
@Testcontainers
@SpringBootTest
public class BaseIntTest {
@Container
private static final PostgreSQLContainer<?> container = new PostgreSQLContainer<>();
[...]
I don't understand, how can the same tests pass at first, but fail when I move them to docker container?
Solution 1:[1]
Thank you @M. Deinum and Mark Bramnik!
I found out that the issue is with Postgres version. For some reason by default docker image is created with old version 9.6.12, but sql script GENERATED BY DEFAULT was added to Postgres with version 10.
Solution 1 (Update the sql script to older version):
CREATE TABLE revinfo
(
rev INTEGER PRIMARY KEY NOT NULL,
revtstmp BIGINT
);
Solution 2: Changed docker image version to 11.2 by creating CustomPostgreSQLContainer file in the project.
import org.testcontainers.containers.PostgreSQLContainer;
public class CustomPostgreSQLContainer extends PostgreSQLContainer<CustomPostgreSQLContainer> {
private static final String IMAGE_VERSION = "postgres:11.2";
private static CustomPostgreSQLContainer container;
CustomPostgreSQLContainer() {
super(IMAGE_VERSION);
}
public static CustomPostgreSQLContainer getInstance() {
if (container == null) {
container = new CustomPostgreSQLContainer();
}
return container;
}
@Override
public void start() {
super.start();
System.setProperty("spring.datasource.url", container.getJdbcUrl());
System.setProperty("spring.datasource.username", container.getUsername());
System.setProperty("spring.datasource.password", container.getPassword());
}
@Override
public void stop() {
//do nothing, JVM handles shut down
}
}
And updating BaseIntTest file:
@Testcontainers
@SpringBootTest
public class BaseIntTest {
@Container
private static final PostgreSQLContainer<?> container = CustomPostgreSQLContainer.getInstance();
And last removing two lines from test application.properties file:
spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver
spring.datasource.url=jdbc:tc:postgresql://localhost:5433/test
Solution 2:[2]
It looks like the test container with the database has started successfully, so no issue there, you're getting an empty database.
Then you try running the flyway and this fails. Flyway in spring boot works during the initialization of the spring application context, so the actual migration runs while the application context gets initialized, so the migration failure looks like a spring failure.
The reason, however, is logged: the migration file has an invalid content:
Migration V1__initial_user.sql failed
-------------------------------------
SQL State : 42601
Error Code : 0
Message : ERROR: syntax error at or near "GENERATED"
Position: 45
Location : db/migration/V1__initial_user.sql (/Users/villemossip/Desktop/GRP/GRP-
SAS/application/build/resources/main/db/migration/V1__initial_user.sql)
Line : 36
Statement : CREATE TABLE revinfo
(
rev INTEGER GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ),
revtstmp BIGINT,
PRIMARY KEY (rev)
)
This GENERATED BY
is unsupported.
Why? Probably your docker image includes the version of RDBMS that doesn't support this syntax. So it differs from the DB that you use in a local environment without docker.
In any case it's not about docker, spring or flyway but about the DB and the migration code.
In terms of resolution, I suggest running the docker image of the DB directly (without java, testcontainers and flyway). When it runs, just run this migration "manually" in pgadmin or something. You're expected to see the same error.
Solution 3:[3]
The problem in my case was because of using spring.datasource.url=jdbc:postgres://localhost:5432/todoListDb
instead of
spring.datasource.url=jdbc:postgresql://localhost:5432/todoListDb
(postgres instead of PostgreSQL) in my application.properties file
So try to use the right URL for your database and verify if there is a typo in your url
Solution 4:[4]
One reason for this issue was missing docker DB version: <embedded-database-spring-test.version>2.0.1</embedded-database-spring-test.version>
By adding this specific version, it worked for me.
Solution 5:[5]
In my case I added in my application.properties file
spring.flyway.baselineOnMigrate = true
and I had also to start from version 1.1 instead of 1 otherwise flyway throws an error (flyway 8.0.5)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Tambet Tamm |
Solution 2 | Mark Bramnik |
Solution 3 | Mohammed NAIMI |
Solution 4 | Balasaheb Nimse |
Solution 5 | Roberto Petrilli |