cancel
Showing results for 
Search instead for 
Did you mean: 

Activiti 5.3 and Spring Security Integration

limcheekin
Champ on-the-rise
Champ on-the-rise
Hi there,

I try to integrate Activiti and Spring Security by implement a custom SpringProcessEngineConfiguration and Session Factory. Please see the following code:


package org.grails.activiti.springsecurity;

import org.activiti.spring.SpringProcessEngineConfiguration;
import org.activiti.engine.ProcessEngine;
import java.util.ArrayList;

class SpringSecurityProcessEngineConfiguration extends SpringProcessEngineConfiguration {
   public ProcessEngine buildProcessEngine() {
      ArrayList customSessionFactories = new ArrayList(1);
      customSessionFactories.add(new SpringSecurityIdentitySessionFactory());
      setCustomSessionFactories(customSessionFactories);
      return super.buildProcessEngine();
   }
}


package org.grails.activiti.springsecurity;

import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;

class SpringSecurityIdentitySessionFactory implements SessionFactory {
  
   public Class<?> getSessionType() {
      return SpringSecurityIdentitySession.class;
   }
   
   public Session openSession() {
      return new SpringSecurityIdentitySession();
   }

}

Then, I configure org.grails.activiti.springsecurity.SpringSecurityProcessEngineConfiguration in spring's application context file to initialize Activiti process engine. Everything seems working fine without any error. But when I run the integration tests of Activiti's identityService, no invocation route to custom SpringSecurityIdentitySession class. Did I missed anything?

Fyi, I am using Activiti 5.3.

Thanks in advance. Wish to hear from you soon!

Best regards,
Chee Kin
10 REPLIES 10

frederikherema1
Star Contributor
Star Contributor
What base-test class are you using? You should check how the engine is obtained in the test-class.

limcheekin
Champ on-the-rise
Champ on-the-rise
What base-test class are you using? You should check how the engine is obtained in the test-class.
Thanks for fast response. Is there anything wrong with my codes in previous post?

I am writing integration tests in Grails environment, I think it is a bit different compare to Activiti test cases. I would like to tell you that all integration tests passed for Activiti 5.0.rc1 and Spring Security Integration. Below is code of tests:

package org.grails.activiti.springsecurity

import grails.test.*

class SpringSecurityIdentitySessionTests extends GrailsUnitTestCase {
def identityService
def springSecurityService

protected void setUp() {
  super.setUp()
}

protected void tearDown() {
  super.tearDown()
}

void testSelectAllUsers() {
  def org1 = new Organization(name: 'ProcessCanvas.com').save(failOnError: true)
  def users = [
   new User(organization: org1,
   email: 'admin@activiti.org',
   firstName: 'Admin',
   lastName: 'User',
   password: springSecurityService.encodePassword('admin'),
   enabled: true).save(failOnError: true),
   new User(organization: org1,
   email: 'admin2@activiti.org',
   firstName: 'Admin2',
   lastName: 'User2',
   password: springSecurityService.encodePassword('admin2'),
   enabled: true).save(failOnError: true)
  ]
  assertEquals users, identityService.createUserQuery().orderByUserLastName().asc().orderByUserFirstName().asc().list()
}

void testSelectAllUsersCount() {
  def org1 = new Organization(name: 'ProcessCanvas.com').save(failOnError: true)
  def users = [
   new User(organization: org1,
   email: 'admin@activiti.org',
   firstName: 'Admin',
   lastName: 'User',
   password: springSecurityService.encodePassword('admin'),
   enabled: true).save(failOnError: true),
   new User(organization: org1,
   email: 'admin2@activiti.org',
   firstName: 'Admin2',
   lastName: 'User2',
   password: springSecurityService.encodePassword('admin2'),
   enabled: true).save(failOnError: true)
  ]
  assertEquals "users.size()", users.size(), identityService.createUserQuery().count()
}

void testFindGroupsByUser() {
  def org1 = new Organization(name: 'ProcessCanvas.com').save(failOnError: true)
  def user = new User(organization: org1,
  email: 'admin@activiti.org',
  firstName: 'Admin',
  lastName: 'User',
  password: springSecurityService.encodePassword('admin'),
  enabled: true).save(failOnError: true)
  def group1 = new UserGroup(name: "User Group 1", organization: org1).save(failOnError: true)
  def group2 = new UserGroup(name: "User Group 2", organization: org1).save(failOnError: true)
  UserUserGroup.create(user, group1)
  UserUserGroup.create(user, group2)
  assertEquals ([group1, group2], identityService.createGroupQuery().groupMember(user.id).orderByGroupId().asc().list())
}

void testFindGroupsByUserCount() {
  def org1 = new Organization(name: 'ProcessCanvas.com').save(failOnError: true)
  def user = new User(organization: org1,
  email: 'admin@activiti.org',
  firstName: 'Admin',
  lastName: 'User',
  password: springSecurityService.encodePassword('admin'),
  enabled: true).save(failOnError: true)
  def group1 = new UserGroup(name: "User Group 1", organization: org1).save(failOnError: true)
  def group2 = new UserGroup(name: "User Group 2", organization: org1).save(failOnError: true)
  UserUserGroup.create(user, group1)
  UserUserGroup.create(user, group2)
  assertEquals 2, identityService.createGroupQuery().groupMember(user.id).count()
}

void testFindUsersByGroup() {
  def org1 = new Organization(name: 'ProcessCanvas.com').save(failOnError: true)
  def users = [
   new User(organization: org1,
   email: 'admin@activiti.org',
   firstName: 'Admin',
   lastName: 'User',
   password: springSecurityService.encodePassword('admin'),
   enabled: true).save(failOnError: true),
   new User(organization: org1,
   email: 'admin2@activiti.org',
   firstName: 'Admin2',
   lastName: 'User2',
   password: springSecurityService.encodePassword('admin2'),
   enabled: true).save(failOnError: true),
    new User(organization: org1,
   email: 'admin3@activiti.org',
   firstName: 'Admin3',
   lastName: 'User3',
   password: springSecurityService.encodePassword('admin3'),
   enabled: true).save(failOnError: true)
  ]
  def group1 = new UserGroup(name: "User Group 1", organization: org1).save(failOnError: true)
  UserUserGroup.create(users[0], group1)
  UserUserGroup.create(users[2], group1)
   assertEquals ([users[0], users[2]], identityService.createUserQuery().memberOfGroup(group1.id).orderByUserId().asc().list())
}
}


Is there anything wrong with my code above?

Best regards,
Chee Kin

frederikherema1
Star Contributor
Star Contributor
The code for setting the custom session-factory should be okay (you set the customSessionFactories before init() is called, so the will be picked up). Although, can also be done using spring-wiring without actually having to override the SpringProcessEngineConfiguration.

How does the test get it's engine? Does it use the same spring-context as your normal app and uses the auto-injection stuff in grails (def identityService)?

limcheekin
Champ on-the-rise
Champ on-the-rise
The code for setting the custom session-factory should be okay (you set the customSessionFactories before init() is called, so the will be picked up). Although, can also be done using spring-wiring without actually having to override the SpringProcessEngineConfiguration.
Can you show sample configuration of spring wiring?

How does the test get it's engine? Does it use the same spring-context as your normal app and uses the auto-injection stuff in grails (def identityService)?

I am using auto-injection stuff in Grails.

Thanks in advance. Wish to hear from you again!

Best regards,
Chee Kin

limcheekin
Champ on-the-rise
Champ on-the-rise
The code for setting the custom session-factory should be okay (you set the customSessionFactories before init() is called, so the will be picked up). Although, can also be done using spring-wiring without actually having to override the SpringProcessEngineConfiguration.
I am using the approach suggested by you. The SpringSecurityProcessEngineConfiguration class is not necessary.

This issue happened even when the application is running (not just integration tests), I can see the getSessionType() being invoked upon the Activiti engine initialization, but not the openSession() when the app retrieves users and groups.

Any advice on how to troubleshoot this issue is very much appreciated.

Thanks.

Best regards,
Chee Kin

frederikherema1
Star Contributor
Star Contributor
Can you check if you see any difference in configuration from this and your solution:

/activiti-engine/src/test/java/org/activiti/standalone/cfg/identity/CustomIdenstitySessionTest.java
/activiti-engine/src/test/resources/org/activiti/standalone/cfg/identity/customIdentitySession-activiti.cfg.xml

This shows the plugging of the identity-session how we 'envisioned' it Smiley Wink

limcheekin
Champ on-the-rise
Champ on-the-rise
Can you check if you see any difference in configuration from this and your solution:

/activiti-engine/src/test/java/org/activiti/standalone/cfg/identity/CustomIdenstitySessionTest.java
/activiti-engine/src/test/resources/org/activiti/standalone/cfg/identity/customIdentitySession-activiti.cfg.xml

This shows the plugging of the identity-session how we 'envisioned' it Smiley Wink

Thanks to show me a ways. I will check it out.

Best regards,
Chee Kin

limcheekin
Champ on-the-rise
Champ on-the-rise
Can you check if you see any difference in configuration from this and your solution:

/activiti-engine/src/test/java/org/activiti/standalone/cfg/identity/CustomIdenstitySessionTest.java
/activiti-engine/src/test/resources/org/activiti/standalone/cfg/identity/customIdentitySession-activiti.cfg.xml

This shows the plugging of the identity-session how we 'envisioned' it Smiley Wink
When looking into your implementation of CustomIdentitySessionFactory class, I found the mistake in my code below (You can compare it with the first post):

package org.grails.activiti.springsecurity;

import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.activiti.engine.impl.cfg.IdentitySession;

class SpringSecurityIdentitySessionFactory implements SessionFactory {
static final Log LOG = LogFactory.getLog(SpringSecurityIdentitySessionFactory.class);
  
public Class<?> getSessionType() {
  return IdentitySession.class;
}

public Session openSession() {
  return new SpringSecurityIdentitySession();
}
}
getSessionType() should return IdentitySession.class instead of SpringSecurityIdentitySession.class.

Best regards,
Chee Kin

frederikherema1
Star Contributor
Star Contributor
Damn… Should have thought of that Smiley Wink Glad you got it working now.