Skip to content

Commit e270bca

Browse files
authored
Merge pull request #121 from tsurdilo/addcontinueas
adding continueas
2 parents 1c27dc5 + 0b62312 commit e270bca

File tree

13 files changed

+392
-1
lines changed

13 files changed

+392
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.api.deserializers;
17+
18+
import com.fasterxml.jackson.core.JsonParser;
19+
import com.fasterxml.jackson.databind.DeserializationContext;
20+
import com.fasterxml.jackson.databind.JsonNode;
21+
import com.fasterxml.jackson.databind.ObjectMapper;
22+
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
23+
import io.serverlessworkflow.api.end.ContinueAs;
24+
import io.serverlessworkflow.api.interfaces.WorkflowPropertySource;
25+
import io.serverlessworkflow.api.timeouts.WorkflowExecTimeout;
26+
27+
import java.io.IOException;
28+
29+
public class ContinueAsDeserializer extends StdDeserializer<ContinueAs> {
30+
31+
private static final long serialVersionUID = 510l;
32+
33+
@SuppressWarnings("unused")
34+
private WorkflowPropertySource context;
35+
36+
public ContinueAsDeserializer() {
37+
this(ContinueAs.class);
38+
}
39+
40+
public ContinueAsDeserializer(Class<?> vc) {
41+
super(vc);
42+
}
43+
44+
public ContinueAsDeserializer(WorkflowPropertySource context) {
45+
this(ContinueAs.class);
46+
this.context = context;
47+
}
48+
49+
@Override
50+
public ContinueAs deserialize(JsonParser jp,
51+
DeserializationContext ctxt) throws IOException {
52+
53+
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
54+
JsonNode node = jp.getCodec().readTree(jp);
55+
56+
ContinueAs continueAs = new ContinueAs();
57+
58+
if (!node.isObject()) {
59+
continueAs.setWorkflowId(node.asText());
60+
continueAs.setVersion(null);
61+
continueAs.setData(null);
62+
continueAs.setWorkflowExecTimeout(null);
63+
return continueAs;
64+
} else {
65+
if (node.get("workflowId") != null) {
66+
continueAs.setWorkflowId(node.get("workflowId").asText());
67+
}
68+
69+
if (node.get("version") != null) {
70+
continueAs.setVersion(node.get("version").asText());
71+
}
72+
73+
if (node.get("data") != null) {
74+
continueAs.setData(node.get("data").asText());
75+
}
76+
77+
if (node.get("workflowExecTimeout") != null) {
78+
continueAs.setWorkflowExecTimeout(mapper.treeToValue(node.get("workflowExecTimeout"), WorkflowExecTimeout.class));
79+
}
80+
81+
return continueAs;
82+
}
83+
}
84+
}
85+

api/src/main/java/io/serverlessworkflow/api/deserializers/EndDefinitionDeserializer.java

+6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.fasterxml.jackson.databind.JsonNode;
2121
import com.fasterxml.jackson.databind.ObjectMapper;
2222
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
23+
import io.serverlessworkflow.api.end.ContinueAs;
2324
import io.serverlessworkflow.api.end.End;
2425
import io.serverlessworkflow.api.interfaces.WorkflowPropertySource;
2526
import io.serverlessworkflow.api.produce.ProduceEvent;
@@ -62,6 +63,7 @@ public End deserialize(JsonParser jp,
6263
end.setProduceEvents(null);
6364
end.setCompensate(false);
6465
end.setTerminate(false);
66+
end.setContinueAs(null);
6567
return node.asBoolean() ? end : null;
6668
} else {
6769
if (node.get("produceEvents") != null) {
@@ -84,6 +86,10 @@ public End deserialize(JsonParser jp,
8486
end.setCompensate(false);
8587
}
8688

89+
if(node.get("continueAs") != null) {
90+
end.setContinueAs(mapper.treeToValue(node.get("continueAs"), ContinueAs.class));
91+
}
92+
8793
return end;
8894

8995
}

api/src/main/java/io/serverlessworkflow/api/mapper/WorkflowModule.java

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import io.serverlessworkflow.api.cron.Cron;
2121
import io.serverlessworkflow.api.datainputschema.DataInputSchema;
2222
import io.serverlessworkflow.api.deserializers.*;
23+
import io.serverlessworkflow.api.end.ContinueAs;
2324
import io.serverlessworkflow.api.end.End;
2425
import io.serverlessworkflow.api.events.EventDefinition;
2526
import io.serverlessworkflow.api.events.OnEvents;
@@ -79,6 +80,7 @@ private void addDefaultSerializers() {
7980
addSerializer(new SubFlowRefSerializer());
8081
addSerializer(new AuthDefinitionSerializer());
8182
addSerializer(new StateExecTimeoutSerializer());
83+
addSerializer(new ContinueAsSerializer());
8284
addSerializer(extensionSerializer);
8385
}
8486

@@ -113,6 +115,7 @@ private void addDefaultDeserializers() {
113115
addDeserializer(AuthDefinition.class, new AuthDefinitionDeserializer(workflowPropertySource));
114116
addDeserializer(StateExecTimeout.class, new StateExecTimeoutDeserializer(workflowPropertySource));
115117
addDeserializer(Errors.class, new ErrorsDeserializer(workflowPropertySource));
118+
addDeserializer(ContinueAs.class, new ContinueAsDeserializer(workflowPropertySource));
116119
}
117120

118121
public ExtensionSerializer getExtensionSerializer() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.api.serializers;
17+
18+
import com.fasterxml.jackson.core.JsonGenerator;
19+
import com.fasterxml.jackson.databind.SerializerProvider;
20+
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
21+
import io.serverlessworkflow.api.end.ContinueAs;
22+
23+
import java.io.IOException;
24+
25+
public class ContinueAsSerializer extends StdSerializer<ContinueAs> {
26+
27+
public ContinueAsSerializer() {
28+
this(ContinueAs.class);
29+
}
30+
31+
protected ContinueAsSerializer(Class<ContinueAs> t) {
32+
super(t);
33+
}
34+
35+
@Override
36+
public void serialize(ContinueAs continueAs,
37+
JsonGenerator gen,
38+
SerializerProvider provider) throws IOException {
39+
40+
if (continueAs != null) {
41+
if ((continueAs.getWorkflowId() != null && !continueAs.getWorkflowId().isEmpty())
42+
&& (continueAs.getVersion() == null || continueAs.getVersion().isEmpty())
43+
&& (continueAs.getData() == null || continueAs.getData().isEmpty())
44+
&& continueAs.getWorkflowExecTimeout() == null ) {
45+
gen.writeString(continueAs.getWorkflowId());
46+
} else {
47+
gen.writeStartObject();
48+
49+
if (continueAs.getWorkflowId() != null && continueAs.getWorkflowId().length() > 0) {
50+
gen.writeStringField("workflowId", continueAs.getWorkflowId());
51+
}
52+
53+
if (continueAs.getVersion() != null && continueAs.getVersion().length() > 0) {
54+
gen.writeStringField("version", continueAs.getVersion());
55+
}
56+
57+
if (continueAs.getData() != null && continueAs.getData().length() > 0) {
58+
gen.writeStringField("data", continueAs.getData());
59+
}
60+
61+
if (continueAs.getWorkflowExecTimeout() != null) {
62+
gen.writeObjectField("workflowExecTimeout", continueAs.getWorkflowExecTimeout());
63+
}
64+
65+
66+
gen.writeEndObject();
67+
}
68+
}
69+
}
70+
}
71+
72+

api/src/main/java/io/serverlessworkflow/api/serializers/EndDefinitionSerializer.java

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public void serialize(End end,
4040

4141
if (end != null) {
4242
if ((end.getProduceEvents() == null || end.getProduceEvents().size() < 1)
43+
&& end.getContinueAs() == null
4344
&& !end.isCompensate() && !end.isTerminate()) {
4445
gen.writeBoolean(true);
4546
} else {
@@ -61,6 +62,10 @@ public void serialize(End end,
6162
gen.writeBooleanField("compensate", true);
6263
}
6364

65+
if(end.getContinueAs() != null) {
66+
gen.writeObjectField("continueAs", end.getContinueAs());
67+
}
68+
6469
gen.writeEndObject();
6570
}
6671
}

api/src/main/java/io/serverlessworkflow/api/serializers/StateExecTimeoutSerializer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public void serialize(StateExecTimeout stateExecTimeout,
3838
SerializerProvider provider) throws IOException {
3939

4040
if (stateExecTimeout != null) {
41-
if ((stateExecTimeout.getTotal() != null && stateExecTimeout.getTotal().isEmpty())
41+
if ((stateExecTimeout.getTotal() != null && !stateExecTimeout.getTotal().isEmpty())
4242
&& (stateExecTimeout.getSingle() == null || stateExecTimeout.getSingle().isEmpty())) {
4343
gen.writeString(stateExecTimeout.getTotal());
4444
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"type": "object",
3+
"javaType": "io.serverlessworkflow.api.end.ContinueAs",
4+
"description": "End definition continue as",
5+
"properties": {
6+
"workflowId": {
7+
"type": "string",
8+
"description": "Unique id of the workflow to continue execution as"
9+
},
10+
"version": {
11+
"type": "string",
12+
"description": "Version of the workflow to continue execution as",
13+
"minLength": 1
14+
},
15+
"data": {
16+
"type": [
17+
"string"
18+
],
19+
"description": "Expression which selects parts of the states data output to become the workflow data input of continued execution"
20+
},
21+
"workflowExecTimeout": {
22+
"$ref": "../timeouts/workflowexectimeout.json"
23+
}
24+
},
25+
"required": [
26+
"kind"
27+
]
28+
}s

api/src/main/resources/schema/end/end.json

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
"type": "boolean",
2121
"default": false,
2222
"description": "If set to true, triggers workflow compensation when before workflow executin completes. Default is false"
23+
},
24+
"continueAs": {
25+
"$ref": "continueas.json"
2326
}
2427
},
2528
"required": [

api/src/test/java/io/serverlessworkflow/api/test/MarkupToWorkflowTest.java

+49
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import io.serverlessworkflow.api.branches.Branch;
2323
import io.serverlessworkflow.api.datainputschema.DataInputSchema;
2424
import io.serverlessworkflow.api.defaultdef.DefaultConditionDefinition;
25+
import io.serverlessworkflow.api.end.End;
2526
import io.serverlessworkflow.api.functions.FunctionDefinition;
2627
import io.serverlessworkflow.api.functions.FunctionRef;
2728
import io.serverlessworkflow.api.functions.SubFlowRef;
@@ -736,4 +737,52 @@ public void testErrorsParams(String workflowLocation) {
736737
assertNotNull(operationState.getOnErrors().get(0).getErrorRefs());
737738
assertEquals(2, operationState.getOnErrors().get(0).getErrorRefs().size());
738739
}
740+
741+
@ParameterizedTest
742+
@ValueSource(strings = {"/features/continueasstring.json", "/features/continueasstring.yml"})
743+
public void testContinueAsString(String workflowLocation) {
744+
Workflow workflow = Workflow.fromSource(WorkflowTestUtils.readWorkflowFile(workflowLocation));
745+
746+
assertNotNull(workflow);
747+
assertNotNull(workflow.getId());
748+
assertNotNull(workflow.getName());
749+
assertNotNull(workflow.getStates());
750+
751+
assertNotNull(workflow.getStates());
752+
assertEquals(1, workflow.getStates().size());
753+
754+
OperationState operationState = (OperationState) workflow.getStates().get(0);
755+
assertNotNull(operationState.getEnd());
756+
End end = operationState.getEnd();
757+
assertNotNull(end.getContinueAs());
758+
assertNotNull(end.getContinueAs().getWorkflowId());
759+
assertEquals("myworkflowid", end.getContinueAs().getWorkflowId());
760+
761+
}
762+
763+
@ParameterizedTest
764+
@ValueSource(strings = {"/features/continueasobject.json", "/features/continueasobject.yml"})
765+
public void testContinueAsObject(String workflowLocation) {
766+
Workflow workflow = Workflow.fromSource(WorkflowTestUtils.readWorkflowFile(workflowLocation));
767+
768+
assertNotNull(workflow);
769+
assertNotNull(workflow.getId());
770+
assertNotNull(workflow.getName());
771+
assertNotNull(workflow.getStates());
772+
773+
assertNotNull(workflow.getStates());
774+
assertEquals(1, workflow.getStates().size());
775+
776+
OperationState operationState = (OperationState) workflow.getStates().get(0);
777+
assertNotNull(operationState.getEnd());
778+
End end = operationState.getEnd();
779+
assertNotNull(end.getContinueAs());
780+
assertNotNull(end.getContinueAs().getWorkflowId());
781+
assertEquals("myworkflowid", end.getContinueAs().getWorkflowId());
782+
assertEquals("1.0", end.getContinueAs().getVersion());
783+
assertEquals("${ .data }", end.getContinueAs().getData());
784+
assertNotNull(end.getContinueAs().getWorkflowExecTimeout());
785+
assertEquals("PT1M", end.getContinueAs().getWorkflowExecTimeout().getDuration());
786+
787+
}
739788
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"id": "functionrefs",
3+
"version": "1.0",
4+
"specVersion": "0.7",
5+
"name": "Customer Credit Check Workflow",
6+
"description": "Perform Customer Credit Check",
7+
"start": "TestFunctionRef",
8+
"functions": [
9+
{
10+
"name": "creditCheckFunction",
11+
"operation": "http://myapis.org/creditcheckapi.json#doCreditCheck"
12+
},
13+
{
14+
"name": "sendRejectionEmailFunction",
15+
"operation": "http://myapis.org/creditcheckapi.json#rejectionEmail"
16+
}
17+
],
18+
"states": [
19+
{
20+
"name": "TestFunctionRefs",
21+
"type": "operation",
22+
"actionMode": "sequential",
23+
"actions": [
24+
{
25+
"functionRef": "creditCheckFunction"
26+
},
27+
{
28+
"functionRef": {
29+
"refName": "sendRejectionEmailFunction",
30+
"arguments": {
31+
"applicant": "${ .customer }"
32+
}
33+
}
34+
}
35+
],
36+
"end": {
37+
"continueAs": {
38+
"workflowId": "myworkflowid",
39+
"version": "1.0",
40+
"data": "${ .data }",
41+
"workflowExecTimeout": {
42+
"duration": "PT1M"
43+
}
44+
}
45+
}
46+
}
47+
]
48+
}

0 commit comments

Comments
 (0)