Skip to content

UNOMI-952: Return HTTP 400 for malformed Item JSON in REST requests#777

Merged
sergehuber merged 4 commits into
masterfrom
UNOMI-952-rest-bad-payload-400
Jun 21, 2026
Merged

UNOMI-952: Return HTTP 400 for malformed Item JSON in REST requests#777
sergehuber merged 4 commits into
masterfrom
UNOMI-952-rest-bad-payload-400

Conversation

@sergehuber

Copy link
Copy Markdown
Contributor

Summary

  • Harden ItemDeserializer to reject non-object or incomplete Item JSON (itemType / itemId required) with JsonMappingException instead of ClassCastException / NPE.
  • Map wrapped JSON deserialization failures in RuntimeExceptionMapper to HTTP 400 (badRequest JSON), completing the UNOMI-928 error-handling work for malformed REST payloads.
  • Add ItemDeserializerTest coverage including registered type mappings.

JIRA

  • UNOMI-952 (primary)
  • Related: UNOMI-933, UNOMI-945, UNOMI-928

Test plan

  • mvn -pl persistence-spi test -Dtest=ItemDeserializerTest
  • mvn -pl rest test -Dtest=RestExceptionMapperTest,LogSanitizerTest
  • Manual: POST context/event payload with malformed source/target Item (e.g. {}, string) → HTTP 400 JSON {"errorMessage":"badRequest"}

Harden ItemDeserializer to reject non-object or incomplete Item payloads with JsonMappingException, and map wrapped JSON deserialization failures to 400 instead of 500.
… handling.

- Use ConcurrentHashMap for thread-safe OSGi registration/deregistration
- Override getNullValue() to reject null Item tokens with JsonMappingException
- Guard treeToValue() result against null to avoid silent NPE -> 500
- RuntimeExceptionMapper now returns 400 for JsonParseException root causes
- Restore WARN/ERROR rationale comment; update RestExceptionMapperTest Javadoc
- Expand ItemDeserializerTest: customItemType assertion, array-root rejection,
  numeric itemType/itemId rejection, unregisterMapping fallback coverage
- Use textValue() consistently for itemIdNode (matches itemTypeNode pattern)
- describeJsonNode fallback now produces "a number/boolean/..." for grammar consistency
- Add comment explaining why itemType is stripped only for registered types
- Add boolean-root test to cover describeJsonNode fallback branch
- Add cycle-guard comment in getRootCause() explaining it is unreachable in practice
- Add MAX_MESSAGE_LENGTH cap to LogSanitizer.forLogging() to prevent log amplification
The test asserted executionCount==1 after awaiting a latch, but the task
runs at a 100ms fixed rate. On a loaded CI runner the second tick could
fire between the latch release and the assertEquals, causing a spurious
failure. Move preDestroy() before the assertion so the scheduler is fully
stopped before we read the counter.
@sergehuber sergehuber merged commit 85fa6f2 into master Jun 21, 2026
12 of 15 checks passed
@sergehuber sergehuber deleted the UNOMI-952-rest-bad-payload-400 branch June 21, 2026 19:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant