This is the 11th day of my participation in Gwen Challenge

>>>> 😜😜😜 Making: 👉 github.com/black-ant

A. The preface

👉 Activiti 7 is basic to use, this article will take a look at activiti configuration

2. Configure the main process

The first thing to know is where the configuration is initiated:

2.1 Starting Point of Configuration

After integration Activiti – Spring, is through the ProcessEngineAutoConfiguration configuration:

@Configuration
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(ActivitiProperties.class)
public class ProcessEngineAutoConfiguration extends AbstractProcessEngineAutoConfiguration {

    private final UserGroupManager userGroupManager;

    public ProcessEngineAutoConfiguration(UserGroupManager userGroupManager) {
        this.userGroupManager = userGroupManager;
    }

    @Bean
    @ConditionalOnMissingBean
    public SpringProcessEngineConfiguration springProcessEngineConfiguration(
            DataSource dataSource,
            PlatformTransactionManager transactionManager,
            SpringAsyncExecutor springAsyncExecutor,
            ActivitiProperties activitiProperties,
            ProcessDefinitionResourceFinder processDefinitionResourceFinder,
            @Autowired(required = false) ProcessEngineConfigurationConfigurer processEngineConfigurationConfigurer) throws IOException {

        / / 2.2 configuration SpringProcessEngineConfiguration
        SpringProcessEngineConfiguration conf = new SpringProcessEngineConfiguration();
        configureProcessDefinitionResources(processDefinitionResourceFinder,conf);
        
        // Set the DataSource and transaction manager
        conf.setDataSource(dataSource);
        conf.setTransactionManager(transactionManager);

        if(springAsyncExecutor ! =null) {
            // SpringAsyncExecutor -> PS:21001
            conf.setAsyncExecutor(springAsyncExecutor);
        }
        
        conf.setDeploymentName(activitiProperties.getDeploymentName());
        
        // Database update type -> PS:21002
        conf.setDatabaseSchema(activitiProperties.getDatabaseSchema());
        conf.setDatabaseSchemaUpdate(activitiProperties.getDatabaseSchemaUpdate());
        
        
        conf.setDbHistoryUsed(activitiProperties.isDbHistoryUsed());
        conf.setAsyncExecutorActivate(activitiProperties.isAsyncExecutorActivate());
        
        // Configure the email system information
        conf.setMailServerHost(activitiProperties.getMailServerHost());
        conf.setMailServerPort(activitiProperties.getMailServerPort());
        conf.setMailServerUsername(activitiProperties.getMailServerUserName());
        conf.setMailServerPassword(activitiProperties.getMailServerPassword());
        conf.setMailServerDefaultFrom(activitiProperties.getMailServerDefaultFrom());
        conf.setMailServerUseSSL(activitiProperties.isMailServerUseSsl());
        conf.setMailServerUseTLS(activitiProperties.isMailServerUseTls());

        // User group manager
        if(userGroupManager ! =null) {
            conf.setUserGroupManager(userGroupManager);
        }

        conf.setHistoryLevel(activitiProperties.getHistoryLevel());

        // Customize Mybatis Mapper
        if(activitiProperties.getCustomMybatisMappers() ! =null) {
            conf.setCustomMybatisMappers(getCustomMybatisMapperClasses(activitiProperties.getCustomMybatisMappers()));
        }

        if(activitiProperties.getCustomMybatisXMLMappers() ! =null) {
            conf.setCustomMybatisXMLMappers(new HashSet<>(activitiProperties.getCustomMybatisXMLMappers()));
        }

        if(activitiProperties.getCustomMybatisXMLMappers() ! =null) {
            conf.setCustomMybatisXMLMappers(new HashSet<>(activitiProperties.getCustomMybatisXMLMappers()));
        }

        // ID generator: an implementation based on the current time and the Ethernet address of the machine running it
        if (activitiProperties.isUseStrongUuids()) {
            conf.setIdGenerator(new StrongUuidGenerator());
        }

        conf.setActivityBehaviorFactory(new CloudActivityBehaviorFactory());

        if(processEngineConfigurationConfigurer ! =null) {
            / / set configuration for processEngineConfigurationConfigurer
            processEngineConfigurationConfigurer.configure(conf);
        }

        return conf;
    }

    private void configureProcessDefinitionResources(ProcessDefinitionResourceFinder processDefinitionResourceFinder, SpringProcessEngineConfiguration conf) throws IOException {
        List<Resource> procDefResources = processDefinitionResourceFinder.discoverProcessDefinitionResources();
        if(! procDefResources.isEmpty()) { conf.setDeploymentResources(procDefResources.toArray(new Resource[0])); }}@Bean
    @ConditionalOnMissingBean
    public ProcessDefinitionResourceFinder processDefinitionResourceFinder(ActivitiProperties activitiProperties, ResourcePatternResolver resourcePatternResolver) {
        return newProcessDefinitionResourceFinder(activitiProperties, resourcePatternResolver); }}Copy the code

PS:21002 SpringAsyncExecutor function

What it does: This is a Spring-based implementation of the Job Executor that uses the Spring abstract TaskExecutor to perform background tasks

C- SpringAsyncExecutor
// Perform a simple task executor interface processor
protected TaskExecutor taskExecutor;
// A policy for processing jobs that have been acquired but cannot be executed at this time (exceeding the queue size)
protected SpringRejectedJobsHandler rejectedJobsHandler;

Copy the code

Take a look at TaskExecutor’s system 👉

PS:21002 databaseSchemaUpdate Specifies the value of the attribute

DatabaseSchemaUpdate property values:

Flase: default value. When creating the process engine, check the version of the DB schema against the library and throw an exception true if the version does not match: After building the process engine, a check is performed and the schema is updated if necessary: The schema is created when the process engine is created and deleted when the process engine is shut down (you must manually shut down the engine to delete the tables). Drop-create: Drop the original old table when Activiti starts and then create a new table (no need to manually shut down the engine).

There are several concerns:

@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(ActivitiProperties.class)
Copy the code

The role of DataSourceAutoConfiguration:

This file is org. Springframework. Boot. Autoconfigure. JDBC of files, because there are data manipulation activiti, so you need to use a DataSource, here is the use of the unity of the Spring

What is ActivitiProperties?

@ConfigurationProperties("spring.activiti")
public class ActivitiProperties {

  private boolean checkProcessDefinitions = true;
  private boolean asyncExecutorActivate = false;
  private String deploymentName = "SpringAutoDeployment";
  private String mailServerHost = "localhost";
  private int mailServerPort = 1025;
  private String mailServerUserName;
  private String mailServerPassword;
  private String mailServerDefaultFrom;
  private boolean mailServerUseSsl;
  private boolean mailServerUseTls;
  private String databaseSchemaUpdate = "true";
  private String databaseSchema;
  private boolean isDbHistoryUsed = false;
  // Historical level
  private HistoryLevel historyLevel = HistoryLevel.NONE;
  // Default process document
  private String processDefinitionLocationPrefix = "classpath:/processes/";
  // Process configuration file suffix
  private List<String> processDefinitionLocationSuffixes = Arrays.asList("**.bpmn20.xml"."**.bpmn");
  // Allow custom DAO operations
  private List<String> customMybatisMappers;
  private List<String> customMybatisXMLMappers;
  private boolean useStrongUuids = true;

    
}

// As you can see here, there are many configurations available in Activiti, which can be configured as required:
HistoryLevel (none /activity / audit/full )


Copy the code

2.3 Configuration Initialization

In ProcessEngineAutoConfiguration above, you can see through the new SpringProcessEngineConfiguration (); Build the object, in fact, in addition to ProcessEngineAutoConfiguration, there are many other objects, we each take a look at:

The main configuration classes for Spring Activiti 7 include the following:C- SpringProcessEngineConfiguration C- JtaProcessEngineConfiguration C- MultiSchemaMultiTenantProcessEngineConfiguration  C- StandaloneInMemProcessEngineConfiguration C- StandaloneProcessEngineConfigurationCopy the code

Let’s see what they did:

2.3.1 SpringProcessEngineConfiguration

C - SpringProcessEngineConfiguration E - ProcessEngineConfigurationImpl it2A class is very huge, we just look at some of the important parts: C - SpringProcessEngineConfiguration MC - SpringProcessEngineConfiguration: Where the AutoDeploymentStrategy collection -> PS is configured:35001M -buildProcessEngine: buildProcessEngine M -getUserGroupManager: UserGroupManager -> PS:35002M - setTransactionSynchronizationAdapterOrder M - initDefaultCommandConfig: initialize the default configuration - > PS:35003M - createTransactionInterceptor: return SpringTransactionInterceptor M - initTransactionContextFactory:newA SpringTransactionContextFactory - > PS:35004M-initjpa: builds JPA m-AutoDeployResources M-setdatasource: sets the data source to be used where additional dependencies need to be generated or used@Bean -> PS:35005
Copy the code

PS: 35001 AutoDeploymentStrategy role

Function: Policy interface for automatic resource deployment. A policy can perform any number of deployments for the resources it provides.

Policies can handle deployments corresponding to specific specified deployment patterns. This applicability can be verified using the #handlesMode(String) method

AutoDeploymentStrategy is an interface: Deploy

C- AutoDeploymentStrategy
    M- boolean handlesMode(final String mode)? - Determines whether the policy handles the deployment M- of the provided deployment modevoid deployResources(final String deploymentNameHint, final Resource[] resources, final RepositoryService repositoryService)? - Deploy the provided resource, using the provided name as a prompt, and using the provided RepositoryService to perform the deploymentCopy the code

He has three implementation classes:

  • C – DefaultAutoDeploymentStrategy: will all resources combined into a single deployment
  • C – ResourceParentFolderAutoDeploymentStrategy: in order to share the same parent folder of each resource set for the deployment of alone
  • C – SingleResourceAutoDeploymentStrategy: by name to perform separate each resource deployment

Activiti – AutoDeploymentStrategy 👉

PS:35002 UserGroupManager

    
- List<String> getUserGroups(String username);
- List<String> getUserRoles(String username);
- List<String> getGroups(a);
- List<String> getUsers(a); C - ActivitiUserGroupManagerImpl: main implementation class F - UserDetailsService UserDetailsService// Run the userDetailsService command to obtain the related status
@Override
public List<String> getUserGroups(String username) {

	return userDetailsService.loadUserByUsername(username).getAuthorities().stream()
                .filter((GrantedAuthority a) -> a.getAuthority().startsWith("GROUP_"))
                .map((GrantedAuthority a) -> a.getAuthority().substring(6))
                .collect(Collectors.toList());
}

@Override
public List<String> getUserRoles(String username) {
    
	return userDetailsService.loadUserByUsername(username).getAuthorities().stream()
                .filter((GrantedAuthority a) -> a.getAuthority().startsWith("ROLE_"))
                .map((GrantedAuthority a) -> a.getAuthority().substring(5))
                .collect(Collectors.toList());
}
Copy the code

PS:35003 SpringTransactionInterceptor

C- SpringTransactionInterceptor
    E- AbstractCommandInterceptor  
Copy the code

PS:35004 SpringTransactionContextFactory

public class SpringTransactionContextFactory implements TransactionContextFactory {
	
    // This is the central interface in Spring's transaction infrastructure
	protected PlatformTransactionManager transactionManager;
	protected Integer transactionSynchronizationAdapterOrder;
    
    / /...
    
}
Copy the code

PS: 35005 build TransactionAwareDataSourceProxy

public ProcessEngineConfiguration setDataSource(DataSource dataSource) {
    if (dataSource instanceof TransactionAwareDataSourceProxy) {
      return super.setDataSource(dataSource);
    } else {
      // Wrap datasource in Transaction-aware proxy
      DataSource proxiedDataSource = new TransactionAwareDataSourceProxy(dataSource);
      return super.setDataSource(proxiedDataSource); }}Copy the code

The role of TransactionAwareDataSourceProxy

C – TransactionAwareDataSourceProxy – target JDBC javax.mail. SQL agent. The data source, Add spring management awareness, TransactionAwareDataSourceProxy is the outermost layers of the data source proxy/adapter chain data sources, TransactionAwareDataSourceProxy can directly entrusted to the target connection pool or some intermediary agent/adapter

Simply put: Data access code that does not have Spring data access support can seamlessly participate in Spring-managed transactions with this broker

Activiti – ProcessEngineConfigurationImpl 👉

2.3.2 JtaProcessEngineConfiguration role

What it does: Uses JTA for transaction management without Activiti transactions

The Java Transaction API, commonly known as JTA, is an API for managing transactions in Java, simply javax.Transaction; The architecture of

public class JtaProcessEngineConfiguration extends ProcessEngineConfigurationImpl {

    protected TransactionManager transactionManager;
    public CommandInterceptor createTransactionInterceptor(a) {
        / / as you can see, constructed a JtaTransactionInterceptor here
        return new JtaTransactionInterceptor(transactionManager);
    }
    
    public void initTransactionContextFactory(a) {
        if (transactionContextFactory == null) {
            / / build a JtaTransactionContextFactory factory class
            transactionContextFactory = newJtaTransactionContextFactory(transactionManager); }}}Copy the code

2.3.3 MultiSchemaMultiTenantProcessEngineConfiguration

Role: a multi-tenant environment, building multi-tenant ProcessEngine ProcessEngineConfiguration, in which each tenant has its own database schema


// The dataSource is bound to tenantId
public void registerTenant(String tenantId, DataSource dataSource) {
    ((TenantAwareDataSource) super.getDataSource()).addDataSource(tenantId, dataSource);
    
    if (booted) {
      createTenantSchema(tenantId);
      
      createTenantAsyncJobExecutor(tenantId);
      
      tenantInfoHolder.setCurrentTenantId(tenantId);
      super.postProcessEngineInitialisation(); tenantInfoHolder.clearCurrentTenantId(); }}public ProcessEngine buildProcessEngine(a) {
    
    Disable schema creation/validation by setting it to NULL
    String originalDatabaseSchemaUpdate = this.databaseSchemaUpdate;
    this.databaseSchemaUpdate = null; 
    
    boolean originalIsAutoActivateAsyncExecutor = this.asyncExecutorActivate;
    this.asyncExecutorActivate = false;
    
    ProcessEngine processEngine = super.buildProcessEngine();
    
    // Reset to the original value
    this.databaseSchemaUpdate = originalDatabaseSchemaUpdate;
    this.asyncExecutorActivate = originalIsAutoActivateAsyncExecutor;
    
    // Create tenant mode
    for (String tenantId : tenantInfoHolder.getAllTenants()) {
      createTenantSchema(tenantId);
    }
    
    // Start executing the program asynchronously
    if(asyncExecutor ! =null && originalIsAutoActivateAsyncExecutor) {
      asyncExecutor.start();
    }
    
    booted = true;
    return processEngine;
  }

Copy the code

2.3.4 StandaloneInMemProcessEngineConfiguration

 // Use the in-memory database, where H2 is used
public StandaloneInMemProcessEngineConfiguration(a) {
    this.databaseSchemaUpdate = DB_SCHEMA_UPDATE_CREATE_DROP;
    this.jdbcUrl = "jdbc:h2:mem:activiti";
}
Copy the code

In a nutshell, this configuration configures the use of an in-memory database

conclusion

Activiti 7 configuration is almost complete. Next, take a look at its database operations.

The appendix

🇨 🇳 ⚽ ✊ 🏆 🎉