Skip to content

Commit e804006

Browse files
committed
[Fix #359] Enhacing deserialization
Signed-off-by: Francisco Javier Tirado Sarti <[email protected]>
1 parent 78a598e commit e804006

File tree

13 files changed

+340
-13
lines changed

13 files changed

+340
-13
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Serverless Workflow Java SDK is **not** a workflow runtime implementation but ca
1616

1717
| Latest Releases | Conformance to spec version |
1818
| :---: | :---: |
19-
| [7.0.0.Final](https://github.com/serverlessworkflow/sdk-java/releases/tag/7.0.0.Final) | [v0.10](https://github.com/serverlessworkflow/specification/tree/0.10.x) |
19+
| [7.0.0.Final](https://github.com/serverlessworkflow/sdk-java/releases/tag/7.0.0.Final) | [v1.0.0](https://github.com/serverlessworkflow/specification/tree/1.0.x) |
2020
| [5.0.0.Final](https://github.com/serverlessworkflow/sdk-java/releases/tag/5.0.0.Final) | [v0.8](https://github.com/serverlessworkflow/specification/tree/0.8.x) |
2121
| [4.0.5.Final](https://github.com/serverlessworkflow/sdk-java/releases/tag/4.0.5.Final) | [v0.8](https://github.com/serverlessworkflow/specification/tree/0.8.x) |
2222
| [3.0.0.Final](https://github.com/serverlessworkflow/sdk-java/releases/tag/3.0.0.Final) | [v0.7](https://github.com/serverlessworkflow/specification/tree/0.7.x) |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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;
17+
18+
import com.fasterxml.jackson.core.JsonParser;
19+
import com.fasterxml.jackson.databind.DeserializationContext;
20+
import com.fasterxml.jackson.databind.JsonDeserializer;
21+
import io.serverlessworkflow.api.types.CallAsyncAPI;
22+
import io.serverlessworkflow.api.types.CallGRPC;
23+
import io.serverlessworkflow.api.types.CallHTTP;
24+
import io.serverlessworkflow.api.types.CallOpenAPI;
25+
import io.serverlessworkflow.api.types.CallTask;
26+
import java.io.IOException;
27+
import java.util.List;
28+
29+
class CallTaskDeserializer extends JsonDeserializer<CallTask> {
30+
31+
@Override
32+
public CallTask deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
33+
return DeserializeHelper.deserialize(
34+
p,
35+
CallTask.class,
36+
List.of(CallHTTP.class, CallAsyncAPI.class, CallOpenAPI.class, CallGRPC.class));
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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;
17+
18+
import com.fasterxml.jackson.core.JsonGenerator;
19+
import com.fasterxml.jackson.databind.JsonSerializer;
20+
import com.fasterxml.jackson.databind.SerializerProvider;
21+
import io.serverlessworkflow.api.types.CallTask;
22+
import java.io.IOException;
23+
24+
class CallTaskSerializer extends JsonSerializer<CallTask> {
25+
@Override
26+
public void serialize(CallTask value, JsonGenerator gen, SerializerProvider serializers)
27+
throws IOException {
28+
SerializeHelper.serialize(gen, value);
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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;
17+
18+
import com.fasterxml.jackson.core.JsonParser;
19+
import com.fasterxml.jackson.core.JsonProcessingException;
20+
import com.fasterxml.jackson.core.TreeNode;
21+
import com.fasterxml.jackson.databind.JsonMappingException;
22+
import java.io.IOException;
23+
import java.util.Collection;
24+
25+
public class DeserializeHelper {
26+
27+
public static <T> T deserialize(
28+
JsonParser p, Class<T> targetClass, Collection<Class<?>> unionTypes) throws IOException {
29+
TreeNode node = p.readValueAsTree();
30+
JsonProcessingException ex = new JsonMappingException("Problem deserializing " + targetClass);
31+
for (Class<?> unionType : unionTypes) {
32+
try {
33+
Object object = p.getCodec().treeToValue(node, unionType);
34+
return targetClass.getConstructor(unionType).newInstance(object);
35+
} catch (IOException | ReflectiveOperationException io) {
36+
ex.addSuppressed(io);
37+
}
38+
}
39+
throw ex;
40+
}
41+
}

api/src/main/java/io/serverlessworkflow/api/ObjectMapperFactory.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
*/
1616
package io.serverlessworkflow.api;
1717

18-
import com.fasterxml.jackson.databind.DeserializationFeature;
1918
import com.fasterxml.jackson.databind.ObjectMapper;
2019
import com.fasterxml.jackson.databind.SerializationFeature;
20+
import com.fasterxml.jackson.databind.module.SimpleModule;
2121
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
2222
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature;
23+
import io.serverlessworkflow.api.types.CallTask;
24+
import io.serverlessworkflow.api.types.Task;
2325

2426
class ObjectMapperFactory {
2527

@@ -37,11 +39,16 @@ public static final ObjectMapper yamlMapper() {
3739
}
3840

3941
private static ObjectMapper configure(ObjectMapper mapper) {
42+
SimpleModule simpleModule = new SimpleModule();
43+
simpleModule.addDeserializer(Task.class, new TaskDeserializer());
44+
simpleModule.addSerializer(Task.class, new TaskSerializer());
45+
simpleModule.addDeserializer(CallTask.class, new CallTaskDeserializer());
46+
simpleModule.addSerializer(CallTask.class, new CallTaskSerializer());
4047
return mapper
4148
.configure(SerializationFeature.INDENT_OUTPUT, true)
4249
.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, false)
4350
.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false)
44-
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
51+
.registerModule(simpleModule);
4552
}
4653

4754
private ObjectMapperFactory() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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;
17+
18+
import com.fasterxml.jackson.core.JsonGenerator;
19+
import java.io.IOException;
20+
import java.lang.reflect.Method;
21+
22+
public class SerializeHelper {
23+
public static void serialize(JsonGenerator jgen, Object item) throws IOException {
24+
try {
25+
for (Method m : item.getClass().getDeclaredMethods()) {
26+
Object value = m.invoke(item);
27+
if (value != null) {
28+
jgen.writeObject(value);
29+
break;
30+
}
31+
}
32+
} catch (ReflectiveOperationException ex) {
33+
throw new IOException(ex);
34+
}
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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;
17+
18+
import com.fasterxml.jackson.core.JsonParser;
19+
import com.fasterxml.jackson.databind.DeserializationContext;
20+
import com.fasterxml.jackson.databind.JsonDeserializer;
21+
import io.serverlessworkflow.api.types.CallTask;
22+
import io.serverlessworkflow.api.types.DoTask;
23+
import io.serverlessworkflow.api.types.EmitTask;
24+
import io.serverlessworkflow.api.types.ForTask;
25+
import io.serverlessworkflow.api.types.ForkTask;
26+
import io.serverlessworkflow.api.types.ListenTask;
27+
import io.serverlessworkflow.api.types.RaiseTask;
28+
import io.serverlessworkflow.api.types.RunTask;
29+
import io.serverlessworkflow.api.types.SetTask;
30+
import io.serverlessworkflow.api.types.SwitchTask;
31+
import io.serverlessworkflow.api.types.Task;
32+
import io.serverlessworkflow.api.types.TryTask;
33+
import io.serverlessworkflow.api.types.WaitTask;
34+
import java.io.IOException;
35+
import java.util.List;
36+
37+
class TaskDeserializer extends JsonDeserializer<Task> {
38+
39+
@Override
40+
public Task deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
41+
return DeserializeHelper.deserialize(
42+
p,
43+
Task.class,
44+
List.of(
45+
CallTask.class,
46+
DoTask.class,
47+
SwitchTask.class,
48+
TryTask.class,
49+
RaiseTask.class,
50+
EmitTask.class,
51+
ForkTask.class,
52+
ForTask.class,
53+
ListenTask.class,
54+
SetTask.class,
55+
RunTask.class,
56+
WaitTask.class));
57+
}
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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;
17+
18+
import com.fasterxml.jackson.core.JsonGenerator;
19+
import com.fasterxml.jackson.databind.JsonSerializer;
20+
import com.fasterxml.jackson.databind.SerializerProvider;
21+
import io.serverlessworkflow.api.types.Task;
22+
import java.io.IOException;
23+
24+
class TaskSerializer extends JsonSerializer<Task> {
25+
26+
@Override
27+
public void serialize(Task value, JsonGenerator gen, SerializerProvider serializers)
28+
throws IOException {
29+
SerializeHelper.serialize(gen, value);
30+
}
31+
}

api/src/test/resources/features/callOpenAPI.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ do:
88
with:
99
document:
1010
uri: "https://petstore.swagger.io/v2/swagger.json"
11-
operation: findPetsByStatus
11+
operationId: findPetsByStatus
1212
parameters:
1313
status: ${ .status }
1414
output:
15-
from: . | length
15+
as: . | length

api/src/test/resources/features/composite.yaml

+6-6
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ do:
66
- compositeExample:
77
do:
88
- setRed:
9-
set:
10-
colors: ${ .colors + ["red"] }
9+
set:
10+
colors: ${ .colors + ["red"] }
1111
- setGreen:
12-
set:
13-
colors: ${ .colors + ["green"] }
12+
set:
13+
colors: ${ .colors + ["green"] }
1414
- setBlue:
15-
set:
16-
colors: ${ .colors + ["blue"] }
15+
set:
16+
colors: ${ .colors + ["blue"] }

custom-generator/src/main/java/io/serverlessworkflow/generator/AllAnyOneOfSchemaRule.java

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
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+
*/
116
package io.serverlessworkflow.generator;
217

318
import static org.apache.commons.lang3.StringUtils.*;
419

5-
import com.fasterxml.jackson.annotation.JsonUnwrapped;
620
import com.fasterxml.jackson.databind.JsonNode;
721
import com.fasterxml.jackson.databind.node.ArrayNode;
822
import com.sun.codemodel.JClass;
923
import com.sun.codemodel.JClassAlreadyExistsException;
1024
import com.sun.codemodel.JClassContainer;
1125
import com.sun.codemodel.JDefinedClass;
26+
import com.sun.codemodel.JExpr;
1227
import com.sun.codemodel.JFieldVar;
1328
import com.sun.codemodel.JMethod;
1429
import com.sun.codemodel.JMod;
@@ -93,6 +108,10 @@ private JDefinedClass populateClass(
93108
wrapIt(definedClass, type);
94109
}
95110
});
111+
if (definedClass.constructors().hasNext()
112+
&& definedClass.getConstructor(new JType[0]) == null) {
113+
definedClass.constructor(JMod.PUBLIC);
114+
}
96115
return definedClass;
97116
}
98117

@@ -112,13 +131,17 @@ private void wrapIt(JDefinedClass definedClass, JType unionType) {
112131
JMod.PRIVATE,
113132
unionType,
114133
ruleFactory.getNameHelper().getPropertyName(unionType.name(), null));
115-
instanceField.annotate(JsonUnwrapped.class);
116134
JMethod method =
117135
definedClass.method(
118136
JMod.PUBLIC,
119137
unionType,
120138
ruleFactory.getNameHelper().getGetterName(unionType.name(), unionType, null));
121139
method.body()._return(instanceField);
140+
JMethod constructor = definedClass.constructor(JMod.PUBLIC);
141+
constructor
142+
.body()
143+
.assign(
144+
JExpr._this().ref(instanceField), constructor.param(unionType, instanceField.name()));
122145
}
123146

124147
private void unionType(

0 commit comments

Comments
 (0)