From 4304d89fbd7bcde460465d21a45a286d44c5e177 Mon Sep 17 00:00:00 2001 From: Nicolas Echegut Date: Thu, 2 Jul 2026 17:07:57 +0100 Subject: [PATCH 1/2] fix(gcs): use snake_case field names in notification request and response --- .../java/io/floci/gcp/services/gcs/GcsService.java | 14 +++++++------- .../gcp/services/gcs/model/StoredNotification.java | 5 +++++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/floci/gcp/services/gcs/GcsService.java b/src/main/java/io/floci/gcp/services/gcs/GcsService.java index 15f9483..37a26ea 100644 --- a/src/main/java/io/floci/gcp/services/gcs/GcsService.java +++ b/src/main/java/io/floci/gcp/services/gcs/GcsService.java @@ -758,16 +758,16 @@ public StoredNotification createNotification(String bucket, Map StoredNotification notif = new StoredNotification(); notif.setId(id); notif.setTopic((String) body.get("topic")); - String fmt = (String) body.get("payloadFormat"); + String fmt = (String) body.get("payload_format"); if (fmt != null) notif.setPayloadFormat(fmt); - if (body.containsKey("eventTypes")) { - notif.setEventTypes((List) body.get("eventTypes")); + if (body.containsKey("event_types")) { + notif.setEventTypes((List) body.get("event_types")); } - if (body.containsKey("customAttributes")) { - notif.setCustomAttributes((Map) body.get("customAttributes")); + if (body.containsKey("custom_attributes")) { + notif.setCustomAttributes((Map) body.get("custom_attributes")); } - if (body.containsKey("objectNamePrefix")) { - notif.setObjectNamePrefix((String) body.get("objectNamePrefix")); + if (body.containsKey("object_name_prefix")) { + notif.setObjectNamePrefix((String) body.get("object_name_prefix")); } notif.setSelfLink(config != null ? config.baseUrl() + "/storage/v1/b/" + bucket + "/notificationConfigs/" + id diff --git a/src/main/java/io/floci/gcp/services/gcs/model/StoredNotification.java b/src/main/java/io/floci/gcp/services/gcs/model/StoredNotification.java index bfe90ac..c28180c 100644 --- a/src/main/java/io/floci/gcp/services/gcs/model/StoredNotification.java +++ b/src/main/java/io/floci/gcp/services/gcs/model/StoredNotification.java @@ -1,6 +1,7 @@ package io.floci.gcp.services.gcs.model; import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; import io.quarkus.runtime.annotations.RegisterForReflection; import java.util.List; @@ -14,9 +15,13 @@ public class StoredNotification { private String id; private String selfLink; private String topic; + @JsonProperty("payload_format") private String payloadFormat = "JSON_API_V1"; + @JsonProperty("event_types") private List eventTypes; + @JsonProperty("custom_attributes") private Map customAttributes; + @JsonProperty("object_name_prefix") private String objectNamePrefix; public String getKind() { return kind; } From 51b42006f5e4d511fa403a4c2c9a5030e73413f3 Mon Sep 17 00:00:00 2001 From: Nicolas Echegut Date: Wed, 15 Jul 2026 11:29:27 +0100 Subject: [PATCH 2/2] test: Add round-trip assertions for all notification fields --- .../floci/gcp/test/GcsNotificationTest.java | 39 +++++++++++++------ .../gcs/model/StoredNotification.java | 5 +++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/compatibility-tests/sdk-test-java/src/test/java/io/floci/gcp/test/GcsNotificationTest.java b/compatibility-tests/sdk-test-java/src/test/java/io/floci/gcp/test/GcsNotificationTest.java index 21986d8..351626d 100644 --- a/compatibility-tests/sdk-test-java/src/test/java/io/floci/gcp/test/GcsNotificationTest.java +++ b/compatibility-tests/sdk-test-java/src/test/java/io/floci/gcp/test/GcsNotificationTest.java @@ -37,6 +37,7 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; @@ -57,7 +58,7 @@ class GcsNotificationTest { private static TopicAdminClient topicAdminClient; private static SubscriptionAdminClient subscriptionAdminClient; - private static String notificationId; + private static Notification createdNotification; @BeforeAll static void setUp() throws IOException { @@ -121,13 +122,21 @@ void createBucketAndNotification() { .setEventTypes(NotificationInfo.EventType.OBJECT_FINALIZE, NotificationInfo.EventType.OBJECT_DELETE) .setPayloadFormat(NotificationInfo.PayloadFormat.JSON_API_V1) + .setCustomAttributes(Map.of("env", "test")) + .setObjectNamePrefix("notification/") .build(); - Notification notification = storage.createNotification(BUCKET_NAME, notifInfo); - assertThat(notification).isNotNull(); - assertThat(notification.getTopic()).isEqualTo(topicName); - notificationId = notification.getNotificationId(); - assertThat(notificationId).isNotBlank(); + createdNotification = storage.createNotification(BUCKET_NAME, notifInfo); + assertThat(createdNotification).isNotNull(); + assertThat(createdNotification.getTopic()).isEqualTo(topicName); + assertThat(createdNotification.getNotificationId()).isNotBlank(); + assertThat(createdNotification.getPayloadFormat()).isEqualTo(NotificationInfo.PayloadFormat.JSON_API_V1); + assertThat(createdNotification.getEventTypes()) + .containsExactlyInAnyOrder(NotificationInfo.EventType.OBJECT_FINALIZE, + NotificationInfo.EventType.OBJECT_DELETE); + assertThat(createdNotification.getCustomAttributes()) + .containsEntry("env", "test"); + assertThat(createdNotification.getObjectNamePrefix()).isEqualTo("notification/"); } @Test @@ -135,15 +144,23 @@ void createBucketAndNotification() { void listNotificationsReturnCreated() { List notifications = storage.listNotifications(BUCKET_NAME); assertThat(notifications).isNotEmpty(); - assertThat(notifications.stream().anyMatch(n -> notificationId.equals(n.getNotificationId()))).isTrue(); + assertThat(notifications.stream() + .anyMatch(n -> createdNotification.getNotificationId().equals(n.getNotificationId()))) + .isTrue(); } @Test @Order(4) void getNotificationById() { - Notification notification = storage.getNotification(BUCKET_NAME, notificationId); + Notification notification = storage.getNotification(BUCKET_NAME, createdNotification.getNotificationId()); assertThat(notification).isNotNull(); - assertThat(notification.getNotificationId()).isEqualTo(notificationId); + assertThat(notification.getNotificationId()).isEqualTo(createdNotification.getNotificationId()); + assertThat(notification.getTopic()).isEqualTo(createdNotification.getTopic()); + assertThat(notification.getPayloadFormat()).isEqualTo(createdNotification.getPayloadFormat()); + assertThat(notification.getEventTypes()) + .containsExactlyInAnyOrderElementsOf(createdNotification.getEventTypes()); + assertThat(notification.getCustomAttributes()).isEqualTo(createdNotification.getCustomAttributes()); + assertThat(notification.getObjectNamePrefix()).isEqualTo(createdNotification.getObjectNamePrefix()); } @Test @@ -222,11 +239,11 @@ void deleteObjectTriggersNotification() throws IOException { @Test @Order(7) void deleteNotificationConfig() { - storage.deleteNotification(BUCKET_NAME, notificationId); + storage.deleteNotification(BUCKET_NAME, createdNotification.getNotificationId()); List remaining = storage.listNotifications(BUCKET_NAME); boolean stillPresent = remaining.stream() - .anyMatch(n -> notificationId.equals(n.getNotificationId())); + .anyMatch(n -> createdNotification.getNotificationId().equals(n.getNotificationId())); assertThat(stillPresent).isFalse(); } } diff --git a/src/main/java/io/floci/gcp/services/gcs/model/StoredNotification.java b/src/main/java/io/floci/gcp/services/gcs/model/StoredNotification.java index c28180c..0e6b244 100644 --- a/src/main/java/io/floci/gcp/services/gcs/model/StoredNotification.java +++ b/src/main/java/io/floci/gcp/services/gcs/model/StoredNotification.java @@ -1,5 +1,6 @@ package io.floci.gcp.services.gcs.model; +import com.fasterxml.jackson.annotation.JsonAlias; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import io.quarkus.runtime.annotations.RegisterForReflection; @@ -16,12 +17,16 @@ public class StoredNotification { private String selfLink; private String topic; @JsonProperty("payload_format") + @JsonAlias("payloadFormat") private String payloadFormat = "JSON_API_V1"; @JsonProperty("event_types") + @JsonAlias("eventTypes") private List eventTypes; @JsonProperty("custom_attributes") + @JsonAlias("customAttributes") private Map customAttributes; @JsonProperty("object_name_prefix") + @JsonAlias("objectNamePrefix") private String objectNamePrefix; public String getKind() { return kind; }