Skip to content

Commit 82eff1a

Browse files
Add batch response to batch migrate endpoints
1 parent f039bdd commit 82eff1a

8 files changed

Lines changed: 363 additions & 7 deletions

File tree

modules/flowable-cmmn-rest/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
<groupId>org.flowable</groupId>
3232
<artifactId>flowable-common-rest</artifactId>
3333
</dependency>
34+
<dependency>
35+
<groupId>org.flowable</groupId>
36+
<artifactId>flowable-batch-service</artifactId>
37+
</dependency>
3438

3539
<dependency>
3640
<groupId>commons-io</groupId>

modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/CmmnRestResponseFactory.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.stream.Collectors;
2222

2323
import org.apache.commons.lang3.StringUtils;
24+
import org.flowable.batch.api.Batch;
2425
import org.flowable.cmmn.api.history.HistoricCaseInstance;
2526
import org.flowable.cmmn.api.history.HistoricMilestoneInstance;
2627
import org.flowable.cmmn.api.history.HistoricPlanItemInstance;
@@ -41,6 +42,7 @@
4142
import org.flowable.cmmn.rest.service.api.history.variable.HistoricVariableInstanceResponse;
4243
import org.flowable.cmmn.rest.service.api.management.HistoryJobResponse;
4344
import org.flowable.cmmn.rest.service.api.management.JobResponse;
45+
import org.flowable.cmmn.rest.service.api.repository.BatchResponse;
4446
import org.flowable.cmmn.rest.service.api.repository.CaseDefinitionResponse;
4547
import org.flowable.cmmn.rest.service.api.repository.CmmnDeploymentResponse;
4648
import org.flowable.cmmn.rest.service.api.repository.DecisionResponse;
@@ -631,7 +633,25 @@ public VariableInstanceResponse createVariableInstanceResponse(VariableInstance
631633
urlBuilder));
632634
return result;
633635
}
634-
636+
637+
public BatchResponse createBatchResponse(Batch batch) {
638+
return createBatchResponse(batch, createUrlBuilder());
639+
}
640+
641+
public BatchResponse createBatchResponse(Batch batch, RestUrlBuilder urlBuilder) {
642+
BatchResponse response = new BatchResponse();
643+
response.setId(batch.getId());
644+
response.setBatchType(batch.getBatchType());
645+
response.setSearchKey(batch.getBatchSearchKey());
646+
response.setSearchKey2(batch.getBatchSearchKey2());
647+
response.setCreateTime(batch.getCreateTime());
648+
response.setCompleteTime(batch.getCompleteTime());
649+
response.setStatus(batch.getStatus());
650+
response.setTenantId(batch.getTenantId());
651+
response.setUrl(urlBuilder.buildUrl(CmmnRestUrls.URL_BATCH, batch.getId()));
652+
return response;
653+
}
654+
635655
public List<EventSubscriptionResponse> createEventSubscriptionResponseList(List<EventSubscription> eventSubscriptions) {
636656
RestUrlBuilder urlBuilder = createUrlBuilder();
637657
List<EventSubscriptionResponse> responseList = new ArrayList<>(eventSubscriptions.size());

modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/CmmnRestUrls.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public final class CmmnRestUrls {
6565
public static final String SEGMENT_TIMER_JOBS = "timer-jobs";
6666
public static final String SEGMENT_SUSPENDED_JOBS = "suspended-jobs";
6767
public static final String SEGMENT_DEADLETTER_JOBS = "deadletter-jobs";
68+
public static final String SEGMENT_BATCHES = "batches";
6869
public static final String SEGMENT_HISTORY_JOBS = "history-jobs";
6970
public static final String SEGMENT_JOB_EXCEPTION_STACKTRACE = "exception-stacktrace";
7071
public static final String SEGMENT_USERS = "users";
@@ -411,6 +412,11 @@ public final class CmmnRestUrls {
411412
*/
412413
public static final String[] URL_DEADLETTER_JOB_COLLECTION = { SEGMENT_MANAGEMENT_RESOURCES, SEGMENT_DEADLETTER_JOBS };
413414

415+
/**
416+
* URL template for a single batch: <i>cmmn-management/batches/{0:batchId}</i>
417+
*/
418+
public static final String[] URL_BATCH = { SEGMENT_MANAGEMENT_RESOURCES, SEGMENT_BATCHES, "{0}" };
419+
414420
/**
415421
* URL template for a single event subscription: <i>cmmn-runtime/event-subscriptions/{0:eventSubscriptionId}</i>
416422
*/
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/* Licensed under the Apache License, Version 2.0 (the "License");
2+
* you may not use this file except in compliance with the License.
3+
* You may obtain a copy of the License at
4+
*
5+
* http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
* limitations under the License.
12+
*/
13+
14+
package org.flowable.cmmn.rest.service.api.repository;
15+
16+
import java.util.Date;
17+
18+
import org.flowable.common.rest.util.DateToStringSerializer;
19+
20+
import tools.jackson.databind.annotation.JsonSerialize;
21+
22+
import io.swagger.annotations.ApiModelProperty;
23+
24+
public class BatchResponse {
25+
26+
protected String id;
27+
protected String url;
28+
protected String batchType;
29+
protected String searchKey;
30+
protected String searchKey2;
31+
@JsonSerialize(using = DateToStringSerializer.class, as = Date.class)
32+
protected Date createTime;
33+
@JsonSerialize(using = DateToStringSerializer.class, as = Date.class)
34+
protected Date completeTime;
35+
protected String status;
36+
protected String tenantId;
37+
38+
@ApiModelProperty(example = "8")
39+
public String getId() {
40+
return id;
41+
}
42+
43+
public void setId(String id) {
44+
this.id = id;
45+
}
46+
47+
@ApiModelProperty(example = "http://localhost:8182/management/batches/8")
48+
public String getUrl() {
49+
return url;
50+
}
51+
52+
public void setUrl(String url) {
53+
this.url = url;
54+
}
55+
56+
@ApiModelProperty(example = "processMigration")
57+
public String getBatchType() {
58+
return batchType;
59+
}
60+
61+
public void setBatchType(String batchType) {
62+
this.batchType = batchType;
63+
}
64+
65+
@ApiModelProperty(example = "1:22:MP")
66+
public String getSearchKey() {
67+
return searchKey;
68+
}
69+
70+
public void setSearchKey(String searchKey) {
71+
this.searchKey = searchKey;
72+
}
73+
74+
@ApiModelProperty(example = "1:24:MP")
75+
public String getSearchKey2() {
76+
return searchKey2;
77+
}
78+
79+
public void setSearchKey2(String searchKey2) {
80+
this.searchKey2 = searchKey2;
81+
}
82+
83+
@ApiModelProperty(example = "2020-06-03T22:05:05.474+0000")
84+
public Date getCreateTime() {
85+
return createTime;
86+
}
87+
88+
public void setCreateTime(Date createTime) {
89+
this.createTime = createTime;
90+
}
91+
92+
@ApiModelProperty(example = "2020-06-03T22:05:05.474+0000")
93+
public Date getCompleteTime() {
94+
return completeTime;
95+
}
96+
97+
public void setCompleteTime(Date completeTime) {
98+
this.completeTime = completeTime;
99+
}
100+
101+
@ApiModelProperty(example = "completed")
102+
public String getStatus() {
103+
return status;
104+
}
105+
106+
public void setStatus(String status) {
107+
this.status = status;
108+
}
109+
110+
public void setTenantId(String tenantId) {
111+
this.tenantId = tenantId;
112+
}
113+
114+
@ApiModelProperty(example = "null")
115+
public String getTenantId() {
116+
return tenantId;
117+
}
118+
}

modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/repository/CaseDefinitionResource.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package org.flowable.cmmn.rest.service.api.repository;
1515

1616
import org.apache.commons.lang3.StringUtils;
17+
import org.flowable.batch.api.Batch;
1718
import org.flowable.cmmn.api.CmmnMigrationService;
1819
import org.flowable.cmmn.api.migration.CaseInstanceMigrationDocument;
1920
import org.flowable.cmmn.api.migration.HistoricCaseInstanceMigrationDocument;
@@ -179,7 +180,7 @@ public void migrateHistoricInstancesOfCaseDefinition(@ApiParam(name = "caseDefin
179180
@ApiResponse(code = 404, message = "Indicates the requested case definition was not found.")
180181
})
181182
@PostMapping(value = "/cmmn-repository/case-definitions/{caseDefinitionId}/batch-migrate", produces = "application/json")
182-
public void batchMigrateInstancesOfCaseDefinition(@ApiParam(name = "caseDefinitionId") @PathVariable String caseDefinitionId,
183+
public BatchResponse batchMigrateInstancesOfCaseDefinition(@ApiParam(name = "caseDefinitionId") @PathVariable String caseDefinitionId,
183184
@RequestBody String migrationDocumentJson) {
184185

185186
CaseDefinition caseDefinition = getCaseDefinitionFromRequestWithoutAccessCheck(caseDefinitionId);
@@ -189,7 +190,8 @@ public void batchMigrateInstancesOfCaseDefinition(@ApiParam(name = "caseDefiniti
189190
}
190191

191192
CaseInstanceMigrationDocument migrationDocument = CaseInstanceMigrationDocumentConverter.convertFromJson(migrationDocumentJson);
192-
cmmnMigrationService.batchMigrateCaseInstancesOfCaseDefinition(caseDefinitionId, migrationDocument);
193+
Batch batch = cmmnMigrationService.batchMigrateCaseInstancesOfCaseDefinition(caseDefinitionId, migrationDocument);
194+
return restResponseFactory.createBatchResponse(batch);
193195
}
194196

195197
@ApiOperation(value = "Batch migrate all historic instances of case definition", tags = { "Case Definitions" }, notes = "")
@@ -198,7 +200,7 @@ public void batchMigrateInstancesOfCaseDefinition(@ApiParam(name = "caseDefiniti
198200
@ApiResponse(code = 404, message = "Indicates the requested case definition was not found.")
199201
})
200202
@PostMapping(value = "/cmmn-repository/case-definitions/{caseDefinitionId}/batch-migrate-historic-instances", produces = "application/json")
201-
public void batchMigrateHistoricInstancesOfCaseDefinition(@ApiParam(name = "caseDefinitionId") @PathVariable String caseDefinitionId,
203+
public BatchResponse batchMigrateHistoricInstancesOfCaseDefinition(@ApiParam(name = "caseDefinitionId") @PathVariable String caseDefinitionId,
202204
@RequestBody String migrationDocumentJson) {
203205

204206
CaseDefinition caseDefinition = getCaseDefinitionFromRequestWithoutAccessCheck(caseDefinitionId);
@@ -208,7 +210,8 @@ public void batchMigrateHistoricInstancesOfCaseDefinition(@ApiParam(name = "case
208210
}
209211

210212
HistoricCaseInstanceMigrationDocument migrationDocument = HistoricCaseInstanceMigrationDocumentConverter.convertFromJson(migrationDocumentJson);
211-
cmmnMigrationService.batchMigrateHistoricCaseInstancesOfCaseDefinition(caseDefinitionId, migrationDocument);
213+
Batch batch = cmmnMigrationService.batchMigrateHistoricCaseInstancesOfCaseDefinition(caseDefinitionId, migrationDocument);
214+
return restResponseFactory.createBatchResponse(batch);
212215
}
213216

214217
protected FormInfo getStartForm(FormRepositoryService formRepositoryService, CaseDefinition caseDefinition) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/* Licensed under the Apache License, Version 2.0 (the "License");
2+
* you may not use this file except in compliance with the License.
3+
* You may obtain a copy of the License at
4+
*
5+
* http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
* limitations under the License.
12+
*/
13+
package org.flowable.cmmn.rest.service.api.repository;
14+
15+
import static org.assertj.core.api.Assertions.assertThat;
16+
17+
import org.apache.http.HttpStatus;
18+
import org.apache.http.client.methods.CloseableHttpResponse;
19+
import org.apache.http.client.methods.HttpPost;
20+
import org.apache.http.entity.StringEntity;
21+
import org.flowable.batch.api.Batch;
22+
import org.flowable.cmmn.api.repository.CaseDefinition;
23+
import org.flowable.cmmn.api.repository.CmmnDeployment;
24+
import org.flowable.cmmn.rest.service.BaseSpringRestTestCase;
25+
import org.flowable.cmmn.rest.service.api.CmmnRestUrls;
26+
import org.flowable.job.api.Job;
27+
import org.junit.jupiter.api.AfterEach;
28+
import org.junit.jupiter.api.Test;
29+
30+
import tools.jackson.databind.JsonNode;
31+
import tools.jackson.databind.node.ObjectNode;
32+
33+
public class CaseDefinitionBatchMigrateResourceTest extends BaseSpringRestTestCase {
34+
35+
@AfterEach
36+
public void tearDown() {
37+
for (Job job : managementService.createJobQuery().list()) {
38+
managementService.deleteJob(job.getId());
39+
}
40+
for (Job job : managementService.createTimerJobQuery().list()) {
41+
managementService.deleteTimerJob(job.getId());
42+
}
43+
for (Batch batch : managementService.createBatchQuery().list()) {
44+
managementService.deleteBatch(batch.getId());
45+
}
46+
for (CmmnDeployment deployment : repositoryService.createDeploymentQuery().list()) {
47+
repositoryService.deleteDeployment(deployment.getId(), true);
48+
}
49+
}
50+
51+
@Test
52+
public void testBatchMigrateReturnsBatchResponse() throws Exception {
53+
CaseDefinition v1 = deployCaseDefinition("v1", "org/flowable/cmmn/rest/service/api/runtime/task-and-stage-start.cmmn.xml");
54+
55+
runtimeService.createCaseInstanceBuilder().caseDefinitionKey("testCase").start();
56+
runtimeService.createCaseInstanceBuilder().caseDefinitionKey("testCase").start();
57+
58+
CaseDefinition v2 = deployCaseDefinition("v2", "org/flowable/cmmn/rest/service/api/runtime/task-and-stage-add-task-listener.cmmn.xml");
59+
60+
ObjectNode requestNode = objectMapper.createObjectNode();
61+
requestNode.put("toCaseDefinitionId", v2.getId());
62+
63+
HttpPost httpPost = new HttpPost(SERVER_URL_PREFIX +
64+
CmmnRestUrls.createRelativeResourceUrl(CmmnRestUrls.URL_CASE_DEFINITION, v1.getId()) + "/batch-migrate");
65+
httpPost.setEntity(new StringEntity(requestNode.toString()));
66+
67+
CloseableHttpResponse response = executeRequest(httpPost, HttpStatus.SC_OK);
68+
JsonNode responseNode = objectMapper.readTree(response.getEntity().getContent());
69+
70+
assertThat(responseNode.get("id").asString()).isNotEmpty();
71+
assertThat(responseNode.get("batchType").asString()).isEqualTo(Batch.CASE_MIGRATION_TYPE);
72+
assertThat(responseNode.get("searchKey").asString()).isEqualTo(v1.getId());
73+
assertThat(responseNode.get("searchKey2").asString()).isEqualTo(v2.getId());
74+
assertThat(responseNode.get("createTime").asString()).isNotEmpty();
75+
assertThat(responseNode.get("status").asString()).isNotEmpty();
76+
assertThat(responseNode.get("url").asString()).contains("cmmn-management/batches/" + responseNode.get("id").asString());
77+
}
78+
79+
@Test
80+
public void testBatchMigrateHistoricReturnsBatchResponse() throws Exception {
81+
CaseDefinition v1 = deployCaseDefinition("v1", "org/flowable/cmmn/rest/service/api/runtime/task-and-stage-start.cmmn.xml");
82+
83+
runtimeService.createCaseInstanceBuilder().caseDefinitionKey("testCase").start();
84+
85+
CaseDefinition v2 = deployCaseDefinition("v2", "org/flowable/cmmn/rest/service/api/runtime/task-and-stage-add-task-listener.cmmn.xml");
86+
87+
ObjectNode requestNode = objectMapper.createObjectNode();
88+
requestNode.put("toCaseDefinitionId", v2.getId());
89+
90+
HttpPost httpPost = new HttpPost(SERVER_URL_PREFIX +
91+
CmmnRestUrls.createRelativeResourceUrl(CmmnRestUrls.URL_CASE_DEFINITION, v1.getId()) + "/batch-migrate-historic-instances");
92+
httpPost.setEntity(new StringEntity(requestNode.toString()));
93+
94+
CloseableHttpResponse response = executeRequest(httpPost, HttpStatus.SC_OK);
95+
JsonNode responseNode = objectMapper.readTree(response.getEntity().getContent());
96+
97+
assertThat(responseNode.get("id").asString()).isNotEmpty();
98+
assertThat(responseNode.get("batchType").asString()).isEqualTo(Batch.CASE_MIGRATION_TYPE);
99+
assertThat(responseNode.get("searchKey").asString()).isEqualTo(v1.getId());
100+
assertThat(responseNode.get("searchKey2").asString()).isEqualTo(v2.getId());
101+
assertThat(responseNode.get("createTime").asString()).isNotEmpty();
102+
assertThat(responseNode.get("status").asString()).isNotEmpty();
103+
assertThat(responseNode.get("url").asString()).contains("cmmn-management/batches/" + responseNode.get("id").asString());
104+
}
105+
106+
protected CaseDefinition deployCaseDefinition(String name, String path) {
107+
CmmnDeployment deployment = repositoryService.createDeployment()
108+
.name(name)
109+
.addClasspathResource(path)
110+
.deploy();
111+
return repositoryService.createCaseDefinitionQuery()
112+
.deploymentId(deployment.getId()).singleResult();
113+
}
114+
}

modules/flowable-rest/src/main/java/org/flowable/rest/service/api/repository/ProcessDefinitionResource.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.Date;
1717

1818
import org.apache.commons.lang3.StringUtils;
19+
import org.flowable.batch.api.Batch;
1920
import org.flowable.bpmn.model.BpmnModel;
2021
import org.flowable.bpmn.model.FlowElement;
2122
import org.flowable.bpmn.model.Process;
@@ -36,6 +37,7 @@
3637
import org.flowable.form.model.SimpleFormModel;
3738
import org.flowable.rest.service.api.FormHandlerRestApiInterceptor;
3839
import org.flowable.rest.service.api.FormModelResponse;
40+
import org.flowable.rest.service.api.management.BatchResponse;
3941
import org.springframework.beans.factory.annotation.Autowired;
4042
import org.springframework.web.bind.annotation.GetMapping;
4143
import org.springframework.web.bind.annotation.PathVariable;
@@ -179,7 +181,7 @@ public void migrateInstancesOfProcessDefinition(@ApiParam(name = "processDefinit
179181
@ApiResponse(code = 404, message = "Indicates the requested process definition was not found.")
180182
})
181183
@PostMapping(value = "/repository/process-definitions/{processDefinitionId}/batch-migrate", produces = "application/json")
182-
public void batchMigrateInstancesOfProcessDefinition(@ApiParam(name = "processDefinitionId") @PathVariable String processDefinitionId,
184+
public BatchResponse batchMigrateInstancesOfProcessDefinition(@ApiParam(name = "processDefinitionId") @PathVariable String processDefinitionId,
183185
@RequestBody String migrationDocumentJson) {
184186

185187
ProcessDefinition processDefinition = getProcessDefinitionFromRequestWithoutAccessCheck(processDefinitionId);
@@ -189,7 +191,8 @@ public void batchMigrateInstancesOfProcessDefinition(@ApiParam(name = "processDe
189191
}
190192

191193
ProcessInstanceMigrationDocument migrationDocument = ProcessInstanceMigrationDocumentConverter.convertFromJson(migrationDocumentJson);
192-
processMigrationService.batchMigrateProcessInstancesOfProcessDefinition(processDefinitionId, migrationDocument);
194+
Batch batch = processMigrationService.batchMigrateProcessInstancesOfProcessDefinition(processDefinitionId, migrationDocument);
195+
return restResponseFactory.createBatchResponse(batch);
193196
}
194197

195198
protected FormInfo getStartForm(FormRepositoryService formRepositoryService, ProcessDefinition processDefinition) {

0 commit comments

Comments
 (0)