Search code examples
javaspringspring-bootspring-securityactiviti

Configure Activiti to reuse the existing user/group data in Spring Boot


I am using Spring Boot 1.4.3.RELEASE. I have already created a simple MVC application to manage users and groups. Now, I am trying to integrate Activiti 5.21.0 within my project, and REUSE the existing user/group tables by Activiti.

I have extended the default UserEntityManager and GroupEntityManager classes from Activiti like below:

CustomUserEntityManager.java

import java.util.List;

import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.UserQueryImpl;
import org.activiti.engine.impl.persistence.entity.IdentityInfoEntity;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import org.activiti.engine.impl.persistence.entity.UserEntityManager;

import com.example.spring.dao.UserDao;
import com.example.spring.model.User;

public class CustomUserEntityManager extends UserEntityManager {

    private UserDao userDao;

    public CustomUserEntityManager(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public UserEntity findUserById(String userId) {
        User user = userDao.findById(Integer.parseInt(userId));
        return userToActivitiUser(user);
    }

    @Override
    public org.activiti.engine.identity.User createNewUser(String userId) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void insertUser(org.activiti.engine.identity.User user) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void updateUser(org.activiti.engine.identity.User updatedUser) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void deleteUser(String userId) {
        throw new UnsupportedOperationException();
    }

    @Override
    public List<org.activiti.engine.identity.User> findUserByQueryCriteria(UserQueryImpl query, Page page) {
        throw new UnsupportedOperationException();
    }

    @Override
    public long findUserCountByQueryCriteria(UserQueryImpl query) {
        throw new UnsupportedOperationException();
    }

    @Override
    public IdentityInfoEntity findUserInfoByUserIdAndKey(String userId, String key) {
        throw new UnsupportedOperationException();
    }

    @Override
    public List<String> findUserInfoKeysByUserIdAndType(String userId, String type) {
        throw new UnsupportedOperationException();
    }

    private UserEntity userToActivitiUser(User user) {
        UserEntity activitiUser = new UserEntity();
        activitiUser.setId(user.getId().toString());
        activitiUser.setPassword(user.getPassword());
        activitiUser.setFirstName(user.getUsername());
        activitiUser.setLastName(user.getLastName());
        activitiUser.setEmail(user.getEmail());
        return activitiUser;
    }

}

ActivitiGroupEntityManager.java

import java.util.List;

import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.GroupQuery;
import org.activiti.engine.impl.GroupQueryImpl;
import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.persistence.entity.GroupEntityManager;

import com.example.spring.dao.CMSGroupDao;

public class CustomGroupEntityManager extends GroupEntityManager {

    private CMSGroupDao groupDao;

    public CustomGroupEntityManager(CMSGroupDao groupDao) {
        this.groupDao = groupDao;
    }

    @Override
    public List<Group> findGroupsByUser(String userId) {
        // TODO add logic
        return null;
    }

    @Override
    public Group createNewGroup(String groupId) {
            throw new UnsupportedOperationException();
    }

    @Override
    public void deleteGroup(String groupId) {
            throw new UnsupportedOperationException();
    }

    @Override
    public GroupQuery createNewGroupQuery() {
            return super.createNewGroupQuery();
    }

    @Override
    public List<Group> findGroupByQueryCriteria(GroupQueryImpl query, Page page) {
            throw new UnsupportedOperationException();
    }

    @Override
    public long findGroupCountByQueryCriteria(GroupQueryImpl query) {
            throw new UnsupportedOperationException();
    }

}

then, I added my custom factories like below:

CustomUserManagerFactory.java

import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.example.spring.dao.UserDao;

@Component(value = "customUserManagerFactory")
public class CustomUserManagerFactory implements SessionFactory {

    @Autowired
    private UserDao userDao;

    @Override
    public Class<?> getSessionType() {
        return CustomUserEntityManager.class;
    }

    @Override
    public Session openSession() {
        return new CustomUserEntityManager(userDao);
    }

}

CustomGroupManagerFactory.java

import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.example.spring.dao.CMSGroupDao;

@Component(value = "customGroupManagerFactory")
public class CustomGroupManagerFactory implements SessionFactory {

    @Autowired
    private CMSGroupDao groupDao;

    @Override
    public Class<?> getSessionType() {
        return CustomGroupEntityManager.class;
    }

    @Override
    public Session openSession() {
        return new CustomGroupEntityManager(groupDao);
    }

}

Finally, I added my ProcessEngine configuration bean like below:

ProcessEngineConfig.java

package com.example.spring.configuration;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Configuration;

@Configuration
@AutoConfigureBefore(org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class)
public class ProcessEngineConfig implements ProcessEngineConfigurationConfigurer{

    @Resource(name = "customUserManagerFactory")
    private SessionFactory userManagerFactory;

    @Resource(name = "customGroupManagerFactory")
    private SessionFactory groupManagerFactory;

    public void configure(SpringProcessEngineConfiguration pec) {
        pec.setDbIdentityUsed(false); 
        List<SessionFactory> customSessionFactories = new ArrayList<SessionFactory>();
        customSessionFactories.add(userManagerFactory);
        customSessionFactories.add(groupManagerFactory);
        if (pec.getCustomSessionFactories() == null){
            pec.setCustomSessionFactories(customSessionFactories);
        }
        else{
            pec.getCustomSessionFactories().addAll(customSessionFactories);
        }
    }
}

Important parts from pom.xml

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <activiti.version>5.21.0</activiti.version>
    </properties>

    <dependencies>

        <!-- Activiti Dependencies -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter-basic</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter-actuator</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <!-- Spring-boot Dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        .......
        .......
     </dependencies>

The application is executing without any runtime error, HOWEVER, when I create a user using org.activiti.engine.IdentityService.newUser() the user is created and saved in Activit user table and UnsupportedOperationException() is not thrown which mean that the custom configuration is not working.

Any help will be appreciated!!


Solution

  • For the CustomGroupManagerFactory the type should be :

      @Override
      public Class<?> getSessionType() {
          return GroupIdentityManager.class;
      }
    

    For CustomUserManagerFactory the type should be :

      @Override
      public Class<?> getSessionType() {
          return UserIdentityManager.class;
      }
    

    I hope the solution above helps you to get it working.