|
2 | 2 | // Licensed under the MIT License. |
3 | 3 | package com.microsoft.durabletask; |
4 | 4 |
|
| 5 | +import com.fasterxml.jackson.databind.JsonNode; |
| 6 | +import com.fasterxml.jackson.databind.ObjectMapper; |
5 | 7 | import org.junit.jupiter.api.Test; |
6 | 8 |
|
7 | 9 | import java.time.Instant; |
@@ -108,4 +110,63 @@ void readStateAs_stillWorksOnTypedInstance() { |
108 | 110 | Integer state = typed.readStateAs(Integer.class); |
109 | 111 | assertEquals(42, state); |
110 | 112 | } |
| 113 | + |
| 114 | + // region Jackson serialization tests |
| 115 | + |
| 116 | + @Test |
| 117 | + void jacksonSerialization_typedEntityMetadata_hidesInternalFields() throws Exception { |
| 118 | + Instant now = Instant.parse("2026-01-15T10:30:00Z"); |
| 119 | + EntityMetadata base = new EntityMetadata( |
| 120 | + "@counter@myKey", now, 3, "orch-lock-123", "42", true, dataConverter); |
| 121 | + |
| 122 | + TypedEntityMetadata<Integer> typed = new TypedEntityMetadata<>(base, Integer.class); |
| 123 | + |
| 124 | + ObjectMapper mapper = new ObjectMapper(); |
| 125 | + mapper.findAndRegisterModules(); |
| 126 | + String json = mapper.writeValueAsString(typed); |
| 127 | + JsonNode root = mapper.readTree(json); |
| 128 | + |
| 129 | + // Should include public API fields |
| 130 | + assertTrue(root.has("entityId"), "Should have entityId field"); |
| 131 | + assertTrue(root.has("lastModifiedTime"), "Should have lastModifiedTime field"); |
| 132 | + assertTrue(root.has("backlogQueueSize"), "Should have backlogQueueSize field"); |
| 133 | + assertTrue(root.has("lockedBy"), "Should have lockedBy field"); |
| 134 | + assertTrue(root.has("includesState"), "Should have includesState field"); |
| 135 | + assertTrue(root.has("state"), "Should have state field"); |
| 136 | + |
| 137 | + // Should NOT include internal fields |
| 138 | + assertFalse(root.has("serializedState"), "Should not expose serializedState"); |
| 139 | + assertFalse(root.has("dataConverter"), "Should not expose dataConverter"); |
| 140 | + assertFalse(root.has("stateType"), "Should not expose stateType"); |
| 141 | + assertFalse(root.has("instanceId"), "Should not expose raw instanceId (use entityId instead)"); |
| 142 | + |
| 143 | + // Verify field values |
| 144 | + assertEquals("@counter@myKey", root.get("entityId").asText()); |
| 145 | + assertEquals(3, root.get("backlogQueueSize").asInt()); |
| 146 | + assertEquals("orch-lock-123", root.get("lockedBy").asText()); |
| 147 | + assertTrue(root.get("includesState").asBoolean()); |
| 148 | + assertEquals(42, root.get("state").asInt()); |
| 149 | + } |
| 150 | + |
| 151 | + @Test |
| 152 | + void jacksonSerialization_entityMetadata_hidesInternalFields() throws Exception { |
| 153 | + EntityMetadata base = new EntityMetadata( |
| 154 | + "@counter@c1", Instant.EPOCH, 0, null, "99", true, dataConverter); |
| 155 | + |
| 156 | + ObjectMapper mapper = new ObjectMapper(); |
| 157 | + mapper.findAndRegisterModules(); |
| 158 | + String json = mapper.writeValueAsString(base); |
| 159 | + JsonNode root = mapper.readTree(json); |
| 160 | + |
| 161 | + // Should include public API fields |
| 162 | + assertTrue(root.has("entityId"), "Should have entityId field"); |
| 163 | + assertTrue(root.has("lastModifiedTime"), "Should have lastModifiedTime field"); |
| 164 | + |
| 165 | + // Should NOT include internal fields |
| 166 | + assertFalse(root.has("serializedState"), "Should not expose serializedState"); |
| 167 | + assertFalse(root.has("dataConverter"), "Should not expose dataConverter"); |
| 168 | + assertFalse(root.has("instanceId"), "Should not expose raw instanceId"); |
| 169 | + } |
| 170 | + |
| 171 | + // endregion |
111 | 172 | } |
0 commit comments