Adding a Database Platform
Adding a database engine to the Spring integration has two layers, and the first is usually already done for you:
- The integration itself audits any engine core supports, with no code change.
DatabaseAuditTestConfigurationdetects the platform from the liveDataSourceat runtime, so once core recognizes the engine, the wiring just works. - The archetype needs a branch to generate a runnable Testcontainers demo harness for the new engine.
So the real work here is the archetype’s database-selection seam. First make sure core supports the engine — follow the core Adding a Database Platform guide — then do the steps below.
Layer 1 — the integration is automatic
DatabaseAuditSuite calls DatabasePlatform.fromDataSource(dataSource) and builds the catalog, JPA, and
capture-scan audits for whatever platform comes back. The plan-based runtime audits (Join/OrderBy/WhereClause)
are wired only when the detected platform is PostgreSQL, so on any other engine the facade’s runtime and
all-family runs stay clean instead of failing fast on a PostgreSQL-only audit. Nothing in
DatabaseAuditTestConfiguration, DatabaseAuditSuite, or the assertion beans names a specific engine — so
there is nothing to change here when core adds one. (The IT DatabaseAuditTestConfigurationIT already proves a
non-PostgreSQL suite omits the plan assertions.)
Layer 2 — the archetype demo-harness seam
The archetype’s databasePlatform property (postgresql default, plus mysql, mariadb) selects the demo
container, the JDBC driver, and which runtime ITs are generated. Adding an engine means adding one branch to
each Velocity template that switches on it. Copy the existing mysql/mariadb branches — they are the model
for a non-PostgreSQL engine.
Step 1 — pom.xml: driver + Testcontainers module
In archetype-resources/pom.xml, add a branch to the #if($databasePlatform == 'mysql') … #elseif … #else
chain that pulls the engine’s Testcontainers module and JDBC driver (test scope):
#elseif($databasePlatform == 'newengine')
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-newengine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.newengine</groupId>
<artifactId>newengine-jdbc</artifactId>
<scope>test</scope>
</dependency>Step 2 — DemoDatabaseTestConfig.java: the container
In archetype-resources/src/test/java/app/DemoDatabaseTestConfig.java, add branches to three switches: the image
default, the Testcontainers container-class import, and the container field + start():
#elseif($databasePlatform == 'newengine')
#set($image = 'newengine:1')
...
#elseif($databasePlatform == 'newengine')
import org.testcontainers.newengine.NewEngineContainer;
...
#elseif($databasePlatform == 'newengine')
private static final NewEngineContainer DATABASE =
new NewEngineContainer(DockerImageName.parse("${image}"));
static {
DATABASE.start();
}Leave the preferQueryMode=simple URL parameter on the PostgreSQL branch only — it is a PostgreSQL JDBC
property the plan audits require, and those audits do not run on other engines.
Step 3 — application.properties: schema name
In archetype-resources/src/test/resources/application.properties, confirm the existing non-PostgreSQL branch
holds for the new engine, and widen it if not:
- Schema name. MySQL and MariaDB have no
publicschema — their Testcontainers database istest— so whenschemaNameis left at its PostgreSQL-oriented default the harness scanstestinstead. If the new engine also lacks apublicschema, the existing#if($databasePlatform != 'postgresql' && $schemaName == 'public')branch covers it.
The primary-key audit’s built-in Liquibase-bookkeeping-table exclusion matches case-insensitively, so an engine
that upper-cases unquoted identifiers (as MySQL/MariaDB do for DATABASECHANGELOG) needs no properties workaround.
The Liquibase changelog (db.changelog-master.xml) is engine-agnostic by design — note its comment about adding
the foreign key after its index so engines that auto-index foreign keys (MySQL, MariaDB) do not create a
redundant one. Verify the new engine reaches the same clean end state.
Step 4 — metadata and the post-generate script
archetype-metadata.xml— extend thedatabasePlatformproperty’s doc comment to list the new accepted value. (The property is free-form with apostgresqldefault; there is no enum to update.)archetype-post-generate.groovy— the plan ITs (Join/OrderBy/WhereClause) are deleted for anydatabasePlatform != 'postgresql', so a new non-PostgreSQL engine is handled with no change: it keeps the catalog, JPA, and unconditional-mutation ITs (andRepositoryWorkloadIT, which primes the capture the mutation audit needs) and drops the three plan ITs automatically.
Step 5 — add a self-test sample
The archetype’s own build generates and runs a sample per engine. Mirror the MySQL sample at
archetype/src/test/resources/projects/full-mysql/: create projects/full-newengine/ with an
archetype.properties (set databasePlatform=newengine, and databaseImage to pin a tag) and a goal.txt
containing verify. This runs the generated harness against a Testcontainers instance of the engine on every
build — the real end-to-end proof.
Important: archetype.properties in a self-test sample must list every property the templates reference —
the integration-test mojo does not apply the metadata defaults the way archetype:generate does. Copy the full
list from full-mysql/archetype.properties.
Step 6 — document it
Add the engine to the databasePlatform row of the Archetype page’s property table (and its
per-platform image default and any schema caveat).
Checklist
- Core supports the engine (its own guide) — the integration then audits it with no change.
pom.xmlbranch: Testcontainers module + JDBC driver.DemoDatabaseTestConfig.javabranches: image default, container import, container field +start().application.properties: schema remap covers the engine.archetype-metadata.xmldoc comment lists the new value; post-generate plan-IT deletion verified.projects/full-newengine/self-test sample (archetype.propertieswith the full property list +goal.txt).- Archetype property table updated;
.\mvnw.cmd clean installgreen (Docker required).

