All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aktivecortex.core.audit.AuditingUnitOfWorkListener Maven / Gradle / Ivy

/*
 * Copyright (C) 2012-2013. Aktive Cortex
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.aktivecortex.core.audit;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.axonframework.auditing.AuditDataProvider;
import org.axonframework.auditing.AuditLogger;
import org.axonframework.domain.AggregateRoot;
import org.axonframework.domain.DomainEventStream;
import org.axonframework.domain.Event;
import org.axonframework.domain.EventMetaData;
import org.axonframework.domain.MutableEventMetaData;
import org.axonframework.unitofwork.UnitOfWorkListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AuditingUnitOfWorkListener implements UnitOfWorkListener {

    private static final Logger logger = LoggerFactory.getLogger(AuditingUnitOfWorkListener.class);

    private final AuditDataProvider auditDataProvider;
    private final AuditLogger auditLogger;
    private final Object command;
    private final List recordedEvents = new ArrayList();
    private volatile Object returnValue;

    /**
     * Initialize a listener for the given command. The auditDataProvider is called before the
     * Unit Of Work is committed to provide the auditing information. The auditLogger is invoked after the
     * Unit Of Work is successfully committed.
     *
     * @param command           The command being audited
     * @param auditDataProvider The instance providing the information to attach to the events
     * @param auditLogger       The logger writing the audit
     */
    public AuditingUnitOfWorkListener(Object command, AuditDataProvider auditDataProvider, AuditLogger auditLogger) {
        this.auditDataProvider = auditDataProvider;
        this.auditLogger = auditLogger;
        this.command = command;
    }

    @Override
    public void afterCommit() {
        auditLogger.logSuccessful(command, returnValue, recordedEvents);
    }

    @Override
    public void onRollback(Throwable failureCause) {
        auditLogger.logFailed(command, failureCause, recordedEvents);
    }

    @Override
    public void onPrepareCommit(Set aggregateRoots, List events) {
        Map auditData = auditDataProvider.provideAuditDataFor(command);
        recordedEvents.addAll(collectEvents(aggregateRoots));
        recordedEvents.addAll(events);
        injectAuditData(auditData);
    }

    private List collectEvents(Set aggregateRoots) {
        List events = new ArrayList();
        for (AggregateRoot aggregateRoot : aggregateRoots) {
            DomainEventStream domainEventStream = aggregateRoot.getUncommittedEvents();
            while (domainEventStream.hasNext()) {
                events.add(domainEventStream.next());
            }
        }
        return events;
    }

    private void injectAuditData(Map auditData) {
        for (Event event : recordedEvents) {
            EventMetaData eventMetaData = event.getMetaData();
            if (!MutableEventMetaData.class.isInstance(eventMetaData)) {
                logger.warn("Unable to inject meta data into event of type [{}]. "
                        + "The EventMetaData field does not contain a subclass of MutableEventMetaData.",
                            event.getClass().getSimpleName());
            } else {
                MutableEventMetaData mutableMetaData = ((MutableEventMetaData) eventMetaData);
                for (Map.Entry entry : auditData.entrySet()) {
                    mutableMetaData.put(entry.getKey(), entry.getValue());
                }
            }
        }
    }

    @Override
    public void onCleanup() {
        // no resources to clean up
    }

    /**
     * Registers the return value of the command handler with the auditing context.
     *
     * @param returnValue The return value of the command handler, if any. May be null or {@link Void#TYPE
     *                    void}.
     */
    public void setReturnValue(Object returnValue) {
        this.returnValue = returnValue;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy