-
1. Re: Reassign Swimlanes NullpointerException
icyjamie Sep 30, 2005 4:41 AM (in response to julian_k)I hope your swimlane really is named : "swimalneid" and not "swimlaneid"
-
2. Re: Reassign Swimlanes NullpointerException
kukeltje Sep 30, 2005 4:44 AM (in response to julian_k)or daleniwims
-
3. Re: Reassign Swimlanes NullpointerException
icyjamie Sep 30, 2005 4:57 AM (in response to julian_k)well,
Indeed you get a null, but if you want to do it "dynamically", the first time you really want to create a taskInstance, the swimLane will be initialized. If you "hard-assign" somebody to the taskInstance (setActorId), the swimlane will inherit this as well. So next tasks will get the actorId.
IF you really want to do "dynamically", you need an assignmentHandler on the task or the swimlane.
Swimlanes are conceptual (the swimlane does not impose anything, it kinda learns). -
4. Re: Reassign Swimlanes NullpointerException
julian_k Sep 30, 2005 10:03 AM (in response to julian_k)Sorry for the confusion, but I posted very early in the morning. My process definition starts as follows:
<process-definition name="Test Process"> <swimlane name="swimlaneid"/> <start-state name="Start State"> <task swimlane="swimlaneid"> <controller> .....
And yes, the new swimlane id would be coming from a variable (not hard coded).
Thanks,
Julian -
5. Re: Reassign Swimlanes NullpointerException
brittm Sep 30, 2005 10:40 AM (in response to julian_k)Julian,
If I am not mistaken, your swimlane instance needs to be initialized--by default swimlane instances are not initialized until the first task that is associated with them is created. I initialize all my swimlanes up front for some of the same reasons you wish to. The code I use isMap swimlanes = pd.getTaskMgmtDefinition().getSwimlanes(); Iterator itr = swimlanes.keySet().iterator(); while(itr.hasNext()) { Swimlane swimlane = (Swimlane)swimlanes.get(itr.next()); SwimlaneInstance swi = pi.getTaskMgmtInstance().getInitializedSwimlaneInstance(new ExecutionContext(pi.getRootToken()), swimlane); }
Notice the .getInitializedSwimlaneInstance() method.
Hope this helps.
-Britt -
6. Re: Reassign Swimlanes NullpointerException
julian_k Sep 30, 2005 11:33 AM (in response to julian_k)Thanks Britt, it worked beautifully.
Julian -
7. Re: Reassign Swimlanes NullpointerException
julian_k Sep 30, 2005 12:52 PM (in response to julian_k)I read in the documentation that any task that is assigned to a swimlane should not have an actorId set. However, when trying to retrieve the taskinstances assigned to the newly instantiated swimlane, no taskinstances are returned. I then set the actorId on the TaskInstance and had no problem. Will this cause problems?
btw, I am using the findTaskInstances(...) method as follows:session.getTaskMgmtSession().findTaskInstances(newSwimlaneId);
where newSwimlaneId is the dynamically set swimlaneid referenced in the above posts.
Thanks again,
Julian -
8. Re: Reassign Swimlanes NullpointerException
julian_k Sep 30, 2005 1:25 PM (in response to julian_k)ok, so I tried this and this works as well...
((TaskInstance)processInstance.getTaskMgmtInstance().getTaskInstances().iterator().next()).assign(executionContext);
Which would be the preferred use case?
Thanks,
Julian -
9. Re: Reassign Swimlanes NullpointerException
brittm Sep 30, 2005 2:50 PM (in response to julian_k)Take a look at my complete process creation code and see if it serves your needs.
ProcessDefinition pd = graphSession.findLatestProcessDefinition(procDefName); jbpmSession.beginTransaction(); ProcessInstance pi = new ProcessInstance(pd); //This ensures that all swimlanes are initialized and available for reporting and reassignment immediately. //If we don't initialize them up front, they won't be created until a task calls for them. Map swimlanes = pd.getTaskMgmtDefinition().getSwimlanes(); Iterator itr = swimlanes.keySet().iterator(); while(itr.hasNext()) { Swimlane swimlane = (Swimlane)swimlanes.get(itr.next()); SwimlaneInstance swi = pi.getTaskMgmtInstance().getInitializedSwimlaneInstance(new ExecutionContext(pi.getRootToken()), swimlane); } //If this process definition defines a startTask in the StartState, we'll have to // explicitly create it--it won't be created otherwise... if (pd.getTaskMgmtDefinition().getStartTask() != null) { //The start task will be assigned to the currently authenticated user (as understood by Jbpm), and that // user WILL overwrite any default swimlane assignment. TaskInstance startTask = pi.getTaskMgmtInstance().createStartTaskInstance(); //Unless our application's authentication scheme has been tied into Jbpm's, we // should manually assign the startTask to a user as well as manually set any swimlane // referenced by this task, otherwise both will be null. startTask.setActorId(user); if(startTask.getSwimlaneInstance() != null) { startTask.getSwimlaneInstance().setActorId(user); } }else { //If our new process doesn't have a startTask defined, we may want to get the new process rolling... // Although, some executions may want to set process variables, etc. before // continuing, in which case they should do such and signal for themselves. //pi.signal(); } graphSession.saveProcessInstance(pi); jbpmSession.commitTransaction();
This is a work in progress, but so far, this code has worked reliably for me. Can anyone find flaws in this process instantiation?
Thanks,
Britt -
10. Re: Reassign Swimlanes NullpointerException
julian_k Sep 30, 2005 3:11 PM (in response to julian_k)Would you mind posting your process deifinition as well?
Thanks,
Julian -
11. Re: Reassign Swimlanes NullpointerException
brittm Sep 30, 2005 4:02 PM (in response to julian_k)This is a process definition that I use for testing purposes...
<?xml version="1.0" encoding="UTF-8"?> <process-definition name="Test"> <!-- SWIMLANES --> <swimlane name="testLane1"> <assignment class="com.ntc.workflow.GenericAssignmentHandler"> <actorId>testActor1</actorId> <groupId>IT Department</groupId> </assignment> </swimlane> <swimlane name="testLane2"> <assignment class="com.ntc.workflow.GenericAssignmentHandler"> <actorId>testActor2</actorId> <groupId>IT Developers</groupId> </assignment> </swimlane> <!-- NODES --> <start-state name="START" > <task swimlane="testLane1" /> <transition to="EMPTY_NODE"/> </start-state> <!-- a simple 'node' should have one associated 'action' element that is responsible for doing whatever and signalling a transition. If no action is present, the node will immediately pass through to its default transition. Think of the simple node by default as a 'milestone' in the workflow --> <node name="EMPTY_NODE"> <!--<action class="com.ntc..." />--> <transition to="ASSIGNED_TASK-NODE"/> </node> <!-- a simple 'state' node should have an 'action' element to notify external processes. This external process would be responsible for signalling the state to continue. A simple 'state' will not transition automatically. <state name="EMPTY_STATE"> <transition to="ASSIGNED_TASK-NODE"/> </state>--> <task-node name="ASSIGNED_TASK-NODE"> <task name="assigned_task-node_task" swimlane="testLane1"> <!--<assignment class="com.ntc.workflow.GenericAssignmentHandler"> <actorId>brittm</actorId> </assignment>--> </task> <transition to="MULTI_TASK_NODE"/> </task-node> <!-- A task-node can automatically create the defined tasks on node enter, or can allow an actionHandler to do it. If an actionHandler is used, tasks can be specified outside of the task node and referenced in the API by name. The 'signal' property defines how/when task status signals the default transition --> <task-node name="MULTI_TASK_NODE" create-tasks="true" signal="never"> <task name="MULTI_TASK_NODE_task1" blocking="no" swimlane="testLane1" /> <task name="MULTI_TASK_NODE_task2" blocking="yes" swimlane="testLane1" /><!-- blocking means a node transition can't be taken without completion of this task--> <task name="MULTI_TASK_NODE_task3" blocking="yes" swimlane="testLane1" /> <transition name="done" to="PRIORITY_TASK_NODE"/> </task-node> <task-node name="PRIORITY_TASK_NODE" create-tasks="true" signal="never"> <task name="PRIORITY_TASK_NODE_task1" blocking="no" swimlane="testLane2" priority="2"/> <task name="PRIORITY_TASK_NODE_task2" blocking="yes" swimlane="testLane2" priority="1"/> <task name="PRIORITY_TASK_NODE_task3" blocking="yes" swimlane="testLane2" priority="3"/> <transition name="drop" to="action/DROP"/> <transition name="throw" to="action/THROW"/> </task-node> <super-state name="action"> <task-node name="DROP"> <task name="drop_task" swimlane="testLane2" /> <transition name="done" to="../END"/> </task-node> <task-node name="THROW"> <task name="keep_task" swimlane="testLane2" /> <transition name="done" to="../END"/> </task-node> </super-state> <!-- END-STATE --> <end-state name="END" /> </process-definition>
-
12. Re: Reassign Swimlanes NullpointerException
brittm Oct 3, 2005 5:47 PM (in response to julian_k)I've discoverd that initializing swimlaneInstances at process creation works great as long as you don't want to assign PooledActors. The following code initializes all swimlanes, and while actor assignments are recorded to the database as expected, any configured PooledActors are not persisted to the database.
... Map swimlanes = pd.getTaskMgmtDefinition().getSwimlanes(); Iterator itr = swimlanes.keySet().iterator(); while(itr.hasNext()) { Swimlane swimlane = (Swimlane)swimlanes.get(itr.next()); SwimlaneInstance swi = pi.getTaskMgmtInstance().getInitializedSwimlaneInstance(new ExecutionContext(pi.getRootToken()), swimlane); //at this point, swi contains both actors and PooledActors that were specified in configuration and populated with an appropriate AssignmentHandler } graphSession.saveProcessInstance(pi); jbpmSession.commitTransaction();
Subsequent peeking into the database reveals that actorId is set for the swimlaneInstance, but no PooledActors were recorded (jbpm_taskactorpool is empty).
PooledActors ARE assigned and stored when the above code fragment is not used, and swimlaneInstances are created by default when their first associated task is created.
I'm going to try to figure out where to put this in JIRA--there are already a couple of "similar, but not identical" swimlane issue entries.
-Britt -
13. Re: Reassign Swimlanes NullpointerException
brittm Oct 4, 2005 11:45 AM (in response to julian_k)Jira issue created: http://jira.jboss.com/jira/browse/JBPM-395
-
14. Re: Reassign Swimlanes NullpointerException
brittm Oct 7, 2005 4:26 PM (in response to julian_k)The problem with PooledActors is solved with a hack to my code example.
//This ensures that all swimlanes are initialized and available for reporting and reassignment immediately. //If we don't initialize them up front, they won't be created until a task calls for them. Map swimlanes = pd.getTaskMgmtDefinition().getSwimlanes(); Iterator itr = swimlanes.keySet().iterator(); while(itr.hasNext()) { Swimlane swimlane = (Swimlane)swimlanes.get(itr.next()); SwimlaneInstance swi = pi.getTaskMgmtInstance().getInitializedSwimlaneInstance(new ExecutionContext(pi.getRootToken()), swimlane); //We have to do this cause it doesn't automatically happen when we call // swimlaneInstance.setPooledActors() Set pooledActors = swi.getPooledActors(); Iterator paItr = pooledActors.iterator(); while(paItr.hasNext()) { ( (PooledActor)paItr.next() ).setSwimlaneInstance(swi); } }
-Britt