BPM assign task to [Cuba] roles, not individual users

Hi,

I was just going through BPM module in the Cuba Platform and was unable to find on the documentation the concept related to swimlanes . I followed the tutorial (Quick Start for BPM) and was able to implement end to end with the assignment of task to individual users on the Cuba platform. My query is if it’s possible to map the BPM Roles created in the Process model to Cuba Roles created form the Cuba User management module.

Also if you could throw some light on the automatic assignment of task to users in swimlane which is just grouping of jobs. So that once the task is initiated it gets assigned to all users in the role (Swimlane/group) automatically rather than programming it. My experience with other BPM implementations is that we start the process modelling with Swimlanes and assign users to the swimlane, so the assignment of Human Tasks happens automatically based on the BPMN flow. Of course, when needed this could be programmed to have logical assignment for parallel and sequential tasks.

Hi!

The swimlanes aren’t supported yet. Of course, you can draw them in the model, but they won’t be taken into account during the process execution. But the concept of ‘process roles’ kind of replaces the swimlane functionality. You can set the process role for the user task, set the ‘Muti-instance type’ property, assign multiple users to the process role and this task will be assigned to all users that were associated with the process role on process start.

Roles of the user management module have a different purpose and are not related to BPM process roles. You can use them for automatic task assignment, but you will have to implement the creation of ProcActor entities for each user of Cuba user role on process start by your own.

Automatic process roles assignment to the predefined user group, as well as the swimlanes support, are important features and they are in our roadmap.

If I didn’t fully answered you questions, please feel free to ask.

1 Like

Hi Max,

Thank you very much the response. Just to clarify on this statement “You can set the process role for the user task, set the ‘Muti-instance type’ property, assign multiple users to the process role and this task will be assigned to all users that were associated with the process role on process start.” - How do we actually assign multiple users to the process role on Cuba platform? Actually I’m just trying to understand, do we need to create separate roles for BPM Human tasks from application roles which are created on Cuba platform? If those are two different platform is there a way to link the two?

To simply my query:
I created controller & manager process roles in BPM Process Model - How do i assign Users created on Cuba platform to these two process roles during design time & for runtime can you guide on the APIs to be access from Controller?

Creation of ProcRole entities for each user of Cuba user role - Can you guide on the API to implement the same for few users and test the funtionality?

Hi Max,

Thank you very much the response. Just to clarify on this statement “You can set the process role for the user task, set the ‘Muti-instance type’ property, assign multiple users to the process role and this task will be assigned to all users that were associated with the process role on process start.” - How do we actually assign multiple users to the process role on Cuba platform? Actually I’m just trying to understand, do we need to create separate roles for BPM Human tasks from application roles which are created on Cuba platform? If those are two different platform is there a way to link the two?

To simply my query:

I created controller & manager process roles in BPM Process Model - How do i assign Users created on Cuba platform to these two process roles during design time & for runtime can you guide on the APIs to be access from Controller?

Creation of ProcRole entities for each user of Cuba user role - Can you guide on the API to implement the same for few users and test the funtionality?

You are right, the security role and the business process role are separate entities. The security role defines permissions (what screens are available, what entity attributes can be edited, etc.), the process role defines only who will get the process task. They are not linked at present.

As for creating ProcessActors for each user with the given security role, I attached a demo project, that illustrates the process.

The project is similar to the one from the quick start. There is a Contract entity, Contract approval process with one task assigned to the Manager process role and screens for editing the contract.
If you create the contract, save the entity and click the Start process button, you will see that users who have ‘someSecRole’ security role are automatically assigned to the Manager process role.

The code that does this is inside the MyCustomForm class (see the createProcActors() method). myCustomForm is a new process form in the project (the discussion of process forms is here).
MyCustomForm has two parameters: secRoleName and procRoleCode (see the screenshots attached).

There is no special API for creating ProcActors, just a regular entities creation. The BPM data model is described here

demo-1

demo-2

bpm-demo-2.zip (89.0K)

2 Likes

Hi Max,

I tried following these steps and those of the MyCustomForm thread but my custom form is not showing up as an available form in the BPM editor. Has anything changed in the last year? I tried importing the two sample projects you have provided but I am unable to open them: “The project uses an application component that is not supported by this version of Studio or was not found…”. My bpm demo project is attached.

bpm-demo.zip (689.0K)

The app log tells me:
"com.haulmont.bpm.gui.app.ProcessFormRepository - Resource app-bpm-forms.xml not found, ignore it"
But I don’t understand why. The app-bpm-forms.xml file is in the same directory as web-app.properties.

Hi,
you should either move your app-bpm-forms.xml file to the root package (under the "src directory) or specify the correct path in the web-app.properties:

bpm.formsConfig = bpm-forms.xml com/company/bpmdemo/app-bpm-forms.xml

Yes, that worked. Thanks.

thank you for your sample project, but i can’t use it in my project, where i need to connect processRoles to systemRoles automatically by pushing standard button, and the method findProcRole throws an

java.lang.IllegalArgumentException: MetaClass not found for myproject$ProcRole
	at com.haulmont.cuba.core.sys.CachingMetadataSession.getClassNN(CachingMetadataSession.java:70)
	at com.haulmont.cuba.core.global.ExtendedEntities.getEffectiveMetaClass(ExtendedEntities.java:115)
	at com.haulmont.cuba.core.sys.jpql.DomainModel.getEntityByName(DomainModel.java:62)
	at com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode.identifyVariableEntity(IdentificationVariableNode.java:93)
	at com.haulmont.cuba.core.sys.jpql.IdVarSelector.post(IdVarSelector.java:88)
	at org.antlr.runtime.tree.TreeVisitor.visit(TreeVisitor.java:66)
	at org.antlr.runtime.tree.TreeVisitor.visit(TreeVisitor.java:60)
	at org.antlr.runtime.tree.TreeVisitor.visit(TreeVisitor.java:60)
	at org.antlr.runtime.tree.TreeVisitor.visit(TreeVisitor.java:60)
	at com.haulmont.cuba.core.sys.jpql.QueryTreeAnalyzer.prepare(QueryTreeAnalyzer.java:58)
	at com.haulmont.cuba.core.sys.jpql.QueryTreeAnalyzer.prepare(QueryTreeAnalyzer.java:46)
	at com.haulmont.cuba.core.global.QueryParserAstBased.getQueryAnalyzer(QueryParserAstBased.java:78)
	at com.haulmont.cuba.core.global.QueryParserAstBased.getEntityName(QueryParserAstBased.java:110)
	at sun.reflect.GeneratedMethodAccessor117.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
	at com.haulmont.cuba.core.sys.PerformanceLogInterceptor.aroundInvoke(PerformanceLogInterceptor.java:29)
	at sun.reflect.GeneratedMethodAccessor89.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
	at com.sun.proxy.$Proxy277.getEntityName(Unknown Source)
	at com.haulmont.cuba.core.sys.PersistenceSecurityImpl.applyConstraints(PersistenceSecurityImpl.java:63)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
	at com.haulmont.cuba.core.sys.PerformanceLogInterceptor.aroundInvoke(PerformanceLogInterceptor.java:29)
	at sun.reflect.GeneratedMethodAccessor89.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
	at com.sun.proxy.$Proxy175.applyConstraints(Unknown Source)
	at com.haulmont.cuba.core.app.DataServiceQueryBuilder.applyConstraints(DataServiceQueryBuilder.java:171)
	at com.haulmont.cuba.core.app.DataServiceQueryBuilder.getQuery(DataServiceQueryBuilder.java:119)
	at com.haulmont.cuba.core.app.RdbmsStore.createQuery(RdbmsStore.java:541)
	at com.haulmont.cuba.core.app.RdbmsStore.load(RdbmsStore.java:130)
	at com.haulmont.cuba.core.app.DataManagerBean.load(DataManagerBean.java:68)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.haulmont.cuba.core.app.DataManagerBean$SecureDataManagerInvocationHandler.invoke(DataManagerBean.java:356)
	at com.sun.proxy.$Proxy347.load(Unknown Source)
	at com.haulmont.cuba.core.app.DataServiceBean.load(DataServiceBean.java:46)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
	at com.haulmont.cuba.core.sys.ServiceInterceptor.aroundInvoke(ServiceInterceptor.java:115)
	at sun.reflect.GeneratedMethodAccessor121.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
	at com.sun.proxy.$Proxy205.load(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.haulmont.cuba.core.sys.remoting.LocalServiceInvokerImpl.invoke(LocalServiceInvokerImpl.java:94)
	at com.haulmont.cuba.web.sys.remoting.LocalServiceProxy$LocalServiceInvocationHandler.invoke(LocalServiceProxy.java:148)
	at com.sun.proxy.$Proxy30.load(Unknown Source)
	at com.haulmont.cuba.client.sys.DataManagerClientImpl.load(DataManagerClientImpl.java:47)
	at com.haulmont.cuba.core.global.DataManager$load.call(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
	at ru.spacecorp.myproject.web.bpm.screens.ProcFormStart.findProcRole(ProcFormStart.groovy:64)
	at ru.spacecorp.myproject.web.bpm.screens.ProcFormStart.init(ProcFormStart.groovy:42)
	at com.haulmont.cuba.gui.WindowManager.init(WindowManager.java:1178)
	at com.haulmont.cuba.gui.WindowManager.initWrapperFrame(WindowManager.java:1167)
	at com.haulmont.cuba.gui.WindowManager.createWindow(WindowManager.java:540)
	at com.haulmont.cuba.gui.WindowManager.openWindow(WindowManager.java:708)
	at com.haulmont.cuba.web.WebWindowManager.openWindow(WebWindowManager.java:144)
	at com.haulmont.cuba.web.gui.components.WebFrame.openWindow(WebFrame.java:266)
	at com.haulmont.bpm.gui.action.StartProcessAction.actionPerform(StartProcessAction.java:52)
	at com.haulmont.cuba.web.gui.components.WebButton.performAction(WebButton.java:44)
	at com.haulmont.cuba.web.gui.components.WebButton.lambda$new$61446b05$1(WebButton.java:36)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:510)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:200)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:163)
	at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1037)
	at com.vaadin.ui.Button.fireClick(Button.java:377)
	at com.haulmont.cuba.web.toolkit.ui.CubaButton.fireClick(CubaButton.java:54)
	at com.vaadin.ui.Button$1.click(Button.java:54)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:158)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:119)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:444)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:409)
	at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)
	at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90)
	at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)
	at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1436)
	at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:385)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:301)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:192)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at com.haulmont.cuba.web.sys.CubaHttpFilter.handleNotFiltered(CubaHttpFilter.java:108)
	at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:95)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

Hi, thanks for this topic, it helped a lot. I’m working on an app, in which roles are set automatically, as i move from task to task. There is a place in my model, where process comes back to a certain user, and my model is duplicating process roles, so here’s my question, how could i avoid role duplicates in my process?

the standard start form provides datasources for all users, which is not a good thing for big projects with hundreds of users. how could i get sys$Role list instead of that?

I also can’t open “bpm-demo-2”
Firstly, I had a problem with import, there was an error: “Repository containing CUBA arifacts not found in [http: // repository. Haulmont.com:8587/nexus/content/groups/work]”.
I changed in build.gradle this part on:
" maven {
url ‘Index of /groups/work’"
but I still can’t open this project, and this error appears:
2018-03-05 16-36-58
This is my build.gradle:

build.gradle (6.4 KB)

The problem is solved