cancel
Showing results for 
Search instead for 
Did you mean: 

Transaction propagation: user/group save; user task end.

udoderk
Champ in-the-making
Champ in-the-making
Hi all,
now i try to undestand, which spring Transaction propagation is used, if i

1. create in Activiti Explorer an user /group or change some user setting
2. complete the some user task.

I analysed the following coding and spring configuration xml for Activiti Explorer , but found only, that
    org.springframework.jdbc.datasource.DataSourceTransactionManager is used as transaction manager.
    After executing SaveUserCmd in close method the session will be flashed

    TransactionTemplate.PROPAGATION_REQUIRED or TransactionTemplate.PROPAGATION_REQUIRES_NEW may be used
But which propagation behavior used exact??
edit: i'm debuging the user creation (break point at org.activiti.engine.impl.cmd.SaveUserCmd.execute(CommandContext) ), i see such call hierarchy
[size=85]
SaveUserCmd.execute(CommandContext) line: 40   
SaveUserCmd.execute(CommandContext) line: 27   
CommandExecutorImpl.execute(Command<T>) line: 24   
CommandContextInterceptor.execute(Command<T>) line: 60   
SpringTransactionInterceptor$1.doInTransaction(TransactionStatus) line: 42   
TransactionTemplate.execute(TransactionCallback<T>) line: 130   
SpringTransactionInterceptor.execute(Command<T>) line: 40   
LogInterceptor.execute(Command<T>) line: 32   
IdentityServiceImpl.saveUser(User) line: 66   
NewUserPopupWindow.createUser() line: 177   
NewUserPopupWindow.handleFormSubmit() line: 150
[/size]
The value of propagation is 0 (TransactionTemplate.PROPAGATION_REQUIRED), But why that value are used???

P.S Analysed coding:


public class SaveUserCmd implements Command<Void>, Serializable {

}
—-


public class [b]SpringTransactionIntercepto[/b]r extends CommandInterceptor {
 
  protected PlatformTransactionManager transactionManager;
  protected int transactionPropagation;
 
  public SpringTransactionInterceptor(PlatformTransactionManager transactionManager, int transactionPropagation) {
    this.transactionManager = transactionManager;
    this.transactionPropagation = transactionPropagation;
  }
 
  @SuppressWarnings("unchecked")
  public <T> T execute(final Command<T> command) {
    TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
    transactionTemplate.setPropagationBehavior(transactionPropagation);
    T result = (T) [b]transactionTemplate.execute[/b](new TransactionCallback() {
      public Object doInTransaction(TransactionStatus status) {
[b]        return next.execute(command);[/b]
      }
    });
    return result;
  }
}
—-

org.activiti.engine.impl.cmd.SaveUserCmd.[b]execute(CommandContext)[/b]
—–

org.activiti.engine.impl.interceptor.CommandContextInterceptor…{…}
org.activiti.engine.impl.interceptor.CommandContextInterceptor.[b]execute(Command<T>) [/b]{
CommandContext context = Context.getCommandContext();
….
try {
      // Push on stack
      Context.setCommandContext(context);
      Context.setProcessEngineConfiguration(processEngineConfiguration);
     
      return next.execute(command);
     
    } catch (Exception e) {
       
      context.exception(e);
     
    } finally {
      try {
         if (!contextReused) {
            context.close();
         }
……..
  }
}
—-


org.activiti.engine.impl.interceptor.CommandContext.close() {..

          if (exception == null) {
        [b]    flushSessions();[/b]
          }
…..
}


org.activiti.engine.impl.interceptor.CommandContext.flushSessions()
{

    for (Session session : sessions.values()) {
     [b] session.flush();[/b]
    }
}

interface org.activiti.engine.impl.interceptor.Session
—-

public class org.activiti.spring.SpringProcessEngineConfiguration extends ProcessEngineConfigurationImpl
{…
  protected Collection< ? extends CommandInterceptor> getDefaultCommandInterceptorsTxRequired() {
    if (transactionManager==null) {
      throw new ActivitiException("transactionManager is required property for SpringProcessEngineConfiguration, use "+StandaloneProcessEngineConfiguration.class.getName()+" otherwise");
    }
   
    List<CommandInterceptor> defaultCommandInterceptorsTxRequired = new ArrayList<CommandInterceptor>();
    defaultCommandInterceptorsTxRequired.add(new LogInterceptor());
    defaultCommandInterceptorsTxRequired.add(new SpringTransactionInterceptor(transactionManager, [b]TransactionTemplate.PROPAGATION_REQUIRED[/b]));
    CommandContextInterceptor commandContextInterceptor = new CommandContextInterceptor(commandContextFactory, this);
    commandContextInterceptor.setContextReusePossible(true);
    defaultCommandInterceptorsTxRequired.add(commandContextInterceptor);
    return defaultCommandInterceptorsTxRequired;
  }
 
  protected Collection< ? extends CommandInterceptor> getDefaultCommandInterceptorsTxRequiresNew() {
    List<CommandInterceptor> defaultCommandInterceptorsTxRequiresNew = new ArrayList<CommandInterceptor>();
    defaultCommandInterceptorsTxRequiresNew.add(new LogInterceptor());
    defaultCommandInterceptorsTxRequiresNew.add(new SpringTransactionInterceptor(transactionManager, [b]TransactionTemplate.PROPAGATION_REQUIRES_NEW[/b]));
    CommandContextInterceptor commandContextInterceptor = new CommandContextInterceptor(commandContextFactory, this);
    commandContextInterceptor.setContextReusePossible(false);
    defaultCommandInterceptorsTxRequiresNew.add(commandContextInterceptor);
    return defaultCommandInterceptorsTxRequiresNew;
  }
}

—-
public abstract class org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl extends org.activiti.engine.ProcessEngineConfiguration { }
{….
  protected void initCommandInterceptorsTxRequired() {
    if (commandInterceptorsTxRequired==null) {
      if (customPreCommandInterceptorsTxRequired!=null) {
        commandInterceptorsTxRequired = new ArrayList<CommandInterceptor>(customPreCommandInterceptorsTxRequired);
      } else {
        commandInterceptorsTxRequired = new ArrayList<CommandInterceptor>();
      }
      commandInterceptorsTxRequired.addAll(getDefaultCommandInterceptorsTxRequired());
      if (customPostCommandInterceptorsTxRequired!=null) {
        commandInterceptorsTxRequired.addAll(customPostCommandInterceptorsTxRequired);
      }
      commandInterceptorsTxRequired.add(actualCommandExecutor);
    }
  }

  protected void initCommandInterceptorsTxRequiresNew() {
    if (commandInterceptorsTxRequiresNew==null) {
      if (customPreCommandInterceptorsTxRequiresNew!=null) {
        commandInterceptorsTxRequiresNew = new ArrayList<CommandInterceptor>(customPreCommandInterceptorsTxRequiresNew);
      } else {
        commandInterceptorsTxRequiresNew = new ArrayList<CommandInterceptor>();
      }
      commandInterceptorsTxRequiresNew.addAll(getDefaultCommandInterceptorsTxRequiresNew());
      if (customPostCommandInterceptorsTxRequiresNew!=null) {
        commandInterceptorsTxRequiresNew.addAll(customPostCommandInterceptorsTxRequiresNew);
      }
      commandInterceptorsTxRequiresNew.add(actualCommandExecutor);
    }
  }
  …
 
  }

3 REPLIES 3

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
Can you edit you post and use code tags instead of quote tags. And put each fie in separate tags?

Edit: I now see it is one file, greatly 'manipulated'. But still, the first question remains.

udoderk
Champ in-the-making
Champ in-the-making
>put each flie
done

jbarrez
Star Contributor
Star Contributor
TransactionTemplate.PROPAGATION_REQUIRED or TransactionTemplate.PROPAGATION_REQUIRES_NEW may be used

But which propagation behavior used exact??

REQUIRED is the default and will start a new transaction when one doesn't exist (or when calling code eg in a method marked with @transactional) or reuse the existing one.

REQUIRES_NEW is only used for fetching new id's from the database. So it could very well be that in your logging you see the requires_new once in  a while because the engine has used up its id's and need to fetch a new block of ids.