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

org.camunda.bpm.engine.impl.interceptor.CommandContextInterceptor Maven / Gradle / Ivy

There is a newer version: 7.22.0-alpha1
Show newest version
/*
 * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. Camunda licenses this file to you under the Apache License,
 * Version 2.0; 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.camunda.bpm.engine.impl.interceptor;


import org.camunda.bpm.engine.delegate.ProcessEngineServicesAware;
import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.camunda.bpm.engine.impl.cmd.CommandLogger;
import org.camunda.bpm.engine.impl.context.Context;
import org.camunda.bpm.engine.impl.context.ProcessEngineContextImpl;

/**
 * 

Interceptor used for opening the {@link CommandContext} and {@link CommandInvocationContext}.

* *

Since 7.1, this interceptor will not always open a new command context but instead reuse an existing * command context if possible. This is required for supporting process engine public API access from * delegation code (see {@link ProcessEngineServicesAware}.). However, for every command, a new * command invocation context is created. While a command context holds resources that are * shared between multiple commands, such as database sessions, a command invocation context holds * resources specific for a single command.

* *

The interceptor will check whether an open command context exists. If true, it will reuse the * command context. If false, it will open a new one. We will always push the context to the * {@link Context} stack. So ins some situations, you will see the same context being pushed to the sack * multiple times. The rationale is that the size of the stack should allow you to determine whether * you are currently running an 'inner' command or an 'outer' command as well as your current stack size. * Existing code may rely on this behavior.

* *

The interceptor can be configured using the property {@link #alwaysOpenNew}. * If this property is set to true, we will always open a new context regardless whether there already * exists an active context or not. This is required for properly supporting REQUIRES_NEW semantics for * commands run through the {@link ProcessEngineConfigurationImpl#getCommandInterceptorsTxRequiresNew()} * chain. In that context the 'inner' command must be able to succeed / fail independently from the * 'outer' command.

* * * @author Tom Baeyens * @author Daniel Meyer * @author Thorben Lindhauer */ public class CommandContextInterceptor extends CommandInterceptor { private final static CommandLogger LOG = CommandLogger.CMD_LOGGER; protected CommandContextFactory commandContextFactory; protected ProcessEngineConfigurationImpl processEngineConfiguration; /** if true, we will always open a new command context */ protected boolean alwaysOpenNew; public CommandContextInterceptor() { } public CommandContextInterceptor(CommandContextFactory commandContextFactory, ProcessEngineConfigurationImpl processEngineConfiguration) { this.commandContextFactory = commandContextFactory; this.processEngineConfiguration = processEngineConfiguration; } public CommandContextInterceptor(CommandContextFactory commandContextFactory, ProcessEngineConfigurationImpl processEngineConfiguration, boolean alwaysOpenNew) { this(commandContextFactory, processEngineConfiguration); this.alwaysOpenNew = alwaysOpenNew; } public T execute(Command command) { CommandContext context = null; if(!alwaysOpenNew) { // check whether we can reuse the command context CommandContext existingCommandContext = Context.getCommandContext(); if(existingCommandContext != null && isFromSameEngine(existingCommandContext)) { context = existingCommandContext; } } // only create a new command context on the current command level (CAM-10002) boolean isNew = ProcessEngineContextImpl.consume(); boolean isOuterCommand = (context == null); boolean openNew = (isOuterCommand || isNew); CommandInvocationContext commandInvocationContext = new CommandInvocationContext(command, processEngineConfiguration, isOuterCommand); Context.setCommandInvocationContext(commandInvocationContext); try { if(openNew) { LOG.debugOpeningNewCommandContext(); context = commandContextFactory.createCommandContext(); } else { LOG.debugReusingExistingCommandContext(); } Context.setCommandContext(context); Context.setProcessEngineConfiguration(processEngineConfiguration); // delegate to next interceptor in chain return next.execute(command); } catch (Throwable t) { commandInvocationContext.trySetThrowable(t); } finally { try { if (openNew) { LOG.closingCommandContext(); context.close(commandInvocationContext); } else { commandInvocationContext.rethrow(); } } finally { Context.removeCommandInvocationContext(); Context.removeCommandContext(); Context.removeProcessEngineConfiguration(); // restore the new command context flag ProcessEngineContextImpl.set(isNew); } } return null; } protected boolean isFromSameEngine(CommandContext existingCommandContext) { return processEngineConfiguration == existingCommandContext.getProcessEngineConfiguration(); } public CommandContextFactory getCommandContextFactory() { return commandContextFactory; } public void setCommandContextFactory(CommandContextFactory commandContextFactory) { this.commandContextFactory = commandContextFactory; } public ProcessEngineConfigurationImpl getProcessEngineConfiguration() { return processEngineConfiguration; } public void setProcessEngineContext(ProcessEngineConfigurationImpl processEngineContext) { this.processEngineConfiguration = processEngineContext; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy