From 8b59fc59bdaa79046a7bda8e416d4eb803e4f2bf Mon Sep 17 00:00:00 2001 From: nijeeshjoshy Date: Mon, 19 Oct 2026 15:25:26 +0200 Subject: [PATCH] fix(event): keep message_id in additional fields Event.messageId from #278 was a typed Jackson field, so a top-level message_id on message.*, reminder.* and poll.* webhooks moved out of getAdditionalFields() and getAdditionalFields().get("message_id") returned null after upgrading. getMessageId()/setMessageId() now read and write the additional-fields map instead, so parsing and serialization match 1.50.0 and both accessors return the ID on every event. Co-Authored-By: Claude Opus 5.5 --- .../io/getstream/chat/java/models/Event.java | 31 ++++++++++++++++--- .../chat/java/ScheduledMessageTest.java | 18 +++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/getstream/chat/java/models/Event.java b/src/main/java/io/getstream/chat/java/models/Event.java index a09d1612..68abcba0 100644 --- a/src/main/java/io/getstream/chat/java/models/Event.java +++ b/src/main/java/io/getstream/chat/java/models/Event.java @@ -117,12 +117,35 @@ public class Event { @JsonProperty("scheduled_message") private ScheduledMessage scheduledMessage; - /** On scheduled_message.sent, the ID of the message that was sent. */ + @NotNull @JsonIgnore private Map additionalFields = new HashMap<>(); + + /** + * The ID of the message the event is about (on scheduled_message.sent, the message that was + * sent). The backend also sends it on message.*, reminder.* and poll.* events. + * + *

Backed by {@link #getAdditionalFields()} so {@code getAdditionalFields().get("message_id")} + * keeps working for existing events. + */ @Nullable - @JsonProperty("message_id") - private String messageId; + @JsonIgnore + public String getMessageId() { + Object value = this.additionalFields.get("message_id"); + return value == null ? null : value.toString(); + } - @NotNull @JsonIgnore private Map additionalFields = new HashMap<>(); + /** + * Sets the ID of the message the event is about; stored in {@link #getAdditionalFields()}. + * + * @param messageId the message ID, or null to remove it + */ + @JsonIgnore + public void setMessageId(@Nullable String messageId) { + if (messageId == null) { + this.additionalFields.remove("message_id"); + } else { + this.additionalFields.put("message_id", messageId); + } + } @JsonAnyGetter public Map getAdditionalFields() { diff --git a/src/test/java/io/getstream/chat/java/ScheduledMessageTest.java b/src/test/java/io/getstream/chat/java/ScheduledMessageTest.java index 430358a3..f8ae418a 100644 --- a/src/test/java/io/getstream/chat/java/ScheduledMessageTest.java +++ b/src/test/java/io/getstream/chat/java/ScheduledMessageTest.java @@ -180,7 +180,25 @@ void whenEventIsScheduledMessageSent_thenFieldsAreTyped() throws Exception { Event.class); Assertions.assertEquals("m-1", event.getMessageId()); + Assertions.assertEquals("m-1", event.getAdditionalFields().get("message_id")); Assertions.assertEquals("sm-1", event.getScheduledMessage().getId()); Assertions.assertFalse(event.getAdditionalFields().containsKey("scheduled_message")); } + + @DisplayName("message.new events keep message_id in additional fields") + @Test + void whenEventIsMessageNew_thenMessageIdStaysInAdditionalFields() throws Exception { + String json = + "{\"type\":\"message.new\",\"cid\":\"messaging:general\",\"message_id\":\"m-2\"," + + "\"message\":{\"id\":\"m-2\",\"text\":\"hi\"}}"; + Event event = MAPPER.readValue(json, Event.class); + + Assertions.assertEquals("m-2", event.getAdditionalFields().get("message_id")); + Assertions.assertEquals("m-2", event.getMessageId()); + Assertions.assertEquals("m-2", event.getMessage().getId()); + + String out = MAPPER.writeValueAsString(event); + Assertions.assertEquals(1, out.split("\"message_id\"", -1).length - 1, out); + Assertions.assertFalse(out.contains("messageId"), out); + } }