Skip to content

Commit

Permalink
feat(core): task API enhancement to include attachment/comments info (#…
Browse files Browse the repository at this point in the history
…4306)

* task API response include attachments and comments info
  * when `withCommentAttachmentInfo` is enabled 
  * additional queries if a attachment/comment  is present
  * count query is not affected 

related to #2404

---------

Signed-off-by: Kumar Pani, Suman <[email protected]>
  • Loading branch information
sumankumarpani authored Sep 16, 2024
1 parent f06cb96 commit ddf039c
Show file tree
Hide file tree
Showing 20 changed files with 407 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -657,5 +657,15 @@
<@lib.parameter name = "parentTaskId"
location = "query"
type = "string"
desc = "Restrict query to all tasks that are sub tasks of the given task. Takes a task id." />

<@lib.parameter name = "withCommentAttachmentInfo"
location = "query"
type = "boolean"
defaultValue = "false"
last = last
desc = "Restrict query to all tasks that are sub tasks of the given task. Takes a task id." />
desc = "Check if task has attachments and/or comments. Value may only be `true`, as
`false` is the default behavior.
Adding the filter will do additional attachment and comments queries to the database,
it might slow down the query in case of tables having high volume of data.
This param is not considered for count queries" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<#macro dto_macro docsUrl="">
<@lib.dto
extends = "TaskDto" >

<@lib.property
name = "attachment"
type = "boolean"
desc = "Specifies if an attachment exists for the task." />

<@lib.property
name = "comment"
type = "boolean"
last = true
desc = "Specifies if an comment exists for the task." />

</@lib.dto>
</#macro>
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@

<@lib.response
code = "200"
dto = "TaskDto"
dto = "TaskWithAttachmentAndCommentDto"
array = true
desc = "Request successful."
examples = ['"example-1": {
"summary": "Status 200 response",
"summary": "Status 200 response 1",
"description": "Response for GET `/task?assignee=anAssignee&delegationState=RESOLVED&maxPriority=50`",
"value": [
{
Expand Down Expand Up @@ -72,6 +72,43 @@
"taskState": "aTaskState"
}
]
}',
'"example-2": {
"summary": "Status 200 response 2",
"description": "Response for GET `/task?assignee=anAssignee&withCommentAttachmentInfo=true`",
"value": [
{
"id":"anId",
"name":"aName",
"assignee":"anAssignee",
"created":"2013-01-23T13:42:42.657+0200",
"due":"2013-01-23T13:49:42.323+0200",
"followUp:":"2013-01-23T13:44:42.987+0200",
"lastUpdated:":"2013-01-23T13:44:42.987+0200",
"delegationState":"RESOLVED",
"description":"aDescription",
"executionId":"anExecution",
"owner":"anOwner",
"parentTaskId":"aParentId",
"priority":42,
"processDefinitionId":"aProcDefId",
"processInstanceId":"aProcInstId",
"caseDefinitionId":"aCaseDefId",
"caseInstanceId":"aCaseInstId",
"caseExecutionId":"aCaseExecution",
"taskDefinitionKey":"aTaskDefinitionKey",
"suspended": false,
"formKey":"aFormKey",
"camundaFormRef":{
"key": "aCamundaFormKey",
"binding": "version",
"version": 2
},
"tenantId": "aTenantId",
"attachment":false,
"comment":false
}
]
}'] />

<@lib.response
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"description": "Logical query: assignee = \\"John Munda\\" AND (name = \\"Approve Invoice\\" OR priority = 5) AND (suspended = false OR taskDefinitionKey = \\"approveInvoice\\")",
"value": {
"assignee": "John Munda",
"withCommentAttachmentInfo": "true",
"orQueries": [
{
"name": "Approve Invoice",
Expand All @@ -86,7 +87,7 @@

<@lib.response
code = "200"
dto = "TaskDto"
dto = "TaskWithAttachmentAndCommentDto"
array = true
desc = "Request successful."
examples = ['"example-1": {
Expand Down Expand Up @@ -150,7 +151,9 @@
"suspended": false,
"formKey": "embedded:app:develop/invoice-forms/approve-invoice.html",
"tenantId": null,
"taskState": "aTaskState"
"taskState": "aTaskState",
"attachment":false,
"comment":false
}
]
}'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

<@lib.response
code = "200"
dto = "TaskDto"
dto = "TaskWithAttachmentAndCommentDto"
desc = "Request successful."
examples = ['"example-1": {
"summary": "GET /task/anId Response",
Expand Down Expand Up @@ -56,6 +56,38 @@
"tenantId":"aTenantId",
"taskState": "aTaskState"
}
}',
'"example-2": {
"summary": "GET /task/anId?withCommentAttachmentInfo=true Response",
"value": [
{
"id": "349fffa8-6571-11e7-9a44-d6940f5ef88d",
"name": "Approve Invoice",
"assignee": "John Munda",
"created": "2017-07-10T15:10:54.670+0200",
"due": "2017-07-17T15:10:54.670+0200",
"followUp": null,
"lastUpdated": "2017-07-17T15:10:54.670+0200",
"delegationState": null,
"description": "Approve the invoice (or not).",
"executionId": "349f8a5c-6571-11e7-9a44-d6940f5ef88d",
"owner": null,
"parentTaskId": null,
"priority": 50,
"processDefinitionId": "invoice:1:2c8d8057-6571-11e7-9a44-d6940f5ef88d",
"processInstanceId": "349f8a5c-6571-11e7-9a44-d6940f5ef88d",
"taskDefinitionKey": "approveInvoice",
"caseExecutionId": null,
"caseInstanceId": null,
"caseDefinitionId": null,
"suspended": false,
"formKey": "embedded:app:develop/invoice-forms/approve-invoice.html",
"tenantId": null,
"taskState": "aTaskState",
"attachment":false,
"comment":false
}
]
}'] />

<@lib.response
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public interface TaskRestService {
public static final String PATH = "/task";

@Path("/{id}")
TaskResource getTask(@PathParam("id") String id);
TaskResource getTask(@PathParam("id") String id, @QueryParam("withCommentAttachmentInfo") boolean withCommentAttachmentInfo);

@GET
@Produces({MediaType.APPLICATION_JSON, Hal.APPLICATION_HAL_JSON})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.camunda.bpm.engine.BadUserRequestException;
import org.camunda.bpm.engine.form.CamundaFormRef;
import org.camunda.bpm.engine.rest.dto.converter.DelegationStateConverter;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.task.DelegationState;
import org.camunda.bpm.engine.task.Task;

Expand Down Expand Up @@ -54,6 +55,44 @@ public class TaskDto {
*/
private String taskState;

public TaskDto() {
}

public TaskDto(Task task) {
this.id = task.getId();
this.name = task.getName();
this.assignee = task.getAssignee();
this.created = task.getCreateTime();
this.lastUpdated = task.getLastUpdated();
this.due = task.getDueDate();
this.followUp = task.getFollowUpDate();

if (task.getDelegationState() != null) {
this.delegationState = task.getDelegationState().toString();
}

this.description = task.getDescription();
this.executionId = task.getExecutionId();
this.owner = task.getOwner();
this.parentTaskId = task.getParentTaskId();
this.priority = task.getPriority();
this.processDefinitionId = task.getProcessDefinitionId();
this.processInstanceId = task.getProcessInstanceId();
this.taskDefinitionKey = task.getTaskDefinitionKey();
this.caseDefinitionId = task.getCaseDefinitionId();
this.caseExecutionId = task.getCaseExecutionId();
this.caseInstanceId = task.getCaseInstanceId();
this.suspended = task.isSuspended();
this.tenantId = task.getTenantId();
this.taskState = task.getTaskState();
try {
this.formKey = task.getFormKey();
this.camundaFormRef = task.getCamundaFormRef();
}
catch (BadUserRequestException e) {
// ignore (initializeFormKeys was not called)
}
}
public String getId() {
return id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ public class TaskQueryDto extends AbstractQueryDto<TaskQuery> {

private List<TaskQueryDto> orQueries;

private Boolean withCommentAttachmentInfo;

public TaskQueryDto() {

}
Expand Down Expand Up @@ -708,6 +710,11 @@ public void setVariableValuesIgnoreCase(Boolean variableValuesCaseInsensitive) {
this.variableValuesIgnoreCase = variableValuesCaseInsensitive;
}

@CamundaQueryParam(value = "withCommentAttachmentInfo", converter = BooleanConverter.class)
public void setWithCommentAttachmentInfo(Boolean withCommentAttachmentInfo) {
this.withCommentAttachmentInfo = withCommentAttachmentInfo;
}

@Override
protected boolean isValidSortByValue(String value) {
return VALID_SORT_BY_VALUES.contains(value);
Expand Down Expand Up @@ -1078,6 +1085,8 @@ public Boolean isVariableValuesIgnoreCase() {
return variableValuesIgnoreCase;
}

public Boolean getWithCommentAttachmentInfo() { return withCommentAttachmentInfo;}

@Override
protected void applyFilters(TaskQuery query) {
if (orQueries != null) {
Expand Down Expand Up @@ -1442,6 +1451,9 @@ protected void applyFilters(TaskQuery query) {
}
}
}
if (withCommentAttachmentInfo != null && withCommentAttachmentInfo) {
query.withCommentAttachmentInfo();
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.camunda.bpm.engine.rest.dto.task;

import org.camunda.bpm.engine.task.Task;

public class TaskWithAttachmentAndCommentDto extends TaskDto {

private boolean hasAttachment;
private boolean hasComment;

public TaskWithAttachmentAndCommentDto() {
}

public TaskWithAttachmentAndCommentDto(Task task) {
super(task);
}
public boolean getAttachment() {
return hasAttachment;
}
public void setAttachment(boolean hasAttachment) {
this.hasAttachment = hasAttachment;
}

public boolean getComment() {
return hasComment;
}

public void setComment(boolean hasComment) {
this.hasComment = hasComment;
}

public static TaskDto fromEntity(Task task) {
TaskWithAttachmentAndCommentDto result = new TaskWithAttachmentAndCommentDto(task);

result.hasAttachment = task.hasAttachment();
result.hasComment = task.hasComment();
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
Expand All @@ -32,6 +33,7 @@
import org.camunda.bpm.engine.rest.dto.CountResultDto;
import org.camunda.bpm.engine.rest.dto.task.TaskDto;
import org.camunda.bpm.engine.rest.dto.task.TaskQueryDto;
import org.camunda.bpm.engine.rest.dto.task.TaskWithAttachmentAndCommentDto;
import org.camunda.bpm.engine.rest.exception.InvalidRequestException;
import org.camunda.bpm.engine.rest.hal.Hal;
import org.camunda.bpm.engine.rest.hal.task.HalTaskList;
Expand Down Expand Up @@ -66,6 +68,7 @@ else if (Hal.APPLICATION_HAL_JSON_TYPE.equals(variant.getMediaType())) {
}

public List<TaskDto> getJsonTasks(UriInfo uriInfo, Integer firstResult, Integer maxResults) {
// get list of tasks
TaskQueryDto queryDto = new TaskQueryDto(getObjectMapper(), uriInfo.getQueryParameters());
return queryTasks(queryDto, firstResult, maxResults);
}
Expand Down Expand Up @@ -95,11 +98,12 @@ public List<TaskDto> queryTasks(TaskQueryDto queryDto, Integer firstResult,
List<Task> matchingTasks = executeTaskQuery(firstResult, maxResults, query);

List<TaskDto> tasks = new ArrayList<TaskDto>();
for (Task task : matchingTasks) {
TaskDto returnTask = TaskDto.fromEntity(task);
tasks.add(returnTask);
if (Boolean.TRUE.equals(queryDto.getWithCommentAttachmentInfo())) {
tasks = matchingTasks.stream().map(TaskWithAttachmentAndCommentDto::fromEntity).collect(Collectors.toList());
}
else {
tasks = matchingTasks.stream().map(TaskDto::fromEntity).collect(Collectors.toList());
}

return tasks;
}

Expand Down Expand Up @@ -130,8 +134,8 @@ public CountResultDto queryTasksCount(TaskQueryDto queryDto) {
}

@Override
public TaskResource getTask(String id) {
return new TaskResourceImpl(getProcessEngine(), id, relativeRootResourcePath, getObjectMapper());
public TaskResource getTask(String id, boolean withCommentAttachmentInfo) {
return new TaskResourceImpl(getProcessEngine(), id, relativeRootResourcePath, getObjectMapper(), withCommentAttachmentInfo);
}

@Override
Expand Down
Loading

0 comments on commit ddf039c

Please sign in to comment.