diff --git a/src/main/java/io/nats/client/support/SerializableConsumerConfiguration.java b/src/main/java/io/nats/client/support/SerializableConsumerConfiguration.java new file mode 100644 index 000000000..beec252c4 --- /dev/null +++ b/src/main/java/io/nats/client/support/SerializableConsumerConfiguration.java @@ -0,0 +1,55 @@ +// Copyright 2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package io.nats.client.support; + +import io.nats.client.api.ConsumerConfiguration; + +import java.io.IOException; +import java.io.Serializable; + +public class SerializableConsumerConfiguration implements Serializable { + private static final long serialVersionUID = 1L; + + private transient ConsumerConfiguration cc; + + public SerializableConsumerConfiguration() { + setConsumerConfiguration(ConsumerConfiguration.builder().build()); + } + + public SerializableConsumerConfiguration(ConsumerConfiguration cc) { + setConsumerConfiguration(cc); + } + + public SerializableConsumerConfiguration(ConsumerConfiguration.Builder builder) { + setConsumerConfiguration(builder.build()); + } + + public void setConsumerConfiguration(ConsumerConfiguration cc) { + this.cc = cc; + } + + public ConsumerConfiguration getConsumerConfiguration() { + return cc; + } + + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeUTF(cc.toJson()); + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + cc = ConsumerConfiguration.builder().json(in.readUTF()).build(); + } +} diff --git a/src/test/java/io/nats/client/api/ConsumerConfigurationTests.java b/src/test/java/io/nats/client/api/ConsumerConfigurationTests.java index 3d5a53c51..e26dadc17 100644 --- a/src/test/java/io/nats/client/api/ConsumerConfigurationTests.java +++ b/src/test/java/io/nats/client/api/ConsumerConfigurationTests.java @@ -14,12 +14,17 @@ package io.nats.client.api; import io.nats.client.support.DateTimeUtils; -import io.nats.client.support.JsonParseException; import io.nats.client.support.JsonParser; import io.nats.client.support.JsonValue; +import io.nats.client.support.SerializableConsumerConfiguration; import io.nats.client.utils.TestBase; import org.junit.jupiter.api.Test; +import java.io.File; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.nio.file.Files; import java.time.Duration; import java.time.ZonedDateTime; import java.util.HashMap; @@ -33,12 +38,12 @@ public class ConsumerConfigurationTests extends TestBase { @Test - public void testBuilder() throws JsonParseException { + public void testBuilder() throws Exception { ZonedDateTime zdt = ZonedDateTime.of(2012, 1, 12, 6, 30, 1, 500, DateTimeUtils.ZONE_ID_GMT); Map metadata = new HashMap<>(); metadata.put("meta-foo", "meta-bar"); - ConsumerConfiguration c = ConsumerConfiguration.builder() + ConsumerConfiguration.Builder builder = ConsumerConfiguration.builder() .ackPolicy(AckPolicy.Explicit) .ackWait(Duration.ofSeconds(99)) // duration .deliverPolicy(DeliverPolicy.ByStartSequence) @@ -65,21 +70,23 @@ public void testBuilder() throws JsonParseException { .headersOnly(true) .memStorage(true) .backoff(1000, 2000, 3000) - .metadata(metadata) - .build(); + .metadata(metadata); + ConsumerConfiguration c = builder.build(); + assertNotNull(c.toString()); // COVERAGE assertAsBuilt(c, zdt); ConsumerCreateRequest ccr = new ConsumerCreateRequest(STREAM, c); + assertNotNull(ccr.toString()); // COVERAGE assertEquals(STREAM, ccr.getStreamName()); - assertNotNull(ccr.getConfig()); assertAsBuilt(ConsumerConfiguration.builder().json(ccr.getConfig().toJson()).build(), zdt); assertAsBuilt(ConsumerConfiguration.builder().jsonValue(ccr.getConfig().toJsonValue()).build(), zdt); - assertNotNull(ccr.toString()); // COVERAGE - assertNotNull(c.toString()); // COVERAGE + SerializableConsumerConfiguration scc = new SerializableConsumerConfiguration(); // COVERAGE + _testSerializing(new SerializableConsumerConfiguration(builder), zdt); + _testSerializing(new SerializableConsumerConfiguration(c), zdt); // flow control idle heartbeat combo c = ConsumerConfiguration.builder() @@ -193,6 +200,17 @@ public void testBuilder() throws JsonParseException { assertClientError(JsConsumerNameDurableMismatch, () -> ConsumerConfiguration.builder().name(NAME).durable(DURABLE).build()); } + private void _testSerializing(SerializableConsumerConfiguration scc, ZonedDateTime zdt) throws IOException, ClassNotFoundException { + File f = File.createTempFile("scc", null); + ObjectOutputStream oos = new ObjectOutputStream(Files.newOutputStream(f.toPath())); + oos.writeObject(scc); + oos.flush(); + oos.close(); + ObjectInputStream ois = new ObjectInputStream(Files.newInputStream(f.toPath())); + scc = (SerializableConsumerConfiguration) ois.readObject(); + assertAsBuilt(scc.getConsumerConfiguration(), zdt); + } + private void validateDefault(ConsumerConfiguration cc) { assertDefaultCc(cc); assertFalse(cc.deliverPolicyWasSet());