Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ricardozanini opened this issue May 30, 2025 · 0 comments
Assignees
Labels

Comments

@ricardozanini
Copy link
Member

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant