Activiti supports two main entry points that you need to implement in order to integrate your identity solution. These are the user manager and the group manager classes. We will first create a factory for group/user management, and then implement the class that we create in the factory. Lets take a dive into the code, implementing the MyGroupManagerFactory class first:
1: package my.great.company.com.businessprocessengine.identityservice;
2:
3: import org.activiti.engine.impl.interceptor.Session;
4: import org.activiti.engine.impl.interceptor.SessionFactory;
5: import org.activiti.engine.impl.persistence.entity.GroupManager;
6:
7: public class MyGroupManagerFactory implements SessionFactory {
8:
9: private MyConnectionParams connectionParams;
10:
11: public MyGroupManagerFactory(MyConnectionParams params) {
12: this.connectionParams = params;
13: }
14:
15: @Override
16: public Class<?> getSessionType() {
17: return GroupManager.class;
18: }
19:
20: @Override
21: public Session openSession() {
22: return new MyGroupManager(connectionParams);
23: }
24: }
1: package my.great.company.com.businessprocessengine.identityservice;
2:
3: import org.activiti.engine.impl.interceptor.Session;
4: import org.activiti.engine.impl.interceptor.SessionFactory;
5: import org.activiti.engine.impl.persistence.entity.UserManager;
6:
7: public class MyUserManagerFactory implements SessionFactory {
8:
9: private MyConnectionParams connectionParams;
10:
11: public MyUserManagerFactory(MyConnectionParams params) {
12: this.connectionParams = params;
13: }
14:
15: @Override
16: public Class<?> getSessionType() {
17: return UserManager.class;
18: }
19:
20: @Override
21: public Session openSession() {
22: return new MyUserManager(connectionParams);
23: }
24:
25: }
We now implement MyGroupManager and MyUserManager classes. We did not not detail the entire code, but created an example to show what must be implemented and what you can skip. In MyGroupManager we only implemented the findGroupByQueryCriteria, and findGroupCountByQueryCriteria. Methods that are marked with TODO notation are mandatory in order to work with Activiti core engine. If you want to work with Activity Explorer - implement all the methods.
1: package my.great.company.com.businessprocessengine.identityservice;
2:
3: import java.util.ArrayList;
4: import java.util.List;
5:
6: import org.activiti.engine.ActivitiException;
7: import org.activiti.engine.identity.Group;
8: import org.activiti.engine.impl.GroupQueryImpl;
9: import org.activiti.engine.impl.Page;
10: import org.activiti.engine.impl.persistence.entity.GroupEntity;
11: import org.activiti.engine.impl.persistence.entity.GroupManager;
12: import org.apache.commons.lang.StringUtils;
13:
14: public class MyGroupManager extends GroupManager {
15:
16:
17: public MyGroupManager(MyConnectionParams connectionParams) {
18:
19: }
20:
21: @Override
22: public Group createNewGroup(String groupId) {
23: throw new ActivitiException("My group manager doesn't support creating a new group");
24: }
25:
26: @Override
27: public void insertGroup(Group group) {
28: throw new ActivitiException("My group manager doesn't support inserting a new group");
29: }
30:
31: @Override
32: public void updateGroup(Group updatedGroup) {
33: throw new ActivitiException("My group manager doesn't support updating a new group");
34: }
35:
36: @Override
37: public void deleteGroup(String groupId) {
38: throw new ActivitiException("My group manager doesn't support deleting a new group");
39: }
40:
41: @Override
42: public long findGroupCountByQueryCriteria(Object query) {
43: return findGroupByQueryCriteria(query, null).size();
44: }
45:
46: @Override
47: public List<Group> findGroupByQueryCriteria(Object query, Page page) {
48: List<Group> groupList = new ArrayList<Group>();
49: GroupQueryImpl groupQuery = (GroupQueryImpl) query;
50: if (StringUtils.isNotEmpty(groupQuery.getId())) {
51: GroupEntity singleGroup = findGroupById(groupQuery.getId());
52: groupList.add(singleGroup);
53: return groupList;
54: } else if (StringUtils.isNotEmpty(groupQuery.getName())) {
55: GroupEntity singleGroup = findGroupById(groupQuery.getId());
56: groupList.add(singleGroup);
57: return groupList;
58: } else if (StringUtils.isNotEmpty(groupQuery.getUserId())) {
59: return findGroupsByUser(groupQuery.getUserId());
60: } else {
61: //TODO: get all groups from your identity domain and convert them to List<Group>
62: return null;
63: } //TODO: you can add other search criteria that will allow extended support using the Activiti engine API
64: }
65:
66: @Override
67: public GroupEntity findGroupById(String activitiGroupID) {
68: //TODO
69: throw new ActivitiException("My group manager doesn't support finding a group");
70: }
71:
72: @Override
73: public List<Group> findGroupsByUser(String userLogin) {
74: //TODO
75: throw new ActivitiException("My group manager doesn't support finding a group");
76: }
77: }
1: package my.great.company.com.businessprocessengine.identityservice;
2:
3: import java.util.ArrayList;
4: import java.util.List;
5:
6: import org.activiti.engine.ActivitiException;
7: import org.activiti.engine.identity.User;
8: import org.activiti.engine.impl.Page;
9: import org.activiti.engine.impl.UserQueryImpl;
10: import org.activiti.engine.impl.persistence.entity.UserEntity;
11: import org.activiti.engine.impl.persistence.entity.UserManager;
12: import org.apache.commons.lang.StringUtils;
13:
14: public class MyUserManager extends UserManager {
15:
16: public MyUserManager(MyConnectionParams connectionParams) {
17: }
18:
19: @Override
20: public User createNewUser(String userId) {
21: throw new ActivitiException("My user manager doesn't support creating a new user");
22: }
23:
24: @Override
25: public void insertUser(User user) {
26: throw new ActivitiException("My user manager doesn't support inserting a new user");
27: }
28:
29: @Override
30: public void updateUser(User updatedUser) {
31: throw new ActivitiException("My user manager doesn't support updating a user");
32: }
33:
34: @Override
35: public void deleteUser(String userId) {
36: throw new ActivitiException("My user manager doesn't support deleting a user");
37: }
38:
39: @Override
40: public UserEntity findUserById(String userLogin) {
41: //TODO: get my user according to userLogin and convert it to UserEntity
42: throw new ActivitiException("My user manager doesn't support finding a user");
43: }
44:
45: @Override
46: public List<User> findUserByQueryCriteria(Object query, Page page) {
47:
48: List<User> userList = new ArrayList<User>();
49: UserQueryImpl userQuery = (UserQueryImpl) query;
50: if (StringUtils.isNotEmpty(userQuery.getId())) {
51: userList.add(findUserById(userQuery.getId()));
52: return userList;
53: } else if (StringUtils.isNotEmpty(userQuery.getLastName())) {
54: userList.add(findUserById(userQuery.getLastName()));
55: return userList;
56: } else {
57: //TODO: get all users from your identity domain and convert them to List<User>
58: return null;
59: } //TODO: you can add other search criteria that will allow extended support using the Activiti engine API
60: }
61:
62: @Override
63: public long findUserCountByQueryCriteria(Object query) {
64: return findUserByQueryCriteria(query, null).size();
65: }
66:
67: @Override
68: public Boolean checkPassword(String userId, String password) {
69: //TODO: check the password in your domain and return the appropriate boolean
70: return false;
71: }
72: }
1: <?xml version="1.0" encoding="UTF-8"?>
2: <beans xmlns="http://www.springframework.org/schema/beans"
3: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4: xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
5:
6: <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
7:
8: ...
9: <property name="customSessionFactories">
10: <list>
11: <bean
12: class="my.great.company.com.businessprocessengine.identityservice.MyUserManagerFactory">
13: <constructor-arg ref="MyConnectionParams" />
14: </bean>
15: <bean
16: class="my.great.company.com.businessprocessengine.identityservice.MyGroupManagerFactory">
17: <constructor-arg ref="MyConnectionParams" />
18: </bean>
19: </list>
20: </property>
21: ...
22: </bean>
23:
24: <bean id="MyConnectionParams"
25: class="my.great.company.com.businessprocessengine.identityservice.MyConnectionParams">
26: </bean>
27: ...
28:
29: </beans>
So, here are a few extra pointers about Activiti Identity:
- First of all there are 3 predefined group types:
- activity-role
- assignment
- user
- Now, no one tells you this, but if you are using Activiti Explorer, and you want your user to have admin privileges (i.e. be able to see the 'manage' tab), then the user's group type must be 'security-role' and the user's group name must be hard coded 'admin'. This means you will need to create some special code hacking for special users to use the Activiti Explorer.
- Lets say you created a process that has a user task with a candidate group option (denote said group as X). NOTE: If you start a process instance, than only if the type of the group X is 'assignment' then users that belong to X will be able to claim the task. Otherwise, the user will not be able to claim the task at all.
Hello, thanks for this wonderful post. It's very useful as this is what we're trying inject workflow into our application. Do you happen to have the full source for this, maybe something more elaborate? I'm new to activity a more detailed example would be extremely helpful. Activiti it's light weight enough for us to use in our application. Thanks again, Paul
ReplyDeleteHello, very intresting post. But I'm more interrested in start process intance !
ReplyDeleteI would like to start a new instance of a process from a java application.
How I can assign a user or user group in my process intance?
Thanks for help.
IdentityService already provides API to add,delete User and groups
ReplyDeleteHi ,very useful post.but what should MyConnectionParams class contain.
ReplyDeleteAs we wrote:
ReplyDelete"assume MyConnectionParams is a simple POJO, and implement it for your needs"
Thank you very much for the quick reply.
ReplyDeleteHi Roi Gamliel ,
ReplyDeleteI have deployed activiti-explorer webapp and my web application which is developed on springs framework on the same tomcatserver and i have configured SpringProcessEngineConfiguration as the way you have said above , and my configuration code is as follows
but when i log in into activiti explorer it is still referencing it's own users and groups table.In the myusermanger class i am returning always true in the checkpassword function,so in the activitiexplorer even though i give wrong password it must let me login. what could be the problem.
Please help me out to fix this issue.
Which configuration file should I modify in the standard demo installation? I tred with apps\apache-tomcat-6.0.32\webapps\activiti-explorer\WEB-INF\applicationContext.xml, but something went wrong :-(
ReplyDeleteThank you very much!
Franco
Don't worry, now it works: I din't get that the "getSessionType" methods must return the UserManager/GroupManager class in order to be recognized by the Activiti engine.
DeleteThanks
Franco
This comment has been removed by the author.
ReplyDeleteI am trying to complete a user task for which fozzie is the assignee.
ReplyDeleteThe code is :
TaskService taskService = processEngine.getTaskService();
List tasks = taskService.createTaskQuery().taskAssignee("fozzie")?.list();
taskService.complete(tasks.get(0).getId(),variables);
But exception occurrs as follows :
rg.activiti.engine.ActivitiException: Provided id is null
at org.activiti.engine.impl.UserQueryImpl.userId(UserQueryImpl.java:53)
at Script1.run(Script1.groovy:4)
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:315)
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:111)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:216)
I tried
IdentityService identityService = processEngine.getIdentityService();
identityService.setAuthenticatedUserId("fozzie")
But it does not work.
I guess i am unable to create a session with user as fozzie.
Can you please help in this regard.
I'm using Activiti Community version 6 and i followed exactly the tutorial and replaced few class names like UserManager and GroupManager with UserEntityManager and GroupEntityManager as per new version. And also I created applicationContext.xml in /../WEB-APPS/classes/ which is actually missing (don't know about the issue why was it missing).
ReplyDeleteWhat does MyConnectionParam class exactly contain?
But still i could login and create users in Act_id_user. How will i know whether it is actually accessing my custom database table?