Archetype

database-audits-spring-boot-integration-archetype scaffolds an audit test suite into a consumer’s project. Two generation modes are supported, controlled by the generateMode property:

  • project (default) — generates the abstract base IT class, all catalog/JPA/runtime audit ITs, and a Testcontainers demo harness for the chosen databasePlatform (PostgreSQL by default). Use this to start fresh with a self-contained, runnable example.
  • tests-only — generates only the audit test classes (no demo app, no entities, no DataSource setup, no RepositoryWorkloadIT). Use this when you already have a Spring Boot application and only want the audit ITs dropped in alongside your existing test infrastructure — your own tests prime the SQL capturer before the runtime audit ITs run.

The archetype also doubles as the project’s end-to-end test: the build generates and validates multiple samples on every clean installproject samples that run their integration tests against Testcontainers PostgreSQL and MySQL, and several tests-only samples (covering the default configuration, the projectDirectory option, and the parentClass option) that compile the generated sources to verify generation correctness.

Run archetype:generate from any directory. Use -DoutputDirectory to control where the generated project is written, or omit it to generate in the current directory.

Note: Generation is not idempotent. In project mode the plugin refuses to generate into a directory that already contains a pom.xml. In tests-only mode the post-generate copy step silently overwrites any existing file of the same name — see the tests-only section for the full warning.

Note: Replace VERSION in the commands and dependency snippet below with the latest released database-audits-spring-boot-integration version.

Generate the full project

mvn archetype:generate -DinteractiveMode=false \
  -DarchetypeGroupId=io.github.database-audits \
  -DarchetypeArtifactId=database-audits-spring-boot-integration-archetype \
  -DarchetypeVersion=VERSION \
  -DgenerateMode=project \
  -DgroupId=com.example \
  -DartifactId=demo \
  -Dpackage=com.example.demo \
  -DschemaName=public \
  -DschemaPropertyName=database.datasource.schema-name \
  -DparentClass=com.example.MySpringTestBase \
  -DdatabaseAuditsVersion=VERSION \
  -DspringBootVersion=4.1.0 \
  -DdatabasePlatform=postgresql \
  -DdatabaseImage=none \
  -DdisabledTests=false \
  -DreportFormat=asciidoc \
  -DfixFormat=liquibase-xml \
  -DfixPlacement=both \
  -DdataSourceName=none \
  -DoutputDirectory=/path/to/output

Generate tests only (for an existing project)

Point -DoutputDirectory at a pom-less scratch directory (e.g. target/audit-scratch; use a path valid on your OS — a Unix-style /tmp path is mis-resolved on Windows) — the plugin refuses to generate into a directory containing a pom.xml, and when run from inside a Maven project it tries to add the result as a <module>. The scratch location avoids both pitfalls; only the post-generate copy step writes to your project.

Set -DprojectDirectory to your project root: an absolute path, or a path relative to the directory you run the command from — use . when you run from the project root itself. The post-generate script copies the generated src/ tree into projectDirectory and deletes the scratch directory.

Warning: The post-generate copy step silently overwrites any existing file of the same name in -DprojectDirectory without prompting or backing up. Re-running generation on a project that already contains generated files will clobber any customizations you have made to them. Commit or back up your changes before regenerating.

# Run from your project root. -DoutputDirectory is a throwaway scratch dir; -DprojectDirectory=. is your project.
mvn archetype:generate -DinteractiveMode=false \
  -DarchetypeGroupId=io.github.database-audits \
  -DarchetypeArtifactId=database-audits-spring-boot-integration-archetype \
  -DarchetypeVersion=VERSION \
  -DgenerateMode=tests-only \
  -DgroupId=com.example \
  -DartifactId=demo-audit-tests \
  -Dpackage=com.example.demo \
  -DschemaName=public \
  -DschemaPropertyName=database.datasource.schema-name \
  -DparentClass=com.example.MySpringTestBase \
  -DdatabaseAuditsVersion=VERSION \
  -DspringBootVersion=4.1.0 \
  -DdatabasePlatform=postgresql \
  -DdatabaseImage=none \
  -DdisabledTests=false \
  -DreportFormat=asciidoc \
  -DfixFormat=liquibase-xml \
  -DfixPlacement=both \
  -DdataSourceName=none \
  -DoutputDirectory=target/audit-scratch \
  -DprojectDirectory=.

Note: On PowerShell, replace each trailing \ with a backtick ( ` ) as the very last character on the line — no trailing space.

Properties

All properties have defaults; none need to be specified unless the default is wrong for your project. Pass only the ones that differ.

Property Default Modes Description
generateMode project Generation mode. project generates the full demo harness plus audit ITs. tests-only generates only the audit ITs, writing files directly into your existing project tree — no pom.xml, no demo harness.
schemaName public both Database schema the catalog audits scan. Written as the value of schemaPropertyName in application.properties (project mode) or read from your existing configuration (tests-only mode). MySQL and MariaDB have no public schema, so when left at the default on those engines the demo harness scans its Testcontainers database (test) instead; set it explicitly to override.
schemaPropertyName database.datasource.schema-name both Spring property key the catalog ITs read via @Value to obtain the schema name. Set this to match the property key your application already uses so the audit ITs share your existing configuration.
parentClass none both Fully qualified class name of your existing Spring Boot test base class, e.g. com.example.MySpringTestBase. When set, each audit IT extends it directly and AbstractDatabaseAuditIT is not generated. Your class must carry @SpringBootTest and — for the single-datasource suite — @Import(DatabaseAuditTestConfiguration.class); with -DdataSourceName set, @Import(DatabaseAudit<Name>TestConfiguration.class) instead (the generated audit ITs carry no @Import of their own — the base class holds it). Leave as none to generate AbstractDatabaseAuditIT as the shared base.
databaseAuditsVersion VERSION project only Version of database-audits-spring-boot-integration written into the generated pom.xml. Not used in tests-only mode — add the dependency manually to your own pom.xml.
springBootVersion 4.1.0 project only Spring Boot parent version written into the generated pom.xml. Not used in tests-only mode.
databasePlatform postgresql both Database engine the audits target: postgresql (default), mysql, or mariadb. In project mode it drives the Testcontainers container and the JDBC driver + Testcontainers module in the generated pom.xml. In both modes it selects which runtime audit ITs are kept — the plan-based audits (Join/OrderBy/WhereClause index) are PostgreSQL-only, so they are kept for postgresql only and removed for the other engines (the post-generate script deletes their ITs); the catalog, JPA, and unconditional-mutation audits are kept on every engine.
databaseImage none project only Testcontainers image DemoDatabaseTestConfig starts, overriding the per-platform default (postgres:16, mysql:8, or mariadb:11). none selects that default; set it to pin a tag, e.g. postgres:17. Not used in tests-only mode.
disabledTests false both When true, annotates every generated test with JUnit’s @Disabled, so the suite is generated and compiles but does not run. (SchemaEntityValidationAuditIT is annotated on the class rather than the method, so its Spring context never loads.) Useful for scaffolding the audits into a project that does not pass them yet — remove the @Disabled annotations to enable audits one at a time.
reportFormat asciidoc both Format of the consolidated findings report the auto-registered listener writes when a run has findings: asciidoc, markdown, or text. Seeded into the generated junit-platform.properties as database-audits.report.format. See the Consolidated findings report guide.
fixFormat liquibase-xml both Per-finding remediation the report emits: liquibase-xml (a databaseChangeLog fragment), sql (raw DDL), or none (findings only). Seeded as database-audits.report.fix-format.
fixPlacement both both Where the report places each audit’s fixes: both (default — inline under each audit and in a consolidated section), inline (only under each audit), or section (only the consolidated block). Seeded as database-audits.report.fix-placement.
dataSourceName none both The datasource to audit when your application configures several peer datasources with no @Primary. When set (e.g. Reporting), the generated audit ITs target that one datasource, resolved by name: the archetype generates a DatabaseAudit<Name>TestConfiguration — a @Qualifier-based mirror of the stock config that builds a DatabaseAuditSuite from your named beans and exposes every *AuditAssertion bean — and the generated AbstractDatabaseAuditIT (or your specified base class) @Import`s it, not the individual ITs (so no datasource need be `@Primary, and the base does not import the stock config). Requires dataSourceBeanName and entityManagerFactoryBeanName. To audit several datasources, generate once per datasource into its own package. The value names the config class (PascalCase) and its capturer bean (camelCase), so it must be a valid Java identifier. Default none generates the single-datasource suite. See the Multiple datasources guide.
dataSourceBeanName none both The DataSource bean name the generated per-datasource config resolves via @Qualifier, e.g. reportingDataSource. Required when dataSourceName is set; ignored otherwise.
entityManagerFactoryBeanName none both The EntityManagerFactory bean name the generated per-datasource config resolves via @Qualifier, e.g. reportingEntityManagerFactory. Required when dataSourceName is set; ignored otherwise.
projectDirectory (empty) tests-only only Your project root — absolute or relative to where you run the command (. for current directory). Set alongside a scratch -DoutputDirectory when generating into an existing project. When omitted, files land under -DoutputDirectory. Resolved from the JVM system property (not archetype metadata); relative values resolve against PWD, falling back to user.dir.

What gets generated

generateMode=project (default)

<artifactId>/
├── pom.xml                              (Spring Boot parent, integration dependency, Failsafe config)
└── src/test/
    ├── java/<package>/
    │   ├── AbstractDatabaseAuditIT.java  (@SpringBootTest + @Import(DatabaseAuditTestConfiguration.class))
    │   ├── DemoApplication.java          (@SpringBootApplication for the test harness)
    │   ├── app/
    │   │   ├── Parent.java               (JPA entity)
    │   │   ├── ParentRepository.java
    │   │   ├── Child.java                (JPA entity with FK to Parent)
    │   │   ├── ChildRepository.java
    │   │   └── DemoDatabaseTestConfig.java (Testcontainers container + DynamicPropertyRegistrar)
    │   ├── catalog/
    │   │   ├── ForeignKeyIndexAuditIT.java
    │   │   ├── ForeignKeyNotNullAuditIT.java
    │   │   ├── ForeignKeyTypeMatchAuditIT.java
    │   │   ├── PrimaryKeyPresenceAuditIT.java
    │   │   └── RedundantIndexAuditIT.java
    │   ├── jpa/
    │   │   └── SchemaEntityValidationAuditIT.java
    │   └── runtime/
    │       ├── RepositoryWorkloadIT.java  (@Order(Integer.MIN_VALUE) — primes SQL capture)
    │       ├── JoinIndexAuditIT.java
    │       ├── OrderByIndexAuditIT.java
    │       ├── UnconditionalMutationAuditIT.java
    │       └── WhereClauseIndexAuditIT.java
    └── resources/
        ├── application.properties         (schema-name, ddl-auto=none, Liquibase changelog path)
        ├── junit-platform.properties      (ClassOrderer$OrderAnnotation + database-audits.report.* keys)
        └── db/changelog/
            └── db.changelog-master.xml    (parent + child tables with indexes)

generateMode=tests-only

The audit test classes are written directly into your project root (the -DprojectDirectory you set, falling back to -DoutputDirectory when omitted), not inside an <artifactId> subdirectory. No pom.xml is generated — the classes are meant to be added to your existing build.

src/test/
├── java/<package>/
│   ├── AbstractDatabaseAuditIT.java  (@SpringBootTest + @Import(DatabaseAuditTestConfiguration.class))
│   ├── catalog/
│   │   ├── ForeignKeyIndexAuditIT.java
│   │   ├── ForeignKeyNotNullAuditIT.java
│   │   ├── ForeignKeyTypeMatchAuditIT.java
│   │   ├── PrimaryKeyPresenceAuditIT.java
│   │   └── RedundantIndexAuditIT.java
│   ├── jpa/
│   │   └── SchemaEntityValidationAuditIT.java
│   └── runtime/
│       ├── JoinIndexAuditIT.java
│       ├── OrderByIndexAuditIT.java
│       ├── UnconditionalMutationAuditIT.java
│       └── WhereClauseIndexAuditIT.java
└── resources/
    └── junit-platform.properties      (ClassOrderer$OrderAnnotation + database-audits.report.* keys)

RepositoryWorkloadIT is not generated in this mode — your existing tests already prime the SQL capturer. The runtime audit ITs are annotated @Order(Integer.MAX_VALUE) and run last, after your own test suite has exercised the repositories.

Add the database-audits-spring-boot-integration dependency to your own pom.xml:

<dependency>
  <groupId>io.github.database-audits</groupId>
  <artifactId>database-audits-spring-boot-integration</artifactId>
  <version>VERSION</version>
  <scope>test</scope>
</dependency>

Running the generated project

generateMode=project

cd demo
# Requires Docker (Testcontainers starts PostgreSQL automatically)
mvn verify

DemoDatabaseTestConfig starts a shared container for the chosen databasePlatform (PostgreSQL by default) and registers its JDBC URL via DynamicPropertyRegistrar (on PostgreSQL it appends preferQueryMode=simple).

generateMode=tests-only

The generated tests compile against your existing Spring Boot test context. Run them using your normal mvn verify after wiring your own DataSource and @SpringBootApplication.

Notes on the generated code

  • Generated classes are pure Java with no Lombok. Dependencies are JUnit Jupiter, Spring Boot test, and this integration artifact only.
  • @Order annotations use JUnit’s org.junit.jupiter.api.Order, not Spring’s.
  • SchemaEntityValidationAuditIT validates Hibernate’s entity mappings against the live schema and reports every mismatch in one run; it runs under the default ddl-auto=none, not Hibernate’s fail-fast ddl-auto=validate.
  • Each catalog IT uses constants (e.g., EXCLUDED_TABLES, EXCLUDED_CONSTRAINTS) to name known/intentional exclusions. ForeignKeyIndexAuditIT and PrimaryKeyPresenceAuditIT call the no-exclusion overload directly to show that pattern as well.
  • With -DdataSourceName=Reporting -DdataSourceBeanName=… -DentityManagerFactoryBeanName=…, the generated ITs target that one datasource: a DatabaseAuditReportingTestConfiguration — a @Qualifier-based mirror of the stock config that resolves your named beans — is generated and the base class @Import`s it, so no datasource need be `@Primary. Generate once per datasource to audit several; see the Multiple datasources guide.

Using SNAPSHOT versions

archetype:generate resolves archetypes using repositories declared in ~/.m2/settings.xml, not in the project pom.xml. Maven’s settings.xml schema requires repositories inside a <profile> — there is no top-level <repositories> element. For snapshot versions, add this to ~/.m2/settings.xml once:

<settings>
  <profiles>
    <profile>
      <id>central-snapshots</id>
      <activation><activeByDefault>true</activeByDefault></activation>
      <repositories>
        <repository>
          <id>central-snapshots</id>
          <url>https://central.sonatype.com/repository/maven-snapshots/</url>
          <snapshots><enabled>true</enabled></snapshots>
          <releases><enabled>false</enabled></releases>
        </repository>
      </repositories>
    </profile>
  </profiles>
</settings>

GA releases resolve from Maven Central with no extra configuration.