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 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