diff --git a/core/src/main/java/com/netflix/conductor/model/TaskModel.java b/core/src/main/java/com/netflix/conductor/model/TaskModel.java index d41640766c..57071099df 100644 --- a/core/src/main/java/com/netflix/conductor/model/TaskModel.java +++ b/core/src/main/java/com/netflix/conductor/model/TaskModel.java @@ -25,6 +25,7 @@ import com.netflix.conductor.common.metadata.workflow.WorkflowTask; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.protobuf.Any; public class TaskModel { @@ -69,8 +70,6 @@ public boolean isRetriable() { private Status status; - private Map inputData = new HashMap<>(); - private String referenceTaskName; private int retryCount; @@ -119,8 +118,6 @@ public boolean isRetriable() { private String workerId; - private Map outputData = new HashMap<>(); - private WorkflowTask workflowTask; private String domain; @@ -159,6 +156,10 @@ public boolean isRetriable() { @JsonIgnore private Map outputPayload = new HashMap<>(); + @JsonIgnore private Map inputData = new HashMap<>(); + + @JsonIgnore private Map outputData = new HashMap<>(); + public String getTaskType() { return taskType; } @@ -175,10 +176,12 @@ public void setStatus(Status status) { this.status = status; } + @JsonIgnore public Map getInputData() { return externalInputPayloadStoragePath != null ? inputPayload : inputData; } + @JsonIgnore public void setInputData(Map inputData) { if (inputData == null) { inputData = new HashMap<>(); @@ -186,6 +189,20 @@ public void setInputData(Map inputData) { this.inputData = inputData; } + /** @deprecated Used only for JSON serialization and deserialization. */ + @JsonProperty("inputData") + @Deprecated + public void setRawInputData(Map inputData) { + setInputData(inputData); + } + + /** @deprecated Used only for JSON serialization and deserialization. */ + @JsonProperty("inputData") + @Deprecated + public Map getRawInputData() { + return inputData; + } + public String getReferenceTaskName() { return referenceTaskName; } @@ -365,10 +382,12 @@ public void setWorkerId(String workerId) { this.workerId = workerId; } + @JsonIgnore public Map getOutputData() { return externalOutputPayloadStoragePath != null ? outputPayload : outputData; } + @JsonIgnore public void setOutputData(Map outputData) { if (outputData == null) { outputData = new HashMap<>(); @@ -376,6 +395,20 @@ public void setOutputData(Map outputData) { this.outputData = outputData; } + /** @deprecated Used only for JSON serialization and deserialization. */ + @JsonProperty("outputData") + @Deprecated + public void setRawOutputData(Map inputData) { + setOutputData(inputData); + } + + /** @deprecated Used only for JSON serialization and deserialization. */ + @JsonProperty("outputData") + @Deprecated + public Map getRawOutputData() { + return outputData; + } + public WorkflowTask getWorkflowTask() { return workflowTask; } diff --git a/core/src/main/java/com/netflix/conductor/model/WorkflowModel.java b/core/src/main/java/com/netflix/conductor/model/WorkflowModel.java index 428e90d93e..5968725970 100644 --- a/core/src/main/java/com/netflix/conductor/model/WorkflowModel.java +++ b/core/src/main/java/com/netflix/conductor/model/WorkflowModel.java @@ -22,6 +22,7 @@ import com.netflix.conductor.common.run.Workflow; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.Preconditions; public class WorkflowModel { @@ -63,14 +64,6 @@ public boolean isSuccessful() { private List tasks = new LinkedList<>(); - private Map input = new HashMap<>(); - - private Map output = new HashMap<>(); - - @JsonIgnore private Map inputPayload = new HashMap<>(); - - @JsonIgnore private Map outputPayload = new HashMap<>(); - private String correlationId; private String reRunFromWorkflowId; @@ -110,6 +103,14 @@ public boolean isSuccessful() { private Status previousStatus; + @JsonIgnore private Map input = new HashMap<>(); + + @JsonIgnore private Map output = new HashMap<>(); + + @JsonIgnore private Map inputPayload = new HashMap<>(); + + @JsonIgnore private Map outputPayload = new HashMap<>(); + public Status getPreviousStatus() { return previousStatus; } @@ -170,10 +171,12 @@ public void setTasks(List tasks) { this.tasks = tasks; } + @JsonIgnore public Map getInput() { return externalInputPayloadStoragePath != null ? inputPayload : input; } + @JsonIgnore public void setInput(Map input) { if (input == null) { input = new HashMap<>(); @@ -181,10 +184,12 @@ public void setInput(Map input) { this.input = input; } + @JsonIgnore public Map getOutput() { return externalOutputPayloadStoragePath != null ? outputPayload : output; } + @JsonIgnore public void setOutput(Map output) { if (output == null) { output = new HashMap<>(); @@ -192,6 +197,34 @@ public void setOutput(Map output) { this.output = output; } + /** @deprecated Used only for JSON serialization and deserialization. */ + @Deprecated + @JsonProperty("input") + public Map getRawInput() { + return input; + } + + /** @deprecated Used only for JSON serialization and deserialization. */ + @Deprecated + @JsonProperty("input") + public void setRawInput(Map input) { + setInput(input); + } + + /** @deprecated Used only for JSON serialization and deserialization. */ + @Deprecated + @JsonProperty("output") + public Map getRawOutput() { + return output; + } + + /** @deprecated Used only for JSON serialization and deserialization. */ + @Deprecated + @JsonProperty("output") + public void setRawOutput(Map output) { + setOutput(output); + } + public String getCorrelationId() { return correlationId; } diff --git a/core/src/test/groovy/com/netflix/conductor/model/TaskModelSpec.groovy b/core/src/test/groovy/com/netflix/conductor/model/TaskModelSpec.groovy new file mode 100644 index 0000000000..c95f8edb67 --- /dev/null +++ b/core/src/test/groovy/com/netflix/conductor/model/TaskModelSpec.groovy @@ -0,0 +1,66 @@ +/* + * Copyright 2022 Netflix, Inc. + *

+ * 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 com.netflix.conductor.model + +import com.netflix.conductor.common.config.ObjectMapperProvider + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.ObjectMapper +import spock.lang.Specification +import spock.lang.Subject + +class TaskModelSpec extends Specification { + + @Subject + TaskModel taskModel + + private static final ObjectMapper objectMapper = new ObjectMapperProvider().getObjectMapper() + + def setup() { + taskModel = new TaskModel() + } + + def "check inputData serialization"() { + given: + String path = "task/input/${UUID.randomUUID()}.json" + taskModel.addInput(['key1': 'value1', 'key2': 'value2']) + taskModel.externalizeInput(path) + + when: + def json = objectMapper.writeValueAsString(taskModel) + println(json) + + then: + json != null + JsonNode node = objectMapper.readTree(json) + node.path("inputData").isEmpty() + node.path("externalInputPayloadStoragePath").isTextual() + } + + def "check outputData serialization"() { + given: + String path = "task/output/${UUID.randomUUID()}.json" + taskModel.addOutput(['key1': 'value1', 'key2': 'value2']) + taskModel.externalizeOutput(path) + + when: + def json = objectMapper.writeValueAsString(taskModel) + println(json) + + then: + json != null + JsonNode node = objectMapper.readTree(json) + node.path("outputData").isEmpty() + node.path("externalOutputPayloadStoragePath").isTextual() + } +} diff --git a/core/src/test/groovy/com/netflix/conductor/model/WorkflowModelSpec.groovy b/core/src/test/groovy/com/netflix/conductor/model/WorkflowModelSpec.groovy new file mode 100644 index 0000000000..3b7763a23b --- /dev/null +++ b/core/src/test/groovy/com/netflix/conductor/model/WorkflowModelSpec.groovy @@ -0,0 +1,68 @@ +/* + * Copyright 2022 Netflix, Inc. + *

+ * 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 com.netflix.conductor.model + +import com.netflix.conductor.common.config.ObjectMapperProvider +import com.netflix.conductor.common.metadata.workflow.WorkflowDef + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.ObjectMapper +import spock.lang.Specification +import spock.lang.Subject + +class WorkflowModelSpec extends Specification { + + @Subject + WorkflowModel workflowModel + + private static final ObjectMapper objectMapper = new ObjectMapperProvider().getObjectMapper() + + def setup() { + def workflowDef = new WorkflowDef(name: "test def name", version: 1) + workflowModel = new WorkflowModel(workflowDefinition: workflowDef) + } + + def "check input serialization"() { + given: + String path = "task/input/${UUID.randomUUID()}.json" + workflowModel.input = ['key1': 'value1', 'key2': 'value2'] + workflowModel.externalizeInput(path) + + when: + def json = objectMapper.writeValueAsString(workflowModel) + println(json) + + then: + json != null + JsonNode node = objectMapper.readTree(json) + node.path("input").isEmpty() + node.path("externalInputPayloadStoragePath").isTextual() + } + + def "check output serialization"() { + given: + String path = "task/output/${UUID.randomUUID()}.json" + workflowModel.output = ['key1': 'value1', 'key2': 'value2'] + workflowModel.externalizeOutput(path) + + when: + def json = objectMapper.writeValueAsString(workflowModel) + println(json) + + then: + json != null + JsonNode node = objectMapper.readTree(json) + node.path("output").isEmpty() + node.path("externalOutputPayloadStoragePath").isTextual() + } +}