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

org.flowable.engine.impl.event.logger.EventLogger Maven / Gradle / Ivy

There is a newer version: 7.0.1
Show newest version
/* 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.flowable.engine.impl.event.logger;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.flowable.common.engine.api.delegate.event.AbstractFlowableEventListener;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.impl.context.Context;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.common.engine.impl.interceptor.CommandContextCloseListener;
import org.flowable.common.engine.impl.runtime.Clock;
import org.flowable.engine.impl.event.logger.handler.ActivityCompensatedEventHandler;
import org.flowable.engine.impl.event.logger.handler.ActivityCompletedEventHandler;
import org.flowable.engine.impl.event.logger.handler.ActivityErrorReceivedEventHandler;
import org.flowable.engine.impl.event.logger.handler.ActivityMessageEventHandler;
import org.flowable.engine.impl.event.logger.handler.ActivitySignaledEventHandler;
import org.flowable.engine.impl.event.logger.handler.ActivityStartedEventHandler;
import org.flowable.engine.impl.event.logger.handler.EventLoggerEventHandler;
import org.flowable.engine.impl.event.logger.handler.ProcessInstanceEndedEventHandler;
import org.flowable.engine.impl.event.logger.handler.ProcessInstanceStartedEventHandler;
import org.flowable.engine.impl.event.logger.handler.SequenceFlowTakenEventHandler;
import org.flowable.engine.impl.event.logger.handler.TaskAssignedEventHandler;
import org.flowable.engine.impl.event.logger.handler.TaskCompletedEventHandler;
import org.flowable.engine.impl.event.logger.handler.TaskCreatedEventHandler;
import org.flowable.engine.impl.event.logger.handler.VariableCreatedEventHandler;
import org.flowable.engine.impl.event.logger.handler.VariableDeletedEventHandler;
import org.flowable.engine.impl.event.logger.handler.VariableUpdatedEventHandler;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * @author Joram Barrez
 */
public class EventLogger extends AbstractFlowableEventListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(EventLogger.class);

    private static final String EVENT_FLUSHER_KEY = "eventFlusher";

    protected Clock clock;
    protected ObjectMapper objectMapper;

    // Mapping of type -> handler
    protected Map> eventHandlers = new HashMap<>();

    // Listeners for new events
    protected List listeners;

    public EventLogger() {
        initializeDefaultHandlers();
    }

    public EventLogger(Clock clock, ObjectMapper objectMapper) {
        this();
        this.clock = clock;
        this.objectMapper = objectMapper;
    }

    protected void initializeDefaultHandlers() {
        addEventHandler(FlowableEngineEventType.TASK_CREATED, TaskCreatedEventHandler.class);
        addEventHandler(FlowableEngineEventType.TASK_COMPLETED, TaskCompletedEventHandler.class);
        addEventHandler(FlowableEngineEventType.TASK_ASSIGNED, TaskAssignedEventHandler.class);

        addEventHandler(FlowableEngineEventType.SEQUENCEFLOW_TAKEN, SequenceFlowTakenEventHandler.class);

        addEventHandler(FlowableEngineEventType.ACTIVITY_COMPLETED, ActivityCompletedEventHandler.class);
        addEventHandler(FlowableEngineEventType.ACTIVITY_STARTED, ActivityStartedEventHandler.class);
        addEventHandler(FlowableEngineEventType.ACTIVITY_SIGNALED, ActivitySignaledEventHandler.class);
        addEventHandler(FlowableEngineEventType.ACTIVITY_MESSAGE_RECEIVED, ActivityMessageEventHandler.class);
        addEventHandler(FlowableEngineEventType.ACTIVITY_MESSAGE_WAITING, ActivityMessageEventHandler.class);

        addEventHandler(FlowableEngineEventType.ACTIVITY_COMPENSATE, ActivityCompensatedEventHandler.class);
        addEventHandler(FlowableEngineEventType.ACTIVITY_ERROR_RECEIVED, ActivityErrorReceivedEventHandler.class);

        addEventHandler(FlowableEngineEventType.VARIABLE_CREATED, VariableCreatedEventHandler.class);
        addEventHandler(FlowableEngineEventType.VARIABLE_DELETED, VariableDeletedEventHandler.class);
        addEventHandler(FlowableEngineEventType.VARIABLE_UPDATED, VariableUpdatedEventHandler.class);
    }

    @Override
    public void onEvent(FlowableEvent event) {
        EventLoggerEventHandler eventHandler = getEventHandler(event);
        if (eventHandler != null) {

            // Events are flushed when command context is closed
            CommandContext currentCommandContext = Context.getCommandContext();
            EventFlusher eventFlusher = (EventFlusher) currentCommandContext.getAttribute(EVENT_FLUSHER_KEY);

            if (eventFlusher == null) {

                eventFlusher = createEventFlusher();
                if (eventFlusher == null) {
                    eventFlusher = new DatabaseEventFlusher(); // Default
                }
                currentCommandContext.addAttribute(EVENT_FLUSHER_KEY, eventFlusher);

                currentCommandContext.addCloseListener(eventFlusher);
                currentCommandContext
                        .addCloseListener(new CommandContextCloseListener() {

                            @Override
                            public void closing(CommandContext commandContext) {
                            }

                            @Override
                            public void closed(CommandContext commandContext) {
                                // For those who are interested: we can now broadcast the events were added
                                if (listeners != null) {
                                    for (EventLoggerListener listener : listeners) {
                                        listener.eventsAdded(EventLogger.this);
                                    }
                                }
                            }

                            @Override
                            public void afterSessionsFlush(CommandContext commandContext) {
                            }

                            @Override
                            public void closeFailure(CommandContext commandContext) {
                            }
                            
                            @Override
                            public Integer order() {
                                return 5;
                            }
                            
                            @Override
                            public boolean multipleAllowed() {
                                return false;
                            }

                        });
            }

            eventFlusher.addEventHandler(eventHandler);
        }
    }

    // Subclasses can override this if defaults are not ok
    protected EventLoggerEventHandler getEventHandler(FlowableEvent event) {

        Class eventHandlerClass = null;
        if (event.getType().equals(FlowableEngineEventType.ENTITY_INITIALIZED)) {
            Object entity = ((FlowableEntityEvent) event).getEntity();
            if (entity instanceof ExecutionEntity) {
                ExecutionEntity executionEntity = (ExecutionEntity) entity;
                if (executionEntity.getProcessInstanceId().equals(executionEntity.getId())) {
                    eventHandlerClass = ProcessInstanceStartedEventHandler.class;
                }
            }
        } else if (event.getType().equals(FlowableEngineEventType.ENTITY_DELETED)) {
            Object entity = ((FlowableEntityEvent) event).getEntity();
            if (entity instanceof ExecutionEntity) {
                ExecutionEntity executionEntity = (ExecutionEntity) entity;
                if (executionEntity.getProcessInstanceId().equals(executionEntity.getId())) {
                    eventHandlerClass = ProcessInstanceEndedEventHandler.class;
                }
            }
        } else {
            // Default: dedicated mapper for the type
            eventHandlerClass = eventHandlers.get(event.getType());
        }

        if (eventHandlerClass != null) {
            return instantiateEventHandler(event, eventHandlerClass);
        }

        return null;
    }

    protected EventLoggerEventHandler instantiateEventHandler(FlowableEvent event,
            Class eventHandlerClass) {
        try {
            EventLoggerEventHandler eventHandler = eventHandlerClass.newInstance();
            eventHandler.setTimeStamp(clock.getCurrentTime());
            eventHandler.setEvent(event);
            eventHandler.setObjectMapper(objectMapper);
            return eventHandler;
        } catch (Exception e) {
            LOGGER.warn("Could not instantiate {}, this is most likely a programmatic error", eventHandlerClass);
        }
        return null;
    }

    @Override
    public boolean isFailOnException() {
        return false;
    }

    public void addEventHandler(FlowableEngineEventType eventType, Class eventHandlerClass) {
        eventHandlers.put(eventType, eventHandlerClass);
    }

    public void addEventLoggerListener(EventLoggerListener listener) {
        if (listeners == null) {
            listeners = new ArrayList<>(1);
        }
        listeners.add(listener);
    }

    /**
     * Subclasses that want something else than the database flusher should override this method
     */
    protected EventFlusher createEventFlusher() {
        return null;
    }

    public Clock getClock() {
        return clock;
    }

    public void setClock(Clock clock) {
        this.clock = clock;
    }

    public ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    public List getListeners() {
        return listeners;
    }

    public void setListeners(List listeners) {
        this.listeners = listeners;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy