cancel
Showing results for 
Search instead for 
Did you mean: 

service/runtime/tasks - action claim

kamil
Champ in-the-making
Champ in-the-making
Hi all,

I have a problem with the method "service/runtime/tasks/task_id ({"action":"claim"})", the documentation says that "@param userId user that claims the task. When userId is null the task is unclaimed, * assigned to no one." but it dosen't work (version 5.13) I get an error "An assignee is required when claiming a task". Can someone help me what could be wrong?

Regards,
Kamil.
7 REPLIES 7

kamil
Champ in-the-making
Champ in-the-making
I use activiti-rest and {"action":"claim"} is passed in the body .

frederikherema1
Star Contributor
Star Contributor
You're referring to the Java API docs. The rest-api docs state:

Claims the task by the given assignee. The assignee is required.

This is a bit inconsistent with the Java-API, you're right. ANyway, if you want to set assignee to null, use PUT runtime/tasks/123 with body {"assignee":"null"} instead.

nscarg
Champ in-the-making
Champ in-the-making
I'm having problem with REST command "service/runtime/tasks?processDefinitionKey=myDefinitionId" (ID_ from procdef Table).  It looks like if it ignores the URL parameter processDefinitionKey and always returns all the tasks without any filtering. The same problem with processDefinitionKey, processDefinitionName and processDefinitionNameLike. I works properly with processInstanceId.
I'd appreciate any help. Thanks

trademak
Star Contributor
Star Contributor
Can you create a unit test showing your issue? That would make it easy for us to reproduce it. In any case please create a JIRA issue so we can look into it.

Best regards,

cavdar
Champ in-the-making
Champ in-the-making
Claim and unclaim an User-Task

I have created Unit-Tests for REST- and API-variant. In the API-variant it is possible to claim and unclaim an User-Task, but not via REST!
Here the API-Variant:
<code>
public class LocalActivitProcessEngineTest
{
  protected static Map<String, Object> taskParams = new HashMap<String, Object>();
  protected static ProcessEngine       processEngine;
  protected static TaskService         taskService;
  protected static RuntimeService      runtimeService;
                                      
  @BeforeClass
  public static void setUpClass()
  {
    processEngine = createProcessEngine();
    deployProcessDefinition( processEngine );
    taskService = processEngine.getTaskService();
    Assert.assertNotNull( taskService );
    runtimeService = processEngine.getRuntimeService();
    Assert.assertNotNull( runtimeService );
  }
 
  @AfterClass
  public static void tearDownClass()
  {
    List<Task> cteTasksList = taskService.createTaskQuery().taskCandidateGroup( UserTaskThread.CTE_TESTER_GROUP ).list();
    taskParams.put( "exportsOK", "true" );
    while( !cteTasksList.isEmpty() )
    {
      Task task = cteTasksList.get( 0 );
      String taskId = task.getId();
      taskService.claim( taskId, "cavdark" );
      taskService.complete( taskId, taskParams );
      cteTasksList = taskService.createTaskQuery().taskCandidateGroup( UserTaskThread.CTE_TESTER_GROUP ).list();
    }
  }
 
  @Test
  public void testClaimUnClaim()
  {
    RuntimeService runtimeService = processEngine.getRuntimeService();
    Assert.assertNotNull( runtimeService );
    ProcessInstance processInstanceByKey = runtimeService.startProcessInstanceByKey( ActivitiTestsBase.PROCESS_NAME );
    Assert.assertNotNull( processInstanceByKey );
   
    Assert.assertNotNull( taskService );
    List<Task> cteTasksList = taskService.createTaskQuery().taskCandidateGroup( UserTaskThread.CTE_TESTER_GROUP ).list();
    Assert.assertNotNull( cteTasksList );
    while( !cteTasksList.isEmpty() )
    {
      Task task = cteTasksList.get( 0 );
      String taskId = task.getId();
      System.out.println( "UserTask: " + taskId );
      taskService.claim( taskId, "cavdark" );
      System.out.println( "\t" + taskId + " wurde von cavdark abgeholt" );
      try
      {
        taskService.claim( taskId, "schneidm" );
        Assert.fail( "UserTask {" + taskId + "} sollte für andere Miglieder der Gruppe nicht mehr greifbar sein!" );
      }
      catch (ActivitiTaskAlreadyClaimedException ex)
      {
        // OK!
      }
      catch (Exception ex)
      {
        Assert.fail( ex.getMessage() );
      }
      taskService.unclaim( taskId );
      System.out.println( "\t" + taskId + " wurde wieder zurückgegeben" );

      taskService.claim( taskId, "schneidm" );
      System.out.println( "\t" + taskId + " wurde von schneidm abgeholt" );
     
      taskParams.put( "signalType", "signalType1" );
      taskService.complete( taskId, taskParams );
      System.out.println( "\t" + taskId + " abgeschlossen" );
    }
  }

  private static void deployProcessDefinition( ProcessEngine processEngine )
  {
    RepositoryService repositoryService = processEngine.getRepositoryService();
    Assert.assertNotNull( repositoryService );
    List<Deployment> deploymentList = repositoryService.createDeploymentQuery().processDefinitionKey( ActivitiTestsBase.PROCESS_NAME ).list();
    while( deploymentList.size() > 0 )
    {
      Deployment deployment = deploymentList.get( 0 );
      repositoryService.deleteDeployment( deployment.getId() );
      deploymentList = repositoryService.createDeploymentQuery().processDefinitionKey( ActivitiTestsBase.PROCESS_NAME ).list();
    }
    DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
    Assert.assertNotNull( deploymentBuilder );
    deploymentBuilder = deploymentBuilder.addClasspathResource( ActivitiTestsBase.DEPLOYMENT_NAME );
    deploymentBuilder.deploy();
  }
 
  private static ProcessEngine createProcessEngine()
  {
    ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
    processEngineConfiguration = processEngineConfiguration.setDatabaseSchemaUpdate( ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE );
    processEngineConfiguration = processEngineConfiguration.setJdbcUrl( "jdbcSmiley Surprisedracle:thin:@localhost:1521:XE" );
    processEngineConfiguration = processEngineConfiguration.setJdbcUsername( "ACTIVITI" );
    processEngineConfiguration = processEngineConfiguration.setJdbcPassword( "activiti" );
    processEngineConfiguration = processEngineConfiguration.setAsyncExecutorEnabled( true );
    processEngineConfiguration = processEngineConfiguration.setAsyncExecutorActivate( false );
    Assert.assertNotNull( processEngineConfiguration );
   
    ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
    Assert.assertNotNull( processEngine );
    return processEngine;
  }
}
</code>

Here the REST-Variant:
<code>
public class RestIntegrationTestBase
{
  protected final static Logger               LOGGER            = Logger.getLogger( RestIntegrationTestBase.class );
  protected static final GreenMail            smtpServer        = new GreenMail( ServerSetupTest.SMTP );
  protected static final EnvironmentConfig    environmentConfig = new EnvironmentConfig();
  protected static RESTServiceConfig          restServiceActiviti;
  protected static String                     ACTIVITI_REST_SERVICE_URI;
  protected static CteActivitiRESTInvoker     restServiceInvoker;
  protected static CteActivitiServiceRestImpl cteActivitiServiceREST;
                                             
  protected Integer                           processInstanceID;
                                             
  @BeforeClass
  public static void createJUNITDeployment()
  {
    try
    {
      environmentConfig.loadEnvironmentConfig( "ENE" );
      restServiceActiviti = environmentConfig.getRestServiceActiviti();
      ACTIVITI_REST_SERVICE_URI = restServiceActiviti.getServiceURL() + CteActivitiRESTInvoker.ACTIVITI_REST_SERVICE_PATH + "/";
      restServiceInvoker = new CteActivitiRESTInvoker( restServiceActiviti.getServiceURL(), restServiceActiviti.getServiceUser(), restServiceActiviti.getServicePassword() );
      cteActivitiServiceREST = new CteActivitiServiceRestImpl( restServiceInvoker );
      String deploymentPath = RestIntegrationTestBase.class.getResource( "/" + ActivitiTestsBase.DEPLOYMENT_NAME ).getPath();
      CteActivitiDeployment cteActivitiDeployment = cteActivitiServiceREST.getDeploymentForName( new File( deploymentPath ).getName() );
      if( cteActivitiDeployment == null )
      {
        String deploymentID = cteActivitiServiceREST.uploadDeployment( deploymentPath );
        Assert.assertNotNull( deploymentID );
      }
      smtpServer.start();
    }
    catch (Exception ex)
    {
      Assert.fail( ex.getMessage());
    }
  }
 
  @AfterClass
  public static void cleanUpJUNITDeployment()
  {
    try
    {
      smtpServer.stop();
      cteActivitiServiceREST.deleteDeployment( ActivitiTestsBase.DEPLOYMENT_NAME );
      CteActivitiDeployment cteActivitiDeploymentForName = cteActivitiServiceREST.getDeploymentForName( ActivitiTestsBase.DEPLOYMENT_NAME );
      Assert.assertNull( "Unser Deployment konnte wurde nicht gelöscht werden!", cteActivitiDeploymentForName );
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }
 
  @Before
  public void setUp()
  {
  }
 
  @After
  public void tearDown()
  {
    try
    {
      //smtpServer.stop();
      cleanUpProcess();
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
 
  protected void cleanUpProcess()
  {
    try
    {
      if( processInstanceID != null )
      {
        cteActivitiServiceREST.deleteProcessInstance( processInstanceID );
      }
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
 
  protected void ensureProcessStarted() throws Exception
  {
    // eventuelle Liechen entfernen…
    List<CteActivitiProcess> processInstancesByDefinitionKey = cteActivitiServiceREST.getProcessInstancesByDefinitionKey(ActivitiTestsBase.PROCESS_NAME);
    for( CteActivitiProcess processInstance : processInstancesByDefinitionKey )
    {
      cteActivitiServiceREST.deleteProcessInstance( processInstance.getId() );
    }
   
    CteActivitiProcess cteActivitiProcessInstance = cteActivitiServiceREST.startProcess( ActivitiTestsBase.PROCESS_NAME, null );
    Assert.assertNotNull( cteActivitiProcessInstance );
    processInstanceID = Integer.valueOf( cteActivitiProcessInstance.getId() );
    CteActivitiProcess cteActivitiProcessInstance2 = cteActivitiServiceREST.getProcessInstanceByID( processInstanceID );
    Assert.assertNotNull( cteActivitiProcessInstance2 );
    Assert.assertEquals( processInstanceID.intValue(), cteActivitiProcessInstance2.getId().intValue() );
  }

</code>
This JUNIT-Test breaks:
<code>
public class CteActivitiRestServiceIntegrationTest extends RestIntegrationTestBase
{
  @Test
  public void testClaimUnclaimTask() throws Exception
  {
    ensureProcessStarted();
    CteActivitiTask cteActivitiTask = cteActivitiServiceREST.findNextTaskForGroup( UserTaskThread.CTE_TESTER_GROUP );
    Assert.assertNotNull( cteActivitiTask );
    logUserTask( cteActivitiTask );
    RESTServiceConfig restServiceActiviti = environmentConfig.getRestServiceActiviti();
   
    cteActivitiServiceREST.claimTask( cteActivitiTask, restServiceActiviti.getServiceUser());
    /** Response:
     *    reasonPhrase "OK" (id=79)
     *    responseBody "" (id=80)
     *    statusCode 200
     */

    cteActivitiServiceREST.unclaimTask( cteActivitiTask);
    /** Reponse:
     *    reasonPhrase "OK" (id=88)
     *    responseBody "{"id":"857708","url":"http://localhost:9999/activiti-rest/service/runtime/tasks/857708','owner':null,'assignee':'null','de... #0","description":null,"createTime":"2016-03-15T16:08:04.437+01:00","dueDate":null,"priority":50,"suspended":false,"taskDefinitionKey":"UserTask0","tenantId":"","category":null,"formKey":null,"parentTaskId":null,"parentTaskUrl":null,"executionId":"857702","executionUrl":"http://localhost:9999/activiti-rest/service/runtime/executions/857702','processInstanceId':'857702',...":[]}" (id=89)
     *    statusCode 200
     */         

    cteActivitiServiceREST.claimTask( cteActivitiTask, restServiceActiviti.getServiceUser());
    /** Reponse:
     *    reasonPhrase "Conflict" (id=94)
     *    responseBody "{"message":"Task was already claimed","exception":"Task '857708' is already claimed by someone else."}" (id=95)
     *    statusCode 409
     */   
  }
</code>

<code>
public class CteActivitiServiceRestImpl implements CteActivitiService
{
  private static ObjectMapper          objectMapper = new ObjectMapper();
  private final CteActivitiRESTInvoker restServiceInvoker;

  @Override
  public void claimTask( CteActivitiTask cteActivitiTask, String userID ) throws Exception
  {
    String path = RestUrls.createRelativeResourceUrl( RestUrls.URL_TASK_COLLECTION ) + "/" + cteActivitiTask.getId();
    restServiceInvoker.init( path, 2000 );
   
    ObjectNode requestNode = objectMapper.createObjectNode();
    requestNode.put( "action", "claim" );
    requestNode.put( "assignee", userID );
   
    String stringEntity = requestNode.toString();
    CteActivitiRESTInvokerResponse cteActivitiRESTInvokerResponse = restServiceInvoker.invokePost( stringEntity );
    // stelle sicher, dass der Status-Code der Response 200 ist
    cteActivitiRESTInvokerResponse.expectStatusOK();
  }
 
  @Override
  public void unclaimTask( CteActivitiTask cteActivitiTask ) throws Exception
  {
    String path = RestUrls.createRelativeResourceUrl( RestUrls.URL_TASK_COLLECTION ) + "/" + cteActivitiTask.getId();
    restServiceInvoker.init( path, 2000 );
   
    ObjectNode requestNode = objectMapper.createObjectNode();
    //requestNode.put( "assignee", "cte-tester");
    requestNode.put( "assignee", "null");
   
    String stringEntity = requestNode.toString();
    CteActivitiRESTInvokerResponse cteActivitiRESTInvokerResponse = restServiceInvoker.invokePut( stringEntity );
    // stelle sicher, dass der Status-Code der Response 200 ist
    cteActivitiRESTInvokerResponse.expectStatusOK();
  }
</code>


<code>
public class CteActivitiRESTInvoker implements Closeable
{
  public static final String        ACTIVITI_REST_SERVICE_PATH = "/activiti-rest/service";

  public CteActivitiRESTInvokerResponse invokePut( String stringEntity )
  {
    HttpPut putMethod = new HttpPut( buildURI() );
    try
    {
      putMethod.setEntity( new StringEntity( stringEntity, "UTF-8" ) );
    }
    catch (UnsupportedEncodingException e)
    {
      throw new CteActivitiServiceException( "Encoding UTF-8 wird nicht unterstützt", e );
    }
    CteActivitiRESTInvokerResponse response = invokeInternal( putMethod, true );
    this.queryParameters.clear();
    return response;
  }
 
  public CteActivitiRESTInvokerResponse invokePost( String stringEntity )
  {
    HttpPost postMethod = new HttpPost( buildURI() );
    try
    {
      postMethod.setEntity( new StringEntity( stringEntity, "UTF-8" ) );
    }
    catch (UnsupportedEncodingException e)
    {
      throw new CteActivitiServiceException( "Encoding UTF-8 wird nicht unterstützt", e );
    }
    CteActivitiRESTInvokerResponse response = invokeInternal( postMethod, true );
    this.queryParameters.clear();
    return response;
  }
  …
}
</code>


jbarrez
Star Contributor
Star Contributor
I added a test to check what you're saying: https://github.com/Activiti/Activiti/commit/f6d58fb0dabd8246c52a73fdcb02228e1469d9bf, which runs green.

I think you need to add the 'claim' parameter when unclaiming the task with the null assignee.

cavdar
Champ in-the-making
Champ in-the-making
Thank you very much! Your test works; I will change my tests and check it.
Getting started

Tags


Find what you came for

We want to make your experience in Hyland Connect as valuable as possible, so we put together some helpful links.