Today, I write about “Tasks List” View in workbench (a.k.a. Business Central).
Most of users don’t need to worry about such internal but I just wanted to note as my work log.
Environment: BPM Suite 6.4.x (= jbpm-wb 6.5.x)
Firstly, I configured a custom UserGroupCallback to the workbench (uisng a custom UserGroupInfoProducer via beans.xml). But “Group” tab of “Tasks List” View displays tasks for login user’s groups resolved by JAAS instead of tasks for login user’s groups resolved by the custom UserGroupCallback.
I set breapoints and debugged around so I found that the custom UserGroupCallback is properly configured to TaskService in the workbench. The problem is that “Tasks List” is not using TaskService. How does it query database? Let’s drill down from client side.
As we cannot set a breakpoint in GWT client code, the first approach is to grep source codes with text label “Tasks List”. (Hmm, I’m not yet confortable with Chrome client side debug)
Finally I listed 2 candidates:
https://github.com/kiegroup/jbpm-wb/blob/6.5.x/jbpm-console-ng-human-tasks/jbpm-console-ng-human-tasks-client/src/main/java/org/jbpm/console/ng/ht/client/editors/taskslist/grid/dash/DataSetTasksListGridPresenter.java
https://github.com/kiegroup/jbpm-wb/blob/6.5.x/jbpm-console-ng-human-tasks/jbpm-console-ng-human-tasks-client/src/main/java/org/jbpm/console/ng/ht/client/editors/taskslist/grid/TasksListGridPresenter.java
I was not sure which is actually used at the stage. Then I looked into those client codes and found the backend services called.
DataSetTasksListGridPresenter -> DataSetLookupServicesImpl
TasksListGridPresenter -> TaskQueryServiceImpl
By setting breakpoints, I got finally sure DataSetTasksListGridPresenter -> DataSetLookupServicesImpl is actually working.
From client side, we may track the source codes like this:
https://github.com/kiegroup/kie-wb-distributions/blob/6.5.x/kie-wb/kie-wb-webapp/src/main/java/org/kie/workbench/client/KieWorkbenchEntryPoint.java#L303
-> jBPM workbech menu places “DataSet Tasks” for Task view
https://github.com/kiegroup/jbpm-wb/blob/6.5.x/jbpm-console-ng-human-tasks/jbpm-console-ng-human-tasks-client/src/main/java/org/jbpm/console/ng/ht/client/perspectives/DataSetTasksListPerspective.java#L36
-> “DataSet Tasks” is DataSetTasksListPerspective. It places “DataSet Tasks List”.
https://github.com/kiegroup/jbpm-wb/blob/6.5.x/jbpm-console-ng-human-tasks/jbpm-console-ng-human-tasks-client/src/main/java/org/jbpm/console/ng/ht/client/editors/taskslist/grid/dash/DataSetTasksListGridPresenter.java#L40
-> “DataSet Tasks List” is DataSetTasksListGridPresenter
Anyway, I prefer debugger/breakpont so that I can confirm what’s actually happening.
Now let’s see how data is queried.
By drilling down with a debugger, SQL is constructed by SQLDataSetProvider and finally executed with plain JDBC.
Daemon Thread [http-127.0.0.1:8080-5] (Suspended) owns: Http11Processor (id=214) JDBCUtils.executeQuery(Connection, String) line: 77 Select.fetch() line: 183 SQLDataSetProvider$LookupProcessor.run() line: 711 SQLDataSetProviderCDI(SQLDataSetProvider)._lookupDataSet(SQLDataSetDef, DataSetLookup) line: 441 SQLDataSetProviderCDI(SQLDataSetProvider).lookupDataSet(DataSetDef, DataSetLookup) line: 235 SQLDataSetProviderCDI$Proxy$_$$_WeldClientProxy.lookupDataSet(DataSetDef, DataSetLookup) line: not available DataSetManagerCDI(DataSetManagerImpl).lookupDataSet(DataSetLookup) line: 153 DataSetManagerCDI$Proxy$_$$_WeldClientProxy.lookupDataSet(DataSetLookup) line: not available DataSetLookupServicesImpl.lookupDataSet(DataSetLookup) line: 79 DataSetLookupServicesImpl$Proxy$_$$_WeldClientProxy.lookupDataSet(DataSetLookup) line: not available NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62 DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43 Method.invoke(Object, Object...) line: 497 ValueReplyRPCEndpointCallback(AbstractRPCMethodCallback).invokeMethodFromMessage(Message) line: 48 ValueReplyRPCEndpointCallback.callback(Message) line: 24 RemoteServiceCallback.callback(Message) line: 54 CDIExtensionPoints$2.callback(Message) line: 396 DeliveryPlan.deliver(Message) line: 47 ServerMessageBusImpl.sendGlobal(Message) line: 297 SimpleDispatcher.dispatchGlobal(Message) line: 46 ErraiServiceImpl<S>.store(Message) line: 97 ...
The executed SQL is like this:
SELECT ACTIVATIONTIME "activationTime", ACTUALOWNER "actualOwner", CREATEDBY "createdBy", CREATEDON "createdOn", DEPLOYMENTID "deploymentId", DESCRIPTION "description", DUEDATE "dueDate", NAME "name", PARENTID "parentId", PRIORITY "priority", PROCESSID "processId", PROCESSINSTANCEID "processInstanceId", PROCESSSESSIONID "processSessionId", STATUS "status", TASKID "taskId", WORKITEMID "workItemId" FROM (SELECT T.ACTIVATIONTIME, T.ACTUALOWNER, T.CREATEDBY, T.CREATEDON, T.DEPLOYMENTID, T.DESCRIPTION, T.DUEDATE, T.NAME, T.PARENTID, T.PRIORITY, T.PROCESSID, T.PROCESSINSTANCEID, T.PROCESSSESSIONID, T.STATUS, T.TASKID, T.WORKITEMID, OE.ID FROM AUDITTASKIMPL T, PEOPLEASSIGNMENTS_POTOWNERS PO, ORGANIZATIONALENTITY OE WHERE T.TASKID = PO.TASK_ID AND PO.ENTITY_ID = OE.ID) "dbSQL" WHERE (STATUS = 'Ready' OR STATUS = 'Reserved' OR STATUS = 'InProgress') AND ((((ID = 'bpmsAdmin' OR ID = 'admin') OR ID = 'bpmsAdmin') AND (ACTUALOWNER = '' OR ACTUALOWNER IS NULL)) OR ACTUALOWNER = 'bpmsAdmin') GROUP BY TASKID, ACTIVATIONTIME, ACTUALOWNER, CREATEDBY, CREATEDON, DEPLOYMENTID, DESCRIPTION, DUEDATE, NAME, PARENTID, PRIORITY, PROCESSID, PROCESSINSTANCEID, PROCESSSESSIONID, STATUS, WORKITEMID ORDER BY CREATEDON ASC LIMIT 10
The WHERE part “(ID = ‘bpmsAdmin’ OR ID = ‘admin’)” has to do with the JAAS resolution. Where is it introduced? Going up the stack, I found the provied DataSetLookup object already contains LogicalExprFilter:
(((id = bpmsAdmin OR id = admin OR id = bpmsAdmin) AND (actualOwner = OR actualOwner is_null )) OR actualOwner = bpmsAdmin)
So it was passed from client side.
Then I go back to client side source codes again and go through how DataSetLookup filter is constructed. Finally, I came to AbstractTasksListGridPresenter.getUserGroupFilters() adds filters based on user/groups based on login Errai User when JAAS based.
https://github.com/kiegroup/jbpm-wb/blob/6.5.x/jbpm-console-ng-human-tasks/jbpm-console-ng-human-tasks-client/src/main/java/org/jbpm/console/ng/ht/client/editors/taskslist/grid/AbstractTasksListGridPresenter.java#L166
https://github.com/kiegroup/jbpm-wb/blob/6.5.x/jbpm-console-ng-human-tasks/jbpm-console-ng-human-tasks-client/src/main/java/org/jbpm/console/ng/ht/client/editors/taskslist/grid/AbstractTasksListGridPresenter.java#L208-L229
I’ve been talking about BPM Suite 6.4.x (= jbpm-wb 6.5.x). In jBPM 7, the implementation is different. Client side is renamed to TaskListViewImpl.
Since jBPM 7, execution engine is consolidated to kie-server (a.k.a. Decision Server). So QueryDataResource is called as a backend service.
Thread [default task-33] (Suspended (breakpoint at line 201 in SQLDataSetProvider)) SQLDataSetProvider.lookupDataSet(DataSetDef, DataSetLookup) line: 201 DataSetManagerImpl.lookupDataSet(DataSetLookup) line: 154 QueryServiceImpl.query(String, QueryResultMapper<T>, QueryContext, QueryParamBuilder<?>) line: 268 QueryServiceImpl.query(String, QueryResultMapper<T>, QueryContext, QueryParam...) line: 210 QueryDataServiceBase.queryFiltered(String, String, Integer, Integer, String, String) line: 179 QueryDataResource.runQueryFiltered(HttpHeaders, String, String, String, Integer, Integer, String) line: 341 ...
PotOwnerTasksPreprocessor is called instead of AbstractTaskListPresenter.getUserGroupFilters(). The behaviour looks similar.
Thread [default task-50] (Suspended) PotOwnerTasksPreprocessor.preprocess(DataSetLookup) line: 57 DataSetManagerImpl.lookupDataSet(DataSetLookup) line: 149 QueryServiceImpl.query(String, QueryResultMapper<T>, QueryContext, QueryParamBuilder<?>) line: 268 QueryServiceImpl.query(String, QueryResultMapper<T>, QueryContext, QueryParam...) line: 210 QueryDataServiceBase.queryFiltered(String, String, Integer, Integer, String, String) line: 179 QueryDataResource.runQueryFiltered(HttpHeaders, String, String, String, Integer, Integer, String) line: 341 ...
I filed a JIRA for this so it could be fixed/changed in the near future.
https://issues.jboss.org/browse/RHBA-401
https://issues.jboss.org/browse/RHBPMS-5126