Using TestContainers 1.1.6, the following code produces a compile time error:
private static final PostgreSQLContainer postgres =
new PostgreSQLContainer("postgres:9.5.4")
.withDatabaseName("test")
.withEnv("PGDATA", CONTAINER_PGDATA)
.withFileSystemBind(HOST_PGDATA.toString(), CONTAINER_PGDATA, BindMode.READ_WRITE);
Compilation error:
/Users/my-user-name/my-project/my/path/to/IntegrationTest.java:71: error: incompatible types: GenericContainer cannot be converted to PostgreSQLContainer
.withFileSystemBind(HOST_PGDATA.toString(), CONTAINER_PGDATA, BindMode.READ_WRITE)
The problem stems from the fact that the PostgreSQLContainer class starts like this, with a recursive bound on its generic type parameter (à la class Enum<E extends Enum<E>>):
public class PostgreSQLContainer<SELF extends PostgreSQLContainer<SELF>>
extends JdbcDatabaseContainer<SELF>
So this is a generic class, but the documentation and example test case use it with no type parameter, as a raw type:
@Rule
public PostgreSQLContainer postgres = new PostgreSQLContainer();
And in this situation Java can't figure out that in my use of the withFileSytemBind() method, the SELF return type unifies with PostgreSQLContainer.
My workaround for this issue illustrates the fix:
// A dummy class whose sole purpose is to instantiate the `SELF`
// type parameter.
private static final class MyPostgreSQLContainer extends PostgreSQLContainer<MyPostgreSQLContainer> {
public MyPostgreSQLContainer(String dockerImageName) {
super(dockerImageName);
}
}
private static final MyPostgreSQLContainer postgres =
new MyPostgreSQLContainer("postgres:9.5.4")
.withDatabaseName("test")
.withEnv("PGDATA", CONTAINER_PGDATA)
.withFileSystemBind(HOST_PGDATA.toString(), CONTAINER_PGDATA, BindMode.READ_WRITE);
This argues that the existing "end user facing" classes like PostgreSQLContainer in the library ought to be split into two classes:
public abstract class AbstractPostgreSQLContainer<SELF extends AbstractPostgreSQLContainer<SELF>>
extends JdbcDatabaseContainer<SELF> {
...
}
public class PostgreSQLContainer extends AbstractPostgreSQLContainer<PostgreSQLContainer> {
...
}
People who want to extend PostgreSQLContainer should be discouraged from doing so as well, and pointed to AbstractPostgreSQLContainer as the proper class for extension. (Making PostgreSQLContainer a final class is one alternative here, but with the downside that it's a backwards-incompatible change.)
Using TestContainers 1.1.6, the following code produces a compile time error:
Compilation error:
The problem stems from the fact that the
PostgreSQLContainerclass starts like this, with a recursive bound on its generic type parameter (à laclass Enum<E extends Enum<E>>):So this is a generic class, but the documentation and example test case use it with no type parameter, as a raw type:
And in this situation Java can't figure out that in my use of the
withFileSytemBind()method, theSELFreturn type unifies withPostgreSQLContainer.My workaround for this issue illustrates the fix:
This argues that the existing "end user facing" classes like
PostgreSQLContainerin the library ought to be split into two classes:People who want to extend
PostgreSQLContainershould be discouraged from doing so as well, and pointed toAbstractPostgreSQLContaineras the proper class for extension. (MakingPostgreSQLContainera final class is one alternative here, but with the downside that it's a backwards-incompatible change.)