diff --git a/api/pom.xml b/api/pom.xml
index 37524b37..d5128d57 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -33,7 +33,14 @@
jakarta.validation
jakarta.validation-api
-
+
+ org.hibernate.validator
+ hibernate-validator
+
+
+ org.glassfish.expressly
+ expressly
+
org.junit.jupiter
@@ -65,11 +72,6 @@
logback-classic
test
-
- org.assertj
- assertj-core
- test
-
@@ -101,6 +103,7 @@
true
true
io.serverlessworkflow.generator.UnreferencedFactory
+ io.serverlessworkflow.generator.ConstAnnotator
diff --git a/api/src/main/java/io/serverlessworkflow/api/ObjectMapperFactory.java b/api/src/main/java/io/serverlessworkflow/api/ObjectMapperFactory.java
index 7bc8414e..850e7da7 100644
--- a/api/src/main/java/io/serverlessworkflow/api/ObjectMapperFactory.java
+++ b/api/src/main/java/io/serverlessworkflow/api/ObjectMapperFactory.java
@@ -17,8 +17,10 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature;
+import io.serverlessworkflow.serialization.BeanDeserializerModifierWithValidation;
class ObjectMapperFactory {
@@ -36,10 +38,13 @@ public static final ObjectMapper yamlMapper() {
}
private static ObjectMapper configure(ObjectMapper mapper) {
+ SimpleModule validationModule = new SimpleModule();
+ validationModule.setDeserializerModifier(new BeanDeserializerModifierWithValidation());
return mapper
.configure(SerializationFeature.INDENT_OUTPUT, true)
.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, false)
- .configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
+ .configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false)
+ .registerModule(validationModule);
}
private ObjectMapperFactory() {}
diff --git a/api/src/main/java/io/serverlessworkflow/serialization/BeanDeserializerModifierWithValidation.java b/api/src/main/java/io/serverlessworkflow/serialization/BeanDeserializerModifierWithValidation.java
new file mode 100644
index 00000000..e4e019ac
--- /dev/null
+++ b/api/src/main/java/io/serverlessworkflow/serialization/BeanDeserializerModifierWithValidation.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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 io.serverlessworkflow.serialization;
+
+import com.fasterxml.jackson.databind.BeanDescription;
+import com.fasterxml.jackson.databind.DeserializationConfig;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.deser.BeanDeserializer;
+import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
+
+public class BeanDeserializerModifierWithValidation extends BeanDeserializerModifier {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public JsonDeserializer> modifyDeserializer(
+ DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer> deserializer) {
+ return deserializer instanceof BeanDeserializer
+ ? new BeanDeserializerWithValidation((BeanDeserializer) deserializer)
+ : deserializer;
+ }
+}
diff --git a/api/src/main/java/io/serverlessworkflow/serialization/BeanDeserializerWithValidation.java b/api/src/main/java/io/serverlessworkflow/serialization/BeanDeserializerWithValidation.java
new file mode 100644
index 00000000..a77e117d
--- /dev/null
+++ b/api/src/main/java/io/serverlessworkflow/serialization/BeanDeserializerWithValidation.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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 io.serverlessworkflow.serialization;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.BeanDeserializer;
+import com.fasterxml.jackson.databind.deser.BeanDeserializerBase;
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.ConstraintViolationException;
+import jakarta.validation.Validation;
+import jakarta.validation.Validator;
+import java.io.IOException;
+import java.util.Set;
+
+public class BeanDeserializerWithValidation extends BeanDeserializer {
+ private static final long serialVersionUID = 1L;
+ private static final Validator validator =
+ Validation.buildDefaultValidatorFactory().getValidator();
+
+ protected BeanDeserializerWithValidation(BeanDeserializerBase src) {
+ super(src);
+ }
+
+ private void validate(T t) throws IOException {
+ Set> violations = validator.validate(t);
+ if (!violations.isEmpty()) {
+ throw new ConstraintViolationException(violations);
+ }
+ }
+
+ @Override
+ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+ Object instance = super.deserialize(p, ctxt);
+ validate(instance);
+ return instance;
+ }
+}
diff --git a/api/src/main/java/io/serverlessworkflow/serialization/DeserializeHelper.java b/api/src/main/java/io/serverlessworkflow/serialization/DeserializeHelper.java
index fc5390f1..72b4cce0 100644
--- a/api/src/main/java/io/serverlessworkflow/serialization/DeserializeHelper.java
+++ b/api/src/main/java/io/serverlessworkflow/serialization/DeserializeHelper.java
@@ -19,6 +19,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.JsonMappingException;
+import jakarta.validation.ConstraintViolationException;
import java.io.IOException;
import java.util.Collection;
@@ -33,7 +34,7 @@ public static T deserializeOneOf(
try {
Object object = p.getCodec().treeToValue(node, unionType);
return targetClass.getConstructor(unionType).newInstance(object);
- } catch (IOException | ReflectiveOperationException io) {
+ } catch (IOException | ReflectiveOperationException | ConstraintViolationException io) {
ex.addSuppressed(io);
}
}
diff --git a/api/src/test/java/io/serverlessworkflow/api/ApiTest.java b/api/src/test/java/io/serverlessworkflow/api/ApiTest.java
index ac5f7532..20248f35 100644
--- a/api/src/test/java/io/serverlessworkflow/api/ApiTest.java
+++ b/api/src/test/java/io/serverlessworkflow/api/ApiTest.java
@@ -18,6 +18,7 @@
import static io.serverlessworkflow.api.WorkflowReader.readWorkflowFromClasspath;
import static org.assertj.core.api.Assertions.assertThat;
+import io.serverlessworkflow.api.types.CallFunction;
import io.serverlessworkflow.api.types.CallHTTP;
import io.serverlessworkflow.api.types.CallTask;
import io.serverlessworkflow.api.types.Task;
@@ -44,4 +45,22 @@ void testCallHTTPAPI() throws IOException {
assertThat(httpCall.getWith().getMethod()).isEqualTo("get");
}
}
+
+ @Test
+ void testCallFunctionAPIWithoutArguments() throws IOException {
+ Workflow workflow = readWorkflowFromClasspath("features/callFunction.yaml");
+ assertThat(workflow.getDo()).isNotEmpty();
+ assertThat(workflow.getDo().get(0).getName()).isNotNull();
+ assertThat(workflow.getDo().get(0).getTask()).isNotNull();
+ Task task = workflow.getDo().get(0).getTask();
+ CallTask callTask = task.getCallTask();
+ assertThat(callTask).isNotNull();
+ assertThat(callTask.get()).isInstanceOf(CallFunction.class);
+ if (callTask.get() instanceof CallFunction) {
+ CallFunction functionCall = callTask.getCallFunction();
+ assertThat(functionCall).isNotNull();
+ assertThat(callTask.getCallAsyncAPI()).isNull();
+ assertThat(functionCall.getWith()).isNull();
+ }
+ }
}
diff --git a/api/src/test/java/io/serverlessworkflow/api/FeaturesTest.java b/api/src/test/java/io/serverlessworkflow/api/FeaturesTest.java
index 8e77673b..af11a49b 100644
--- a/api/src/test/java/io/serverlessworkflow/api/FeaturesTest.java
+++ b/api/src/test/java/io/serverlessworkflow/api/FeaturesTest.java
@@ -43,7 +43,8 @@ public class FeaturesTest {
"features/set.yaml",
"features/switch.yaml",
"features/try.yaml",
- "features/listen.yaml"
+ "features/listen.yaml",
+ "features/callFunction.yaml"
})
public void testSpecFeaturesParsing(String workflowLocation) throws IOException {
Workflow workflow = readWorkflowFromClasspath(workflowLocation);
diff --git a/api/src/test/resources/features/callFunction.yaml b/api/src/test/resources/features/callFunction.yaml
new file mode 100644
index 00000000..95a3a987
--- /dev/null
+++ b/api/src/test/resources/features/callFunction.yaml
@@ -0,0 +1,19 @@
+document:
+ dsl: 1.0.0-alpha1
+ namespace: default
+ name: http-call-with-response-output
+ version: 1.0.0
+
+use:
+ functions:
+ getPet:
+ call: http
+ with:
+ method: get
+ endpoint:
+ uri: https://petstore.swagger.io/v2/pet/{petId}
+ output: response
+
+do:
+ - getPetFunctionCall:
+ call: getPet
\ No newline at end of file
diff --git a/api/src/test/resources/features/callHttp.yaml b/api/src/test/resources/features/callHttp.yaml
index 9b48c783..4022e38a 100644
--- a/api/src/test/resources/features/callHttp.yaml
+++ b/api/src/test/resources/features/callHttp.yaml
@@ -2,6 +2,7 @@ document:
dsl: 1.0.0-alpha1
namespace: default
name: http-call-with-response-output
+ version: 1.0.0
do:
- getPet:
call: http
diff --git a/api/src/test/resources/features/callOpenAPI.yaml b/api/src/test/resources/features/callOpenAPI.yaml
index 46ecc921..1a1d0c56 100644
--- a/api/src/test/resources/features/callOpenAPI.yaml
+++ b/api/src/test/resources/features/callOpenAPI.yaml
@@ -2,6 +2,7 @@ document:
dsl: 1.0.0-alpha1
namespace: default
name: openapi-call-with-content-output
+ version: 1.0.0
do:
- findPet:
call: openapi
diff --git a/api/src/test/resources/features/composite.yaml b/api/src/test/resources/features/composite.yaml
index 71b0dea4..515cda25 100644
--- a/api/src/test/resources/features/composite.yaml
+++ b/api/src/test/resources/features/composite.yaml
@@ -2,6 +2,7 @@ document:
dsl: 1.0.0-alpha1
namespace: default
name: do
+ version: 1.0.0
do:
- compositeExample:
do:
diff --git a/api/src/test/resources/features/data-flow.yaml b/api/src/test/resources/features/data-flow.yaml
index d66d7848..bebb2123 100644
--- a/api/src/test/resources/features/data-flow.yaml
+++ b/api/src/test/resources/features/data-flow.yaml
@@ -2,6 +2,7 @@ document:
dsl: 1.0.0-alpha1
namespace: default
name: output-filtering
+ version: 1.0.0
do:
- getPet:
call: http
diff --git a/api/src/test/resources/features/emit.yaml b/api/src/test/resources/features/emit.yaml
index 488feedc..983407d9 100644
--- a/api/src/test/resources/features/emit.yaml
+++ b/api/src/test/resources/features/emit.yaml
@@ -2,6 +2,7 @@ document:
dsl: 1.0.0-alpha1
namespace: default
name: emit
+ version: 1.0.0
do:
- emitEvent:
emit:
diff --git a/api/src/test/resources/features/flow.yaml b/api/src/test/resources/features/flow.yaml
index 83baf04c..6bd8a6e7 100644
--- a/api/src/test/resources/features/flow.yaml
+++ b/api/src/test/resources/features/flow.yaml
@@ -2,6 +2,7 @@ document:
dsl: 1.0.0-alpha1
namespace: default
name: implicit-sequence
+ version: 1.0.0
do:
- setRed:
set:
diff --git a/api/src/test/resources/features/for.yaml b/api/src/test/resources/features/for.yaml
index f8ae826d..662dff91 100644
--- a/api/src/test/resources/features/for.yaml
+++ b/api/src/test/resources/features/for.yaml
@@ -2,6 +2,7 @@ document:
dsl: 1.0.0-alpha1
namespace: default
name: for
+ version: 1.0.0
do:
- loopColors:
for:
diff --git a/api/src/test/resources/features/listen.yaml b/api/src/test/resources/features/listen.yaml
index 393355d0..1c56c229 100644
--- a/api/src/test/resources/features/listen.yaml
+++ b/api/src/test/resources/features/listen.yaml
@@ -2,6 +2,7 @@ document:
dsl: 1.0.0-alpha1
namespace: default
name: listen-task
+ version: 1.0.0
do:
- listenToSomething:
listen:
diff --git a/api/src/test/resources/features/raise.yaml b/api/src/test/resources/features/raise.yaml
index 9dd6b4f3..7745162c 100644
--- a/api/src/test/resources/features/raise.yaml
+++ b/api/src/test/resources/features/raise.yaml
@@ -2,10 +2,12 @@ document:
dsl: 1.0.0-alpha1
namespace: default
name: raise-custom-error
+ version: 1.0.0
do:
- raiseError:
raise:
error:
status: 400
type: https://serverlessworkflow.io/errors/types/compliance
- title: Compliance Error
\ No newline at end of file
+ title: Compliance Error
+ instance: raiseError
\ No newline at end of file
diff --git a/api/src/test/resources/features/set.yaml b/api/src/test/resources/features/set.yaml
index 1589792f..dfebbf2d 100644
--- a/api/src/test/resources/features/set.yaml
+++ b/api/src/test/resources/features/set.yaml
@@ -2,6 +2,7 @@ document:
dsl: 1.0.0-alpha1
namespace: default
name: set
+ version: 1.0.0
do:
- setShape:
set:
diff --git a/api/src/test/resources/features/switch.yaml b/api/src/test/resources/features/switch.yaml
index 74d046cb..aa073fed 100644
--- a/api/src/test/resources/features/switch.yaml
+++ b/api/src/test/resources/features/switch.yaml
@@ -2,6 +2,7 @@ document:
dsl: 1.0.0-alpha1
namespace: default
name: switch-match
+ version: 1.0.0
do:
- switchColor:
switch:
diff --git a/api/src/test/resources/features/try.yaml b/api/src/test/resources/features/try.yaml
index 7f9ba599..ec19194d 100644
--- a/api/src/test/resources/features/try.yaml
+++ b/api/src/test/resources/features/try.yaml
@@ -2,6 +2,7 @@ document:
dsl: 1.0.0-alpha1
namespace: default
name: try-catch-404
+ version: 1.0.0
do:
- tryGetPet:
try:
diff --git a/custom-generator/src/main/java/io/serverlessworkflow/generator/ConstAnnotator.java b/custom-generator/src/main/java/io/serverlessworkflow/generator/ConstAnnotator.java
new file mode 100644
index 00000000..a893cfb5
--- /dev/null
+++ b/custom-generator/src/main/java/io/serverlessworkflow/generator/ConstAnnotator.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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 io.serverlessworkflow.generator;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.codemodel.JDefinedClass;
+import com.sun.codemodel.JFieldVar;
+import jakarta.validation.constraints.Pattern;
+import org.jsonschema2pojo.AbstractAnnotator;
+import org.jsonschema2pojo.GenerationConfig;
+
+public class ConstAnnotator extends AbstractAnnotator {
+
+ private static final String CONST = "const";
+
+ public ConstAnnotator(GenerationConfig generationConfig) {
+ super(generationConfig);
+ }
+
+ @Override
+ public void propertyField(
+ JFieldVar field, JDefinedClass clazz, String propertyName, JsonNode propertyNode) {
+ if (propertyNode.has(CONST)) {
+ field.annotate(Pattern.class).param("regexp", propertyNode.get(CONST).asText());
+ }
+ }
+}
diff --git a/pom.xml b/pom.xml
index 42064622..5311c098 100644
--- a/pom.xml
+++ b/pom.xml
@@ -76,7 +76,8 @@
5.11.0
5.12.0
2.0.16
-
+ 8.0.1.Final
+ 5.0.0
true
@@ -124,6 +125,17 @@
json-schema-validator
${version.com.networknt}
+
+ org.hibernate.validator
+ hibernate-validator
+ ${version.org.hibernate.validator}
+
+
+ org.glassfish.expressly
+ expressly
+ ${version.org.glassfish.expressly}
+
+
com.fasterxml.jackson.dataformat
jackson-dataformat-yaml