From d0f17a0203e5fca1c9a1c50cf0e3d02110741edf Mon Sep 17 00:00:00 2001 From: Javier Date: Wed, 28 Aug 2024 18:52:00 +0200 Subject: [PATCH 1/2] [Fix #418] Adding const support Signed-off-by: Javier --- api/pom.xml | 1 + .../io/serverlessworkflow/api/ApiTest.java | 19 +++++++++ .../serverlessworkflow/api/FeaturesTest.java | 3 +- .../test/resources/features/callFunction.yaml | 18 +++++++++ .../generator/ConstAnnotator.java | 40 +++++++++++++++++++ 5 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 api/src/test/resources/features/callFunction.yaml create mode 100644 custom-generator/src/main/java/io/serverlessworkflow/generator/ConstAnnotator.java diff --git a/api/pom.xml b/api/pom.xml index 37524b37..3bf0047e 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -101,6 +101,7 @@ true true io.serverlessworkflow.generator.UnreferencedFactory + io.serverlessworkflow.generator.ConstAnnotator 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..162ec31e --- /dev/null +++ b/api/src/test/resources/features/callFunction.yaml @@ -0,0 +1,18 @@ +document: + dsl: 1.0.0-alpha1 + namespace: default + name: http-call-with-response-output + +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/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()); + } + } +} From 3b65612d602c6cf0abfd303463a58e06b33072da Mon Sep 17 00:00:00 2001 From: Javier Date: Wed, 28 Aug 2024 19:39:11 +0200 Subject: [PATCH 2/2] [Fix #418] Adding Jsr 303 validation support Notice that this will force us to add version and other mandatory field we were not including in the examples Signed-off-by: Javier --- api/pom.xml | 14 ++--- .../api/ObjectMapperFactory.java | 7 ++- ...eanDeserializerModifierWithValidation.java | 35 +++++++++++++ .../BeanDeserializerWithValidation.java | 51 +++++++++++++++++++ .../serialization/DeserializeHelper.java | 3 +- .../test/resources/features/callFunction.yaml | 1 + api/src/test/resources/features/callHttp.yaml | 1 + .../test/resources/features/callOpenAPI.yaml | 1 + .../test/resources/features/composite.yaml | 1 + .../test/resources/features/data-flow.yaml | 1 + api/src/test/resources/features/emit.yaml | 1 + api/src/test/resources/features/flow.yaml | 1 + api/src/test/resources/features/for.yaml | 1 + api/src/test/resources/features/listen.yaml | 1 + api/src/test/resources/features/raise.yaml | 4 +- api/src/test/resources/features/set.yaml | 1 + api/src/test/resources/features/switch.yaml | 1 + api/src/test/resources/features/try.yaml | 1 + pom.xml | 14 ++++- 19 files changed, 130 insertions(+), 10 deletions(-) create mode 100644 api/src/main/java/io/serverlessworkflow/serialization/BeanDeserializerModifierWithValidation.java create mode 100644 api/src/main/java/io/serverlessworkflow/serialization/BeanDeserializerWithValidation.java diff --git a/api/pom.xml b/api/pom.xml index 3bf0047e..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 - 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/resources/features/callFunction.yaml b/api/src/test/resources/features/callFunction.yaml index 162ec31e..95a3a987 100644 --- a/api/src/test/resources/features/callFunction.yaml +++ b/api/src/test/resources/features/callFunction.yaml @@ -2,6 +2,7 @@ document: dsl: 1.0.0-alpha1 namespace: default name: http-call-with-response-output + version: 1.0.0 use: functions: 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/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