Skip to content

Flatten API model: fix circular reference in REST serialization #47

@stalep

Description

@stalep

Problem

The REST API added in #46 exposes a circular reference in the API model:

Node → NodeGroup → List<Node> → NodeGroup → ...

This causes StackOverflow during JSON serialization via Jackson. The current workaround in tests is using asString() to avoid RestAssured's Groovy JSON parser triggering the cycle.

The root cause is that the API records mirror the entity graph's bidirectional relationships:

record Node(..., NodeGroup group, ..., List<Node> sources)
record NodeGroup(..., Node root, List<Node> sources)
record Value(..., Node node, ...)  // affected via Node → NodeGroup cycle

Note: Folder is already flat, getGroupedValues() returns List<JsonNode>, and create() returns Long — these have no circular reference issues.

Proposed solution

Introduce flat REST DTOs with ID-based references instead of nested objects:

record NodeDto(Long id, String name, String fqdn, NodeType type, Long groupId, String operation, List<Long> sourceIds)
record NodeGroupDto(Long id, String name, Long rootId, List<Long> sourceIds)
record ValueDto(Long id, JsonNode data, Long nodeId, Long folderId, int idx)

Move JAX-RS annotations from service interfaces to dedicated REST resource classes (NodeResource, FolderResource, etc.) that wrap the services and map to DTOs. This keeps service interfaces and CLI code unchanged.

Why DTOs over Jackson annotations?

  • @JsonIdentityInfo on records produces mixed JSON (first ref = full object, subsequent = bare ID) — hostile to frontend consumers
  • @JsonBackReference is already on entities but cycle occurs in API records after MapStruct mapping
  • @JsonView could exclude fields but then REST responses lack the relationship entirely
  • Flat DTOs with groupId/sourceIds give clients the relationship without the cycle

Acceptance criteria

  • REST endpoints return flat DTOs (no nested object references)
  • OpenAPI spec has clean, non-recursive schemas
  • No asString() workarounds needed in REST tests
  • Service interfaces unchanged — CLI functionality unaffected
  • All existing tests pass

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions