Expand my Community achievements bar.

Enhance your AEM Assets & Boost Your Development: [AEM Gems | June 19, 2024] Improving the Developer Experience with New APIs and Events

Querying who completed a User Task

Avatar

Former Community Member
This is a curly question ... sorry.



Is there a table in the ES database that actually records which user completed a task in workflow, or is this information lost?



I'm trying to access logging information about processes. It doesn't have to be in this format but I'm looking for something along the lines of:

"user-A, completed task-B at 08-28-2007-17:50:31-PST".



I've looked at the ES DB table 'tb_action_instance'. It has a column called 'completed_by_id' which seems like it could record the user but alas, it seems to always record a SystemContextAccount user for me.



Any pointers or hints please?



Regards,



Lachlan



http://www.avoka.com
18 Replies

Avatar

Former Community Member
You can use the TaskManager API to obtain information about tasks. I will post the code that will perform this task. Currently, I am working on an SDK documentation titled: Retrieving Task Information that will discuss how to obtain this type of information.

Avatar

Former Community Member
As promised -- here is the TaskManager API code example that performs a search on completed tasks -- Notice:

sf.addStatus(StatusFilter.completed)



Then information about the completed tasks -- including the user identifier and the completation time is obtained:



try{

//Set connection properties

Properties ConnectionProps = new Properties();

ConnectionProps.setProperty("DSC_DEFAULT_EJB_ENDPOINT", "jnp://localhost:1099");

ConnectionProps.setProperty("DSC_TRANSPORT_PROTOCOL","EJB");

ConnectionProps.setProperty("DSC_SERVER_TYPE", "JBoss");

ConnectionProps.setProperty("DSC_CREDENTIAL_USERNAME", "administrator");

ConnectionProps.setProperty("DSC_CREDENTIAL_PASSWORD", "password");



//Create a ServiceClientFactory object

ServiceClientFactory myFactory = ServiceClientFactory.createInstance(ConnectionProps);



//Create a TaskManagerQueryService object

TaskManagerQueryService queryManager = TaskManagerClientFactory.getQueryManager(myFactory);



//Create a TaskiManager obejct

TaskManager myTaskManager = TaskManagerClientFactory.getTaskManager(myFactory);



//Define search criteria by performing a search on

//Completed tasks

TaskFilter filter = queryManager.newTaskFilter();

StatusFilter sf = filter.newStatusFilter();

sf.addStatus(StatusFilter.completed);

filter.setStatusFiltering(sf);



//Perform the search

List result = queryManager.taskList(filter);



//Create an Iterator object and iterate through

//the List object

Iterator iter = result.iterator();

int i = 0 ;

while (iter.hasNext()) {

TaskRow myTask = (TaskRow)iter.next();



//Get the task identifier value

long taskId = myTask.getTaskId();



//Determine the user Identifier of the completed task

TaskInfo taskInfo = myTaskManager.getTaskInfo(taskId);

ParticipantInfo pastInfo = taskInfo.getAssignedTo();

String userName = pastInfo.getSpecifiedUserId();



//Get the status of the task

long taskStatus = myTask.getTaskStatus();



//Get the name of process on which this task is based

String processName = myTask.getProcessName();



Date completionTime = myTask.getCompleteTime();



//Get the task description

String taskDes = myTask.getDescription();



System.out.println("The task identifier is "+taskId +"\n"+

"The status of the task is "+taskStatus +"\n"+

"The name of the user whom completed this task is "+userName +"\n"+

"The completion time is "+ completionTime.getDate());

i++ ;

}

}



catch(Exception e)

{

e.printStackTrace();

}

Avatar

Former Community Member
Hi Scott,



Thank you very much for helping. I am grateful of the time and effort you have freely given here.



I can execute your code and it executes & provides results, but unfortunately they were not the results I was hoping to get.



On my version of the ES preview I noticed that the call to getSpecifiedUserID() always returned the principalID of the SuperAdmin, and not the user who actually completed that task.



Also it didn't seem to pick up task instances that were completed today.

Am I missing something?



Regards,



Lachlan

Avatar

Former Community Member
The getSpecifiedUserID should return the user ID of the user who is assigned the task. THe version i am using is 8.0.1 -- so i can't comment on the Preview Release. You can get an evaluation of the 8.0.1 version on the developer web site. You don't have to purchase the product in order to try it. Just go ahead and download it from this URL:



http://www.adobe.com/devnet/livecycle/

Avatar

Former Community Member
To obtain information about a completed task, specify the user whom completed the task when setting connection properties required to invoke LiveCycle ES operations.



That is, to retrieve info about tasks user A completed, then specify user A when specifying connection settings. The TaskManagerQuery service only returns those tasks for the user specified in the connection properties.



For example, to find out about Tony Blues tasks - you need to:



Properties ConnectionProps = new Properties();

ConnectionProps.setProperty("DSC_DEFAULT_EJB_ENDPOINT", "jnp://localhost:1099");

ConnectionProps.setProperty("DSC_TRANSPORT_PROTOCOL","EJB");

ConnectionProps.setProperty("DSC_SERVER_TYPE", "JBoss");

ConnectionProps.setProperty("DSC_CREDENTIAL_USERNAME", "tblue");

ConnectionProps.setProperty("DSC_CREDENTIAL_PASSWORD", "password");



//Create a ServiceClientFactory object

ServiceClientFactory myFactory = ServiceClientFactory.createInstance(ConnectionProps);



//Create a TaskManagerQueryService object

TaskManagerQueryService queryManager = TaskManagerClientFactory.getQueryManager(myFactory);

Avatar

Former Community Member
HI Lachlan



After working more with the TaskManager API, I have come up with the solution that you are seeking. You can obtain all completed tasks and then get the user name of the user (not just the user ID). The Java Code below creates this output:



The task identifier is 1

The name of the user who completed the task is SuperAdmin

The name of the process on which the task is based is MortgageLoan - Prebuilt

The completion time is 29

The task identifier is 2

The name of the user who completed the task is tblue

The name of the process on which the task is based is MortgageLoan - Prebuilt

The completion time is 29



Here is the full Java example that uses the TaskMamager API and User Manager API to get the user name:



package com.adobe.sample.taskmanager;



import java.util.*;

import com.adobe.idp.dsc.clientsdk.ServiceClientFactory;

import com.adobe.idp.taskmanager.dsc.client.query.TaskRow;

import com.adobe.idp.taskmanager.dsc.client.query.TaskSearchFilter;

import com.adobe.idp.taskmanager.dsc.client.task.ParticipantInfo;

import com.adobe.idp.taskmanager.dsc.client.task.TaskInfo;

import com.adobe.idp.taskmanager.dsc.client.task.TaskManager;

import com.adobe.idp.taskmanager.dsc.client.*;

import com.adobe.idp.um.api.infomodel.Principal;

import com.adobe.livecycle.usermanager.client.DirectoryManagerServiceClient;



public class RetrievingTasks {



public static void main(String[] args) {



try{

//Set connection properties

Properties ConnectionProps = new Properties();

ConnectionProps.setProperty("DSC_DEFAULT_EJB_ENDPOINT", "jnp://localhost:1099");

ConnectionProps.setProperty("DSC_TRANSPORT_PROTOCOL","EJB");

ConnectionProps.setProperty("DSC_SERVER_TYPE", "JBoss");

ConnectionProps.setProperty("DSC_CREDENTIAL_USERNAME", "administrator");

ConnectionProps.setProperty("DSC_CREDENTIAL_PASSWORD", "password");



//Create a ServiceClientFactory object

ServiceClientFactory myFactory = ServiceClientFactory.createInstance(ConnectionProps);



//Create a TaskManagerQueryService object

TaskManagerQueryService queryManager = TaskManagerClientFactory.getQueryManager(myFactory);



TaskManager taskManager = TaskManagerClientFactory.getTaskManager(myFactory);



//Define search criteria by performing a search on

//completed tasks

TaskSearchFilter filter = new TaskSearchFilter();

filter.setServiceName("MortgageLoan - Prebuilt");

filter.setAdminIgnoreAllAcls(true); // this line is the key



//Perform the search

List result = queryManager.taskSearch(filter);



//Create an Iterator object and iterate through

//the List object

Iterator iter = result.iterator();

int i = 0 ;

while (iter.hasNext()) {



TaskRow myTask = (TaskRow)iter.next();



//Make sure that the task is completed- 100 represents

//a completed task



if (myTask.getTaskStatus()== 100)

{

//Get the name of the user who completed the task

long taskId = myTask.getTaskId();



TaskInfo taskInfo= taskManager.getTaskInfo(taskId);

ParticipantInfo user = taskInfo.getAssignedTo();

String userId = user.getSpecifiedUserId();



String userName = getUserName(myFactory, userId);



//Get the name of the process

String processName = myTask.getProcessName();



//Get the completion time

Date completionTime = myTask.getCompleteTime();



//Display task information

System.out.println("The task identifier is "+taskId +"\n"+

"The name of the user who completed the task is "+ userName +"\n"+

"The name of the process on which the task is based is "+ processName+"\n"+

"The completion time is "+ completionTime.getDate());

i++ ;

}

}

}



catch(Exception e)

{

e.printStackTrace();

}

}



static private String getUserName(ServiceClientFactory myFactory, String userId){

String userName = "";

try{

//Create a DirectoryManagerServiceClient object DirectoryManagerServiceClient dirClient = new DirectoryManagerServiceClient(myFactory);



//Find a local user

Principal prin = dirClient.findPrincipal(userId);

userName = prin.getCanonicalName();

}



catch(Exception e)

{

e.printStackTrace();

}

return userName;

}



}

Avatar

Former Community Member

Hi Scott,

I need exactly this information for my project but I was wondering how to do it using webservice inplace of EJBs because client application can call the LiveCycle ES 2 server only through webservice. I read somewhere that the Task Manager API are not fully supported on webservice and we need to do the workaround by creating a process (because process has a wsdl associated with it). Can you please provide an .lca file and a java code that shows how to do this?

Thanks!!

Avatar

Former Community Member
Hi Scott,



Helpful and informative!



Thank you very much. I am grateful for all the help and assistance you've provided in finding an API based solution.



Kind regards,



Lachlan

Avatar

Former Community Member
I found a small problem in above code. The method setServiceName in the class TaskSearchFilter is undefined. Any clue?

Avatar

Former Community Member
The setServiceName is a valid method that belongs to com.adobe.idp.taskmanager.dsc.client.query.TaskSearchFilter. If the API you are using does have contain this method, then you may have an outdated build. There is an URL in this thread that points to a build that is updated.

Avatar

Former Community Member
Thanks for your help. But i managed by using



((TaskSearchingUtil)filter.getPropertyUtil()).setProcessVariableServiceName("myservice");

Avatar

Former Community Member
Hi,



I've problem running the sample codes given by Scott. I keep getting the following error. Any advice would be greatly appreciated



java.lang.IllegalStateException

at com.adobe.idp.dsc.clientsdk.ServiceClientFactory$1.handleThrowable(ServiceClientFactory.java:68)

at com.adobe.idp.dsc.clientsdk.ServiceClient.invoke(ServiceClient.java:220)

at com.adobe.idp.taskmanager.dsc.client.TypedTaskManagerQueryService.taskSearch(TypedTaskManagerQueryService.java:218)

at RetrievingTasks.main(RetrievingTasks.java:62)

Caused by: java.lang.NoClassDefFoundError: javax/ejb/EJBException

at com.adobe.idp.dsc.clientsdk.ServiceClientFactory.evaluateMessageDispatcher(ServiceClientFactory.java:512)

at com.adobe.idp.dsc.clientsdk.ServiceClient.invoke(ServiceClient.java:215)

Avatar

Former Community Member
Ah~~ silly me. Forgot to include the jboss jar files...

Avatar

Former Community Member
just to double check, when you got that error, it was because you hadn't included the jbossall-client.jar file? Because I'm getting the exact same exception and I've included the jar file. I think in my case it may because of my connection properties;



Properties ConnectionProps = new Properties();

ConnectionProps.setProperty("DSC_DEFAULT_EJB_ENDPOINT", "jnp://wfdev:1099");

ConnectionProps.setProperty("DSC_TRANSPORT_PROTOCOL","EJB");

ConnectionProps.setProperty("DSC_SERVER_TYPE", "JBoss");

ConnectionProps.setProperty("DSC_CREDENTIAL_USERNAME", "administrator");

ConnectionProps.setProperty("DSC_CREDENTIAL_PASSWORD", "password");



As you can see, my server is not local, so i went ahead and added the jar file, but i'm still getting the same error. Any help would be greatly apopreciated!

Avatar

Former Community Member
just to double check, when you got that error, it was because you hadn't included the jbossall-client.jar file? Because I'm getting the exact same exception and I've included the jar file. I think in my case it may because of my connection properties;



Properties ConnectionProps = new Properties();

ConnectionProps.setProperty("DSC_DEFAULT_EJB_ENDPOINT", "jnp://wfdev:1099");

ConnectionProps.setProperty("DSC_TRANSPORT_PROTOCOL","EJB");

ConnectionProps.setProperty("DSC_SERVER_TYPE", "JBoss");

ConnectionProps.setProperty("DSC_CREDENTIAL_USERNAME", "administrator");

ConnectionProps.setProperty("DSC_CREDENTIAL_PASSWORD", "password");



As you can see, my server is not local, so i went ahead and added the jar file, but i'm still getting the same error. Any help would be greatly apopreciated!

Avatar

Former Community Member
just to add a little more info, the exception gets thrown at the point where i call;



List result = queryManager.taskList(filter);



which i'm assuming is where the connection is actually made to LC server.

Avatar

Former Community Member
whoops, i accidently imported jboss-client.jar file instead of jbossall-client.jar file :S<br /><br />But now i have another error;<br /><br />ALC-DSC-031-000: com.adobe.idp.dsc.net.DSCNamingException: Remote EJBObject lookup failed for ejb/Invocation provider<br /> at com.adobe.idp.dsc.provider.impl.ejb.EjbMessageDispatcher.initialise(EjbMessageDispatcher.java:97)<br /> at com.adobe.idp.dsc.provider.impl.ejb.EjbMessageDispatcher.doSend(EjbMessageDispatcher.java:130)<br /> at com.adobe.idp.dsc.provider.impl.base.AbstractMessageDispatcher.send(AbstractMessageDispatcher.java:57)<br /> at com.adobe.idp.dsc.clientsdk.ServiceClient.invoke(ServiceClient.java:208)<br /> at com.adobe.idp.taskmanager.dsc.client.TypedTaskManagerQueryService.taskList(TypedTaskManagerQueryService.java:271)<br /> at com.adobe.sample.taskmanager.RetrieveTaskInfo.main(RetrieveTaskInfo.java:71)<br />Caused by: javax.naming.CommunicationException [Root exception is java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is: <br /> java.net.ConnectException: Connection refused: connect]<br /> at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:707)<br /> at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:572)<br /> at javax.naming.InitialContext.lookup(Unknown Source)<br /> at com.adobe.idp.dsc.provider.impl.ejb.EjbMessageDispatcher.initialise(EjbMessageDispatcher.java:88)<br /> ... 5 more<br />Caused by: java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is: <br /> java.net.ConnectException: Connection refused: connect<br /> at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source)<br /> at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)<br /> at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source)<br /> at sun.rmi.server.UnicastRef.invoke(Unknown Source)<br /> at org.jnp.server.NamingServer_Stub.lookup(Unknown Source)<br /> at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:610)<br /> ... 8 more<br />Caused by: java.net.ConnectException: Connection refused: connect<br /> at java.net.PlainSocketImpl.socketConnect(Native Method)<br /> at java.net.PlainSocketImpl.doConnect(Unknown Source)<br /> at java.net.PlainSocketImpl.connectToAddress(Unknown Source)<br /> at java.net.PlainSocketImpl.connect(Unknown Source)<br /> at java.net.SocksSocketImpl.connect(Unknown Source)<br /> at java.net.Socket.connect(Unknown Source)<br /> at java.net.Socket.connect(Unknown Source)<br /> at java.net.Socket.<init>(Unknown Source)<br /> at java.net.Socket.<init>(Unknown Source)<br /> at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(Unknown Source)<br /> at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown Source)<br /> ... 14 more<br /><br />Is this due again to the connection properties?

Avatar

Level 1

Thanks for the useful information.