Skip to content

audit_trail table not created in MySQL #135

@sarbogast

Description

@sarbogast

Up until now I was using the default H2 database in my project.
Now I'm migrating to using a regular MySQL database.
My datasource is configured with dbCreate = 'create-drop' so it should recreate all tables on startup.
I also enabled SQL logging to make sure that the tables are all created. And indeed in the logs, I have the following SQL query:

create table audit_trail (
    id varchar(255) not null,
    actor varchar(255),
    class_name varchar(255),
    date_created datetime not null,
    event_name varchar(255),
    last_updated datetime not null,
    new_value varchar(65534),
    old_value varchar(65534),
    persisted_object_id varchar(255),
    persisted_object_version bigint,
    property_name varchar(255),
    uri varchar(255),
    primary key (id)
) ENGINE=InnoDB`

And yet, once my application has started, there is no trace of this table in my database.

I am using Grails 3.2.6, with MySQL connector 6.0.6. The default generator for my identifiers is uuid2, which is why I commented out this instruction in the AuditTrail class:

/**
     * AuditTrails are reported to the AuditLog table.
     * This requires you to set up a table or allow
     * Grails to create a table for you. (e.g. DDL or db-migration plugin)
     */
class AuditTrail implements Serializable {
    @SuppressWarnings("GroovyUnusedDeclaration")
    private static final long serialVersionUID = 1L

    @SuppressWarnings("GroovyUnusedDeclaration")
    static auditable = false

    String id
    Date dateCreated
    Date lastUpdated

    String actor
    String uri
    String className
    String persistedObjectId
    Long persistedObjectVersion = 0

    String eventName
    String propertyName
    String oldValue
    String newValue

    static constraints = {
        actor(nullable: true)
        uri(nullable: true)
        className(nullable: true)
        persistedObjectId(nullable: true)
        persistedObjectVersion(nullable: true)
        eventName(nullable: true)
        propertyName(nullable: true)

        // for large column support (as in < 1.0.6 plugin versions), use
        oldValue(nullable: true, maxSize: 65534)
        newValue(nullable: true, maxSize: 65534)
    }

    static mapping = {

        // Set similiar when you used "auditLog.tablename" in < 1.1.0 plugin version.
        // table 'audit_log'

        // Remove when you used "auditLog.cacheDisabled = true" in < 1.1.0 plugin version.
        cache usage: 'read-only', include: 'non-lazy'

        // Set similar when you used "auditLog.useDatasource" in < 1.1.0 plugin version.
        // datasource "yourdatasource"

        // Set similar when you used "auditLog.idMapping" in < 1.1.0 plugin version. Example:
        // id generator: 'uuid2', type: 'string', length: 36

        // no HQL queries package name import (was default in 1.x version)
        // autoImport false

        //noinspection GroovyAssignabilityCheck
        version false
    }

    /**
     * Deserializer that maps a stored map onto the object
     * assuming that the keys match attribute properties.
     */
    private void readObject(ObjectInputStream input) throws IOException, ClassNotFoundException {
        def map = input.readObject()
        map.each { k, v -> this."$k" = v }
    }

    /**
     * Because Closures do not serialize we can't send the constraints closure
     * to the Serialize API so we have to have a custom serializer to allow for
     * this object to show up inside a webFlow context.
     */
    private void writeObject(ObjectOutputStream out) throws IOException {
        def map = [
                id: id,
                dateCreated: dateCreated,
                lastUpdated: lastUpdated,

                actor: actor,
                uri: uri,
                className: className,
                persistedObjectId: persistedObjectId,
                persistedObjectVersion: persistedObjectVersion,

                eventName: eventName,
                propertyName: propertyName,
                oldValue: oldValue,
                newValue: newValue,
        ]
        out.writeObject(map)
    }

    @Override
    String toString() {
        String actorStr = actor ? "user ${actor}" : "user ?"
        "audit log ${dateCreated} ${actorStr} " +
                "${eventName} ${className} " +
                "id:${persistedObjectId} version:${persistedObjectVersion}"
    }
}

My audit logging configuration is the following:

grails.plugin.auditLog.auditDomainClassName = 'com.adessa.unbox.AuditTrail'
grails.plugin.auditLog.logIds = true
grails {
    plugin {
        auditLog {
            actorClosure = { request, session ->
                if (request.applicationContext.springSecurityService.principal instanceof String) {
                    return request.applicationContext.springSecurityService.principal
                }
                def username = request.applicationContext.springSecurityService.principal?.username
                if (grails.plugin.springsecurity.SpringSecurityUtils.isSwitched()) {
                    username = grails.plugin.springsecurity.SpringSecurityUtils.switchedUserOriginalUsername + " AS " + username
                }
                return username
            }
        }
    }
}

And when I try to run the create table query I get in the logs on the DB itself, it works fine, indicating there is not error there.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions