Skip to content

Commit 0b62312

Browse files
committed
adding continueas
Signed-off-by: Tihomir Surdilovic <tihomir@temporal.io>
1 parent 1c27dc5 commit 0b62312

File tree

13 files changed

+392
-1
lines changed

13 files changed

+392
-1
lines changed
Lines changed: 85 additions & 0 deletions
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

Lines changed: 6 additions & 0 deletions
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

Lines changed: 3 additions & 0 deletions
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() {
Lines changed: 72 additions & 0 deletions
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

Lines changed: 5 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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 {
Lines changed: 28 additions & 0 deletions
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 49 additions & 0 deletions
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
}
Lines changed: 48 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy