/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.core.execution;
import org.mule.runtime.core.api.MuleContext;
import org.mule.runtime.core.api.Event;
import org.mule.runtime.core.api.construct.FlowConstruct;
import org.mule.runtime.core.api.exception.MessagingExceptionHandler;
import org.mule.runtime.core.api.execution.ExecutionCallback;
import org.mule.runtime.core.api.execution.ExecutionTemplate;
import org.mule.runtime.core.api.transaction.TransactionConfig;
import org.mule.runtime.core.transaction.MuleTransactionConfig;
/**
* Creates an execution context that should be used when: - A flow execution starts because a message was received by a
* MessageReceiver - Any other entry point of execution with no parent execution context
* <p>
* Created a ExecutionTemplate that will: Resolve non xa transactions created before it if the TransactionConfig action requires
* it suspend-resume xa transaction created before it if the TransactionConfig action requires it start a transaction if required
* by TransactionConfig action resolve transaction if was started by this TransactionTemplate route any exception to exception
* strategy if it was not already routed to it
*/
public class TransactionalErrorHandlingExecutionTemplate implements ExecutionTemplate<Event> {
private ExecutionInterceptor<Event> executionInterceptor;
private TransactionalErrorHandlingExecutionTemplate(MuleContext muleContext,
MessagingExceptionHandler messagingExceptionHandler,
FlowConstruct flowConstruct, boolean resolveAnyTransaction) {
this(muleContext, new MuleTransactionConfig(), messagingExceptionHandler, flowConstruct, resolveAnyTransaction);
}
private TransactionalErrorHandlingExecutionTemplate(MuleContext muleContext, TransactionConfig transactionConfig,
MessagingExceptionHandler messagingExceptionHandler,
FlowConstruct flowConstruct, boolean resolveAnyTransaction) {
final boolean processTransactionOnException = true;
ExecutionInterceptor<Event> tempExecutionInterceptor = new ExecuteCallbackInterceptor<>();
tempExecutionInterceptor = new CommitTransactionInterceptor(tempExecutionInterceptor);
tempExecutionInterceptor = new HandleExceptionInterceptor(tempExecutionInterceptor, messagingExceptionHandler, flowConstruct);
tempExecutionInterceptor =
new BeginAndResolveTransactionInterceptor<>(tempExecutionInterceptor, transactionConfig, muleContext,
processTransactionOnException, resolveAnyTransaction);
tempExecutionInterceptor = new ResolvePreviousTransactionInterceptor<>(tempExecutionInterceptor, transactionConfig);
tempExecutionInterceptor = new SuspendXaTransactionInterceptor<>(tempExecutionInterceptor, transactionConfig,
processTransactionOnException);
tempExecutionInterceptor = new ValidateTransactionalStateInterceptor<>(tempExecutionInterceptor, transactionConfig);
tempExecutionInterceptor = new IsolateCurrentTransactionInterceptor(tempExecutionInterceptor, transactionConfig);
tempExecutionInterceptor = new ExternalTransactionInterceptor<>(tempExecutionInterceptor, transactionConfig, muleContext);
this.executionInterceptor = new RethrowExceptionInterceptor(tempExecutionInterceptor);
}
private TransactionalErrorHandlingExecutionTemplate(MuleContext muleContext, TransactionConfig transactionConfig,
FlowConstruct flowConstruct, boolean resolveAnyTransaction) {
this(muleContext, transactionConfig, null, flowConstruct, resolveAnyTransaction);
}
/**
* Creates a TransactionalErrorHandlingExecutionTemplate to be used as first processing template in a flow using no transaction
* configuration
*
* @param muleContext MuleContext for this application
* @param messagingExceptionHandler exception listener to use for any MessagingException thrown
*/
public static TransactionalErrorHandlingExecutionTemplate createMainExecutionTemplate(MuleContext muleContext,
FlowConstruct flowConstruct,
MessagingExceptionHandler messagingExceptionHandler) {
return new TransactionalErrorHandlingExecutionTemplate(muleContext, messagingExceptionHandler, flowConstruct, true);
}
/**
* Creates a TransactionalErrorHandlingExecutionTemplate to be used as first processing template in a flow
*
* @param muleContext MuleContext for this application
* @param transactionConfig Transaction configuration
* @param messagingExceptionHandler Exception listener for any MessagingException thrown
*/
public static TransactionalErrorHandlingExecutionTemplate createMainExecutionTemplate(MuleContext muleContext,
FlowConstruct flowConstruct,
TransactionConfig transactionConfig,
MessagingExceptionHandler messagingExceptionHandler) {
return new TransactionalErrorHandlingExecutionTemplate(muleContext, transactionConfig, messagingExceptionHandler,
flowConstruct, true);
}
/**
* Creates a TransactionalErrorHandlingExecutionTemplate to be used as first processing template in a flow using no particular
* exception listener. Exception listener configured in the flow within this ExecutionTemplate is executed will be used.
*
* @param muleContext MuleContext for this application
* @param transactionConfig Transaction configuration
*/
public static TransactionalErrorHandlingExecutionTemplate createMainExecutionTemplate(MuleContext muleContext,
FlowConstruct flowConstruct,
TransactionConfig transactionConfig) {
return new TransactionalErrorHandlingExecutionTemplate(muleContext, transactionConfig, flowConstruct, true);
}
/**
* Creates a TransactionalErrorHandlingExecutionTemplate for inner scopes within a flow
*
* @param muleContext
* @param transactionConfig
* @return
*/
public static TransactionalErrorHandlingExecutionTemplate createScopeExecutionTemplate(MuleContext muleContext,
FlowConstruct flowConstruct,
TransactionConfig transactionConfig,
MessagingExceptionHandler messagingExceptionHandler) {
return new TransactionalErrorHandlingExecutionTemplate(muleContext, transactionConfig, messagingExceptionHandler,
flowConstruct, false);
}
@Override
public Event execute(ExecutionCallback<Event> executionCallback) throws Exception {
return this.executionInterceptor.execute(executionCallback, new ExecutionContext());
}
}