Skip to content

[0.8] - Functions, Errors, Events objects are marshaling into YAML/JSON with ref attributes instead of actual object #603

@ricardozanini

Description

@ricardozanini

What happened:

Given the following builder:

public class WorkFlowBuilder {

    public Workflow buildWorkFlow() throws JsonProcessingException {

        ObjectMapper mapper = new ObjectMapper();

        JsonNode sendOrderArgs = mapper.readTree("""
                {
                  "supplier-id": "1",
                  "content": ".orderId",
                  "locator": ".reference"
                }
                """);

        JsonNode printMessageArgs = mapper.readTree("""
                {
                  "message": "\\"Order received: \\" + .orderId",
                  "locator": ".reference"
                }
                """);
        // Define Function Definitions
        FunctionDefinition sendOrderFunction = new FunctionDefinition()
                .withName("sendOrder")
                .withOperation("specs/sendOrderOpenApi.yaml#sendOrder")
                .withType(FunctionDefinition.Type.CUSTOM);

        FunctionDefinition printMessageFunction = new FunctionDefinition()
                .withName("printMessage")
                .withOperation("specs/printMessage.yaml#printMessage")
                .withType(FunctionDefinition.Type.CUSTOM);

        // Define Actions
        Action sendOrderAction = new Action()
                .withName("sendOrder")
                .withFunctionRef(new io.serverlessworkflow.api.functions.FunctionRef()
                        .withRefName("sendOrder")
                        .withArguments(sendOrderArgs)
                        .withInvoke(FunctionRef.Invoke.SYNC))
                .withRetryRef("defaultRetry")
                .withRetryableErrors(List.of(
                        "Internal Server error", "Bad Gateway", "Service Unavailable",
                        "Gateway timeout", "Insufficient storage", "Locked"
                ))
                .withNonRetryableErrors(List.of());

        Action printMessageAction = new Action()
                .withName("printMessage")
                .withFunctionRef(new io.serverlessworkflow.api.functions.FunctionRef()
                        .withRefName("printMessage")
                        .withArguments(printMessageArgs)
                        .withInvoke(FunctionRef.Invoke.SYNC))
                .withRetryRef("defaultRetry")
                .withRetryableErrors(sendOrderAction.getRetryableErrors())
                .withNonRetryableErrors(List.of());

        // Define State
        OperationState orderReceivedState = new OperationState()
                .withName("Order Received")
                .withType(DefaultState.Type.OPERATION)
                .withActionMode(OperationState.ActionMode.SEQUENTIAL)
                .withActions(List.of(sendOrderAction, printMessageAction))
                .withUsedForCompensation(false)
                .withEnd(new End().withTerminate(true).withProduceEvents(List.of()).withCompensate(false))
                .withOnErrors(List.of());

        Functions functions = new Functions();
        functions.setFunctionDefs(List.of(sendOrderFunction, printMessageFunction));
        Errors errors = new Errors();
        errors.setRefValue("specs/errors.yaml");
        // Build Workflow
        return new Workflow()
                .withId("order")
                .withName("Order Workflow")
                .withDescription("Order Workflow Sample")
                .withVersion("1.0")
                .withStart(new Start().withStateName("Order Received"))
                .withExpressionLang("jq")
                .withKeepActive(false)
                .withAutoRetries(false)
                .withFunctions(functions)
                .withErrors(errors)
                .withStates(List.of(orderReceivedState))
                .withExtensions(List.of());
    }
}

Would marshal the functions and errors as:

functions:
  refValue: null
  functionDefs:
    - name: "sendOrder"
      operation: "specs/sendOrderOpenApi.yaml#sendOrder"
      type: "custom"
    - name: "printMessage"
      operation: "specs/printMessage.yaml#printMessage"
      type: "custom"
errors:
  refValue: "specs/errors.yaml"
  errorDefs: null

There's a clear problem with how the marshallers process anyOf attributes within the JSON Schema.

What you expected to happen:

The output should be:

functions:
  - name: "sendOrder"
    operation: "specs/sendOrderOpenApi.yaml#sendOrder"
    type: "custom"
  - name: "printMessage"
    operation: "specs/printMessage.yaml#printMessage"
    type: "custom"
errors:
  - "specs/errors.yaml"

Null objects should also be ignored.

How to reproduce it:

Run the given WorkflowBuilder

Anything else we need to know?:

Whole output of the following builder:

id: "order"
name: "Order Workflow"
description: "Order Workflow Sample"
version: "1.0"
annotations: []
start:
  stateName: "Order Received"
expressionLang: "jq"
keepActive: false
autoRetries: false
functions:
  refValue: null
  functionDefs:
    - name: "sendOrder"
      operation: "specs/sendOrderOpenApi.yaml#sendOrder"
      type: "custom"
    - name: "printMessage"
      operation: "specs/printMessage.yaml#printMessage"
      type: "custom"
errors:
  refValue: "specs/errors.yaml"
  errorDefs: null
states:
  - actionMode: "sequential"
    actions:
      - name: "sendOrder"
        functionRef:
          refName: "sendOrder"
          arguments:
            supplier-id: "1"
            content: ".orderId"
            locator: ".reference"
          invoke: "sync"
        retryRef: "defaultRetry"
        nonRetryableErrors: []
        retryableErrors:
          - "Internal Server error"
          - "Bad Gateway"
          - "Service Unavailable"
          - "Gateway timeout"
          - "Insufficient storage"
          - "Locked"
      - name: "printMessage"
        functionRef:
          refName: "printMessage"
          arguments:
            message: "\"Order received: \" + .orderId"
            locator: ".reference"
          invoke: "sync"
        retryRef: "defaultRetry"
        nonRetryableErrors: []
        retryableErrors:
          - "Internal Server error"
          - "Bad Gateway"
          - "Service Unavailable"
          - "Gateway timeout"
          - "Insufficient storage"
          - "Locked"
    usedForCompensation: false
    name: "Order Received"
    type: "operation"
    end:
      terminate: true
      produceEvents: []
      compensate: false
    onErrors: []
extensions: []

Environment:

  • Specification version used: 0.8

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    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