From 10059db7eb565f5a78e4e6b84bedefe22e098cae Mon Sep 17 00:00:00 2001 From: Ryan Senior Date: Tue, 24 Oct 2023 08:31:18 -0500 Subject: [PATCH 1/2] Support StreamConfiguration creation from JSON This commit adds a public method to StreamConfiguration that allows hydrating a StreamConfiguration via a JSON String. Previously this was only package scoped and used in tests. --- .../nats/client/api/StreamConfiguration.java | 20 ++++- .../client/api/StreamConfigurationTests.java | 86 +++++++++++++++++++ 2 files changed, 102 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/nats/client/api/StreamConfiguration.java b/src/main/java/io/nats/client/api/StreamConfiguration.java index 2273705b4..8dc4194b7 100644 --- a/src/main/java/io/nats/client/api/StreamConfiguration.java +++ b/src/main/java/io/nats/client/api/StreamConfiguration.java @@ -13,9 +13,7 @@ package io.nats.client.api; -import io.nats.client.support.JsonSerializable; -import io.nats.client.support.JsonUtils; -import io.nats.client.support.JsonValue; +import io.nats.client.support.*; import java.time.Duration; import java.util.*; @@ -143,9 +141,23 @@ static StreamConfiguration instance(JsonValue v) { this.firstSequence = b.firstSequence; } + /** + * Returns a StreamConfiguration deserialized from its JSON form. + * + * @see #toJson() + * @param json + * @return StreamConfiguration for the given json + * @throws JsonParseException + */ + public static StreamConfiguration instance(String json) throws JsonParseException { + JsonValue parsedJson = JsonParser.parse(json); + return instance(parsedJson); + } + /** * Returns a JSON representation of this consumer configuration. - * + * + * @see #instance(String) * @return json consumer configuration to send to the server. */ public String toJson() { diff --git a/src/test/java/io/nats/client/api/StreamConfigurationTests.java b/src/test/java/io/nats/client/api/StreamConfigurationTests.java index 3ba87547c..d912c6bfb 100644 --- a/src/test/java/io/nats/client/api/StreamConfigurationTests.java +++ b/src/test/java/io/nats/client/api/StreamConfigurationTests.java @@ -22,6 +22,7 @@ import io.nats.client.utils.ResourceUtils; import nl.jqno.equalsverifier.EqualsVerifier; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.function.Executable; import java.time.Duration; import java.time.ZonedDateTime; @@ -30,6 +31,10 @@ import static io.nats.client.api.CompressionOption.None; import static io.nats.client.api.CompressionOption.S2; import static io.nats.client.api.ConsumerConfiguration.*; +import static io.nats.client.support.ApiConstants.*; +import static io.nats.client.support.ApiConstants.FIRST_SEQ; +import static io.nats.client.support.JsonValueUtils.*; +import static io.nats.client.support.JsonValueUtils.readLong; import static org.junit.jupiter.api.Assertions.*; public class StreamConfigurationTests extends JetStreamTestBase { @@ -61,6 +66,87 @@ public void testRoundTrip() throws Exception { }); } + @Test + public void testSerializationDeserialization() throws Exception { + String originalJson = ResourceUtils.dataAsString("StreamConfiguration.json"); + StreamConfiguration sc = StreamConfiguration.instance(originalJson); + validate(sc, false); + String serializedJson = sc.toJson(); + validate(StreamConfiguration.instance(serializedJson), false); + } + + @Test + public void testSerializationDeserializationDefaults() throws Exception { + StreamConfiguration sc = StreamConfiguration.instance(""); + assertNotNull(sc); + String serializedJson = sc.toJson(); + assertNotNull(StreamConfiguration.instance(serializedJson)); + } + + @Test + public void testMissingJsonFields() throws Exception{ + List streamConfigFields = new ArrayList(){ + { + add(RETENTION); + add(COMPRESSION); + add(STORAGE); + add(DISCARD); + add(NAME); + add(DESCRIPTION); + add(MAX_CONSUMERS); + add(MAX_MSGS); + add(MAX_MSGS_PER_SUB); + add(MAX_BYTES); + add(MAX_AGE); + add(MAX_MSG_SIZE); + add(NUM_REPLICAS); + add(NO_ACK); + add(TEMPLATE_OWNER); + add(DUPLICATE_WINDOW); + add(SUBJECTS); + add(PLACEMENT); + add(REPUBLISH); + add(SUBJECT_TRANSFORM); + add(CONSUMER_LIMITS); + add(MIRROR); + add(SOURCES); + add(SEALED); + add(ALLOW_ROLLUP_HDRS); + add(ALLOW_DIRECT); + add(MIRROR_DIRECT); + add(DENY_DELETE); + add(DENY_PURGE); + add(DISCARD_NEW_PER_SUBJECT); + add(METADATA); + add(FIRST_SEQ); + } + }; + + String originalJson = ResourceUtils.dataAsString("StreamConfiguration.json"); + + + for (String streamConfigFieldName: streamConfigFields) { + JsonValue originalParsedJson = JsonParser.parse(originalJson); + originalParsedJson.map.remove(streamConfigFieldName); + StreamConfiguration sc = StreamConfiguration.instance(originalParsedJson.toJson()); + assertNotNull(sc); + } + } + + @Test + public void testInvalidNameInJson() throws Exception{ + String originalJson = ResourceUtils.dataAsString("StreamConfiguration.json"); + JsonValue originalParsedJson = JsonParser.parse(originalJson); + originalParsedJson.map.put(NAME, new JsonValue("Inavlid*Name")); + assertThrows(IllegalArgumentException.class, + new Executable() { + @Override + public void execute() throws Throwable { + StreamConfiguration.instance(originalParsedJson.toJson()); + } + }); + } + @Test public void testConstruction() { StreamConfiguration testSc = getTestConfiguration(); From 0cf662dee7b277c40522000f60c0a99300d2c81e Mon Sep 17 00:00:00 2001 From: Ryan Senior Date: Tue, 24 Oct 2023 10:29:47 -0500 Subject: [PATCH 2/2] Minor changes after PR feedback --- .../java/io/nats/client/api/StreamConfiguration.java | 4 +--- .../io/nats/client/api/StreamConfigurationTests.java | 11 +++-------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/main/java/io/nats/client/api/StreamConfiguration.java b/src/main/java/io/nats/client/api/StreamConfiguration.java index 8dc4194b7..154202af3 100644 --- a/src/main/java/io/nats/client/api/StreamConfiguration.java +++ b/src/main/java/io/nats/client/api/StreamConfiguration.java @@ -150,14 +150,12 @@ static StreamConfiguration instance(JsonValue v) { * @throws JsonParseException */ public static StreamConfiguration instance(String json) throws JsonParseException { - JsonValue parsedJson = JsonParser.parse(json); - return instance(parsedJson); + return instance(JsonParser.parse(json)); } /** * Returns a JSON representation of this consumer configuration. * - * @see #instance(String) * @return json consumer configuration to send to the server. */ public String toJson() { diff --git a/src/test/java/io/nats/client/api/StreamConfigurationTests.java b/src/test/java/io/nats/client/api/StreamConfigurationTests.java index d912c6bfb..d13a4a464 100644 --- a/src/test/java/io/nats/client/api/StreamConfigurationTests.java +++ b/src/test/java/io/nats/client/api/StreamConfigurationTests.java @@ -124,7 +124,8 @@ public void testMissingJsonFields() throws Exception{ String originalJson = ResourceUtils.dataAsString("StreamConfiguration.json"); - + // Loops through each field in the StreamConfiguration JSON format and ensures that the + // StreamConfiguration can be built without that field being present in the JSON for (String streamConfigFieldName: streamConfigFields) { JsonValue originalParsedJson = JsonParser.parse(originalJson); originalParsedJson.map.remove(streamConfigFieldName); @@ -138,13 +139,7 @@ public void testInvalidNameInJson() throws Exception{ String originalJson = ResourceUtils.dataAsString("StreamConfiguration.json"); JsonValue originalParsedJson = JsonParser.parse(originalJson); originalParsedJson.map.put(NAME, new JsonValue("Inavlid*Name")); - assertThrows(IllegalArgumentException.class, - new Executable() { - @Override - public void execute() throws Throwable { - StreamConfiguration.instance(originalParsedJson.toJson()); - } - }); + assertThrows(IllegalArgumentException.class, () -> StreamConfiguration.instance(originalParsedJson.toJson())); } @Test