envers-validation-maven-plugin
This is a maven plugin which validates the structure and content of audit revisions generated/managed by hibernate-envers.
This plugin is especially useful for databases where the table structure or content is not always generated by Envers. I.e. in databases where DBA sometimes runs a custom scrip to fix high priority issues or where release scripts are generated by another framework.
Warnings:
- Current version assumes the default settings of envers as described in: https://docs.jboss.org/envers/docs/#configuration
What the plugin does
The plugin connects with your database and will inform you of the following:
- Any unknown audit or content table
- If one or more audit tables specified in the whitelist are not present in the database.
- If a table exists with a name that ends in _AUD but the table name is not present in the whitelist, assuming that only audit tables end in _AUD.
- If a table was found with a foreign key to the revinfo table but the table name is not present in the whitelist.
- If an audit table exists but the content table does not.
- Incorrect structure of the audit table
- A column that is present in the audited table, but not in the audit table (and is not present in the whitelist).
- A primary key for an audit table which does not match with the primary key of the content table. (Primary key of an audit table should consist of the primary key columns of the content table + the rev column.)
- An audit table does not have a foreign key to the revinfo table.
- If a column in the audit table is nonnull but the column is not part of the primary key, as this prevents Envers from inserting 'Remove' revisions.
- Incorrect revisions, for example:
- If the history of a specific record is invalid. For example: Starting with an 'Modify' or 'Remove' revision, as these can only exist after an 'Add' revision and indicates missing revisions.
- If the content has a column 'ENABLED' and the value of this column = 'true', but the latest revision has a value of 'false' then a validation error will be thrown.
- The content no longer exists in the content table, but the latest revision for the primary key is 'Add' or 'Modify' instead of 'Remove'.
- The latest revision is 'Remove' but there is still a record in the content table.
- Remove revisions with nonnull values in nullable columsn for a Remove revision. Remove revisions should only have values in the primary key columns and the revtype column.
- Revisions without a revtype.
How to use the plugin
Pom.xml
<plugin>
<groupId>com.github.zeger-tak</groupId>
<artifactId>envers-validation-maven-plugin</artifactId>
<version>${envers-validation-version}</version>
<configuration>
<!-- Property file can contain zero or more of the other parameters, but each of these parameters will not be overriden if it is already provided in the pom.xml. -->
<connectionPropertyFile>src/test/resources/connection.properties</connectionPropertyFile>
<!--Add the following to ignore specific validations-->
<ignorables>
<ignorable>RevisionValidator</ignorable> <!--To ignore the entire validator. -->
<ignorable>RevisionValidator.validateAllRecordsInContentTableHaveAValidLatestRevision</ignorable> <!--To ignore a specific validation method.-->
<ignorable>RevisionValidator.validateAllRecordsInContentTableHaveAValidLatestRevision.CONTENT_TABLE_NAME</ignorable> <!--To ignore a specific run of a validation method.-->
</ignorables>
<url>JDBC connection string.</>
<username>Database username used to connect with the database.</username>
<password>Database user password used to connect with the database.</password>
<driver>Database driver class used to connect with the database.</driver>
<schema>
Optional parameter specifying for which schema the validations should run.
Schema will be inferred from the url if no entry is provided for this parameter.
Warning: If the schema is not provided and cannot be inferred from the url, metadata for all authorized schemas will be retrieved.
</schema>
<auditTableInformationFile>Contains audit table information.</>
</configuration>
<dependencies>
<!-- Add this dependency when running against an oracle db, -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.4</version>
</dependency>
<!-- Add this dependency when running against a postgreql db, -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.3-1102-jdbc41</version>
</dependency>
</dependencies>
</plugin>
Connection property file
The connection property file may contain any of the other properties:
url=jdbc:postgresql://localhost/schemaname #example of a jdbc connection url.
driver=org.postgresql.Driver #example of the driver class.
username=dbuser
password=dbpassword
auditTableInformationFile=src/test/resources/known_audit_tables.xml #relative path to the audit table information file.
Audit table information file
The audit table information file is an XML file validated against the XSD file found under: src/main/resources/xsd/configuration-1.0.xsd An example XML file:
<?xml version="1.0" encoding="UTF-8"?>
<configurationFile xmlns="http://zeger-tak.github.com/envers-validation/configuration_1-0">
<auditTableInformation>
<auditTableName>EXAMPLE_TABLE_AUD</auditTableName>
<auditTableParentName>EXAMPLE_TABLE_PARENT_AUD</auditTableParentName>
<contentTableName>EXAMPLE_TABLE</contentTableName>
</auditTableInformation>
<auditTableInformation>
<auditTableName>EXAMPLE_TABLE_PARENT_AUD</auditTableName>
<contentTableName>EXAMPLE_TABLE_PARENT</contentTableName>
</auditTableInformation>
<auditTableInformation>
<auditTableName>EXAM_TABLE_WITHOUT_PARENTS_AUD</auditTableName>
<columnNamePresentInContentTableButNotInAuditTable>VERSION</columnNamePresentInContentTableButNotInAuditTable>
</auditTableInformation>
</configurationFile>
Executing the plugin
The plugin can now be executed with the following statement envers-validation:validate
Or added to a phase and automatically executed during the verify phase by adding the following lines to the pom.xml
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>