From 070f1c9e4dae947ba21b015ea5027c3d20d170bd Mon Sep 17 00:00:00 2001 From: randgalt Date: Fri, 24 Mar 2017 19:22:48 -0500 Subject: [PATCH 1/8] CURATOR-275 introduced a new field into ServiceInstance. This caused a potential UnrecognizedPropertyException in older clients that read newly serialized ServiceInstances. Added an alternate ctor to JsonInstanceSerializer with a compatibleSerializationMode option. when set to true, the new enabled field of ServiceInstance is not serialized. --- .../x/discovery/ServiceInstanceBuilder.java | 2 + .../details/JsonInstanceSerializer.java | 44 +++- .../discovery/details/OldServiceInstance.java | 196 ++++++++++++++++++ .../discovery/TestJsonInstanceSerializer.java | 136 +++++++----- .../discovery/details/NewServiceInstance.java | 148 +++++++++++++ ...stJsonInstanceSerializerCompatibility.java | 79 +++++++ 6 files changed, 543 insertions(+), 62 deletions(-) create mode 100644 curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/OldServiceInstance.java create mode 100644 curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/NewServiceInstance.java create mode 100644 curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java diff --git a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstanceBuilder.java b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstanceBuilder.java index c2ea40ed5c..0f6a0b7d83 100644 --- a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstanceBuilder.java +++ b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstanceBuilder.java @@ -19,6 +19,7 @@ package org.apache.curator.x.discovery; import com.google.common.collect.Lists; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; @@ -30,6 +31,7 @@ /** * Builder for service instances */ +@JsonIgnoreProperties(ignoreUnknown = true) public class ServiceInstanceBuilder { private T payload; diff --git a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/JsonInstanceSerializer.java b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/JsonInstanceSerializer.java index b7ddbc2efa..983c48dc00 100644 --- a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/JsonInstanceSerializer.java +++ b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/JsonInstanceSerializer.java @@ -16,12 +16,14 @@ * specific language governing permissions and limitations * under the License. */ + package org.apache.curator.x.discovery.details; +import com.google.common.annotations.VisibleForTesting; import org.apache.curator.x.discovery.ServiceInstance; +import org.codehaus.jackson.map.DeserializationConfig; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.type.JavaType; -import java.io.ByteArrayOutputStream; /** * A serializer that uses Jackson to serialize/deserialize as JSON. IMPORTANT: The instance @@ -29,17 +31,42 @@ */ public class JsonInstanceSerializer implements InstanceSerializer { - private final ObjectMapper mapper; - private final Class payloadClass; - private final JavaType type; + private final ObjectMapper mapper; + private final Class payloadClass; + private final boolean compatibleSerializationMode; + private final JavaType type; /** * @param payloadClass used to validate payloads when deserializing */ public JsonInstanceSerializer(Class payloadClass) + { + this(payloadClass, false, false); + } + + /** + * CURATOR-275 introduced a new field into {@link org.apache.curator.x.discovery.ServiceInstance}. This caused a potential + * {@link org.codehaus.jackson.map.exc.UnrecognizedPropertyException} in older clients that + * read newly serialized ServiceInstances. If you are susceptible to this you should set the + * serializer to be an instance of {@link org.apache.curator.x.discovery.details.JsonInstanceSerializer} + * with compatibleSerializationMode set to true. IMPORTANT: when this is done, the new enabled + * field of ServiceInstance is not serialized. + * + * @param payloadClass used to validate payloads when deserializing + * @param compatibleSerializationMode pass true to serialize in a manner that supports clients pre-CURATOR-275 + */ + public JsonInstanceSerializer(Class payloadClass, boolean compatibleSerializationMode) + { + this(payloadClass, compatibleSerializationMode, false); + } + + @VisibleForTesting + JsonInstanceSerializer(Class payloadClass, boolean compatibleSerializationMode, boolean failOnUnknownProperties) { this.payloadClass = payloadClass; + this.compatibleSerializationMode = compatibleSerializationMode; mapper = new ObjectMapper(); + mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, failOnUnknownProperties); type = mapper.getTypeFactory().constructType(ServiceInstance.class); } @@ -55,8 +82,11 @@ public ServiceInstance deserialize(byte[] bytes) throws Exception @Override public byte[] serialize(ServiceInstance instance) throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - mapper.writeValue(out, instance); - return out.toByteArray(); + if ( compatibleSerializationMode ) + { + OldServiceInstance compatible = new OldServiceInstance(instance.getName(), instance.getId(), instance.getAddress(), instance.getPort(), instance.getSslPort(), instance.getPayload(), instance.getRegistrationTimeUTC(), instance.getServiceType(), instance.getUriSpec()); + return mapper.writeValueAsBytes(compatible); + } + return mapper.writeValueAsBytes(instance); } } diff --git a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/OldServiceInstance.java b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/OldServiceInstance.java new file mode 100644 index 0000000000..253b27407e --- /dev/null +++ b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/OldServiceInstance.java @@ -0,0 +1,196 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.curator.x.discovery.details; + +import com.google.common.base.Preconditions; +import org.apache.curator.x.discovery.ServiceType; +import org.apache.curator.x.discovery.UriSpec; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.annotate.JsonTypeInfo.Id; + +/** + * POJO that represents a service instance + */ +class OldServiceInstance +{ + private final String name; + private final String id; + private final String address; + private final Integer port; + private final Integer sslPort; + private final T payload; + private final long registrationTimeUTC; + private final ServiceType serviceType; + private final UriSpec uriSpec; + + /** + * @param name name of the service + * @param id id of this instance (must be unique) + * @param address address of this instance + * @param port the port for this instance or null + * @param sslPort the SSL port for this instance or null + * @param payload the payload for this instance or null + * @param registrationTimeUTC the time (in UTC) of the registration + * @param serviceType type of the service + * @param uriSpec the uri spec or null + */ + OldServiceInstance(String name, String id, String address, Integer port, Integer sslPort, T payload, long registrationTimeUTC, ServiceType serviceType, UriSpec uriSpec) + { + name = Preconditions.checkNotNull(name, "name cannot be null"); + id = Preconditions.checkNotNull(id, "id cannot be null"); + + this.serviceType = serviceType; + this.uriSpec = uriSpec; + this.name = name; + this.id = id; + this.address = address; + this.port = port; + this.sslPort = sslPort; + this.payload = payload; + this.registrationTimeUTC = registrationTimeUTC; + } + + OldServiceInstance() + { + this("", "", null, null, null, null, 0, ServiceType.DYNAMIC, null); + } + + public String getName() + { + return name; + } + + public String getId() + { + return id; + } + + public String getAddress() + { + return address; + } + + public Integer getPort() + { + return port; + } + + public Integer getSslPort() + { + return sslPort; + } + + @JsonTypeInfo(use = Id.CLASS, defaultImpl = Object.class) + public T getPayload() + { + return payload; + } + + public long getRegistrationTimeUTC() + { + return registrationTimeUTC; + } + + public ServiceType getServiceType() + { + return serviceType; + } + + public UriSpec getUriSpec() + { + return uriSpec; + } + + @SuppressWarnings("RedundantIfStatement") + @Override + public boolean equals(Object o) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + + OldServiceInstance that = (OldServiceInstance)o; + + if ( registrationTimeUTC != that.registrationTimeUTC ) + { + return false; + } + if ( address != null ? !address.equals(that.address) : that.address != null ) + { + return false; + } + if ( id != null ? !id.equals(that.id) : that.id != null ) + { + return false; + } + if ( name != null ? !name.equals(that.name) : that.name != null ) + { + return false; + } + if ( payload != null ? !payload.equals(that.payload) : that.payload != null ) + { + return false; + } + if ( port != null ? !port.equals(that.port) : that.port != null ) + { + return false; + } + if ( serviceType != that.serviceType ) + { + return false; + } + if ( sslPort != null ? !sslPort.equals(that.sslPort) : that.sslPort != null ) + { + return false; + } + if ( uriSpec != null ? !uriSpec.equals(that.uriSpec) : that.uriSpec != null ) + { + return false; + } + + return true; + } + + @Override + public int hashCode() + { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + (id != null ? id.hashCode() : 0); + result = 31 * result + (address != null ? address.hashCode() : 0); + result = 31 * result + (port != null ? port.hashCode() : 0); + result = 31 * result + (sslPort != null ? sslPort.hashCode() : 0); + result = 31 * result + (payload != null ? payload.hashCode() : 0); + result = 31 * result + (int)(registrationTimeUTC ^ (registrationTimeUTC >>> 32)); + result = 31 * result + (serviceType != null ? serviceType.hashCode() : 0); + result = 31 * result + (uriSpec != null ? uriSpec.hashCode() : 0); + return result; + } + + @Override + public String toString() + { + return "ServiceInstance{" + "name='" + name + '\'' + ", id='" + id + '\'' + ", address='" + address + '\'' + ", port=" + port + ", sslPort=" + sslPort + ", payload=" + payload + ", registrationTimeUTC=" + registrationTimeUTC + ", serviceType=" + serviceType + ", uriSpec=" + uriSpec + '}'; + } +} diff --git a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java index f17919d33b..ae49dbf747 100644 --- a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java +++ b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java @@ -16,27 +16,27 @@ * specific language governing permissions and limitations * under the License. */ + package org.apache.curator.x.discovery; +import org.apache.curator.x.discovery.details.JsonInstanceSerializer; +import org.testng.Assert; +import org.testng.annotations.Test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.curator.x.discovery.details.JsonInstanceSerializer; -import org.testng.Assert; -import org.testng.annotations.Test; - public class TestJsonInstanceSerializer { @Test - public void testBasic() throws Exception + public void testBasic() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(String.class); - ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, "payload", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true); - byte[] bytes = serializer.serialize(instance); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(String.class); + ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, "payload", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true); + byte[] bytes = serializer.serialize(instance); - ServiceInstance rhs = serializer.deserialize(bytes); + ServiceInstance rhs = serializer.deserialize(bytes); Assert.assertEquals(instance, rhs); Assert.assertEquals(instance.getId(), rhs.getId()); Assert.assertEquals(instance.getName(), rhs.getName()); @@ -49,12 +49,12 @@ public void testBasic() throws Exception } @Test - public void testWrongPayloadType() throws Exception + public void testWrongPayloadType() throws Exception { - JsonInstanceSerializer stringSerializer = new JsonInstanceSerializer(String.class); - JsonInstanceSerializer doubleSerializer = new JsonInstanceSerializer(Double.class); + JsonInstanceSerializer stringSerializer = new JsonInstanceSerializer(String.class); + JsonInstanceSerializer doubleSerializer = new JsonInstanceSerializer(Double.class); - byte[] bytes = stringSerializer.serialize(new ServiceInstance("name", "id", "address", 10, 20, "payload", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true)); + byte[] bytes = stringSerializer.serialize(new ServiceInstance("name", "id", "address", 10, 20, "payload", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true)); try { doubleSerializer.deserialize(bytes); @@ -67,13 +67,13 @@ public void testWrongPayloadType() throws Exception } @Test - public void testNoPayload() throws Exception + public void testNoPayload() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(Void.class); - ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, null, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true); - byte[] bytes = serializer.serialize(instance); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(Void.class); + ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, null, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true); + byte[] bytes = serializer.serialize(instance); - ServiceInstance rhs = serializer.deserialize(bytes); + ServiceInstance rhs = serializer.deserialize(bytes); Assert.assertEquals(instance, rhs); Assert.assertEquals(instance.getId(), rhs.getId()); Assert.assertEquals(instance.getName(), rhs.getName()); @@ -86,26 +86,26 @@ public void testNoPayload() throws Exception } @Test - public void testNoEnabledState() throws Exception + public void testNoEnabledState() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(Void.class); - byte[] bytes = "{}".getBytes("utf-8"); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(Void.class); + byte[] bytes = "{}".getBytes("utf-8"); - ServiceInstance instance = serializer.deserialize(bytes); + ServiceInstance instance = serializer.deserialize(bytes); Assert.assertTrue(instance.isEnabled(), "Instance that has no 'enabled' should be assumed enabled"); } @Test - public void testPayloadAsList() throws Exception + public void testPayloadAsList() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(Object.class); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(Object.class); List payload = new ArrayList(); payload.add("Test value 1"); payload.add("Test value 2"); - ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false); - byte[] bytes = serializer.serialize(instance); + ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false); + byte[] bytes = serializer.serialize(instance); - ServiceInstance rhs = serializer.deserialize(bytes); + ServiceInstance rhs = serializer.deserialize(bytes); Assert.assertEquals(instance, rhs); Assert.assertEquals(instance.getId(), rhs.getId()); Assert.assertEquals(instance.getName(), rhs.getName()); @@ -117,18 +117,17 @@ public void testPayloadAsList() throws Exception Assert.assertEquals(instance.isEnabled(), rhs.isEnabled()); } - @Test - public void testPayloadAsMap() throws Exception + public void testPayloadAsMap() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(Object.class); - Map payload = new HashMap(); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(Object.class); + Map payload = new HashMap(); payload.put("1", "Test value 1"); payload.put("2", "Test value 2"); - ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false); - byte[] bytes = serializer.serialize(instance); + ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false); + byte[] bytes = serializer.serialize(instance); - ServiceInstance rhs = serializer.deserialize(bytes); + ServiceInstance rhs = serializer.deserialize(bytes); Assert.assertEquals(instance, rhs); Assert.assertEquals(instance.getId(), rhs.getId()); Assert.assertEquals(instance.getName(), rhs.getName()); @@ -141,15 +140,15 @@ public void testPayloadAsMap() throws Exception } @Test - public void testPayloadClass() throws Exception + public void testPayloadClass() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(Payload.class); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(Payload.class); Payload payload = new Payload(); payload.setVal("Test value"); - ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true); - byte[] bytes = serializer.serialize(instance); + ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true); + byte[] bytes = serializer.serialize(instance); - ServiceInstance rhs = serializer.deserialize(bytes); + ServiceInstance rhs = serializer.deserialize(bytes); Assert.assertEquals(instance, rhs); Assert.assertEquals(instance.getId(), rhs.getId()); Assert.assertEquals(instance.getName(), rhs.getName()); @@ -161,21 +160,48 @@ public void testPayloadClass() throws Exception Assert.assertEquals(instance.isEnabled(), rhs.isEnabled()); } - public static class Payload { - private String val; - public String getVal() { - return val; - } - public void setVal(String val) { - this.val = val; - } - @Override - public boolean equals(Object other) { - if (other == null || !(other instanceof Payload)) return false; - String otherVal = ((Payload)other).getVal(); - if (val == null) return val == otherVal; - return val.equals(otherVal); - } - } + public static class Payload + { + private String val; + public Payload(String val) + { + this.val = val; + } + + public Payload() + { + } + + public String getVal() + { + return val; + } + + public void setVal(String val) + { + this.val = val; + } + + @Override + public int hashCode() + { + return val != null ? val.hashCode() : 0; + } + + @Override + public boolean equals(Object other) + { + if ( other == null || !(other instanceof Payload) ) + { + return false; + } + String otherVal = ((Payload)other).getVal(); + if ( val == null ) + { + return val.equals(otherVal); + } + return val.equals(otherVal); + } + } } diff --git a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/NewServiceInstance.java b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/NewServiceInstance.java new file mode 100644 index 0000000000..407ce6f664 --- /dev/null +++ b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/NewServiceInstance.java @@ -0,0 +1,148 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.curator.x.discovery.details; + +import com.google.common.base.Preconditions; +import org.apache.curator.x.discovery.ServiceType; +import org.apache.curator.x.discovery.UriSpec; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.annotate.JsonTypeInfo.Id; +import java.net.URI; +import java.util.Date; + +/** + * POJO that represents a service instance + */ +class NewServiceInstance +{ + private final String name; + private final String id; + private final String address; + private final Integer port; + private final Integer sslPort; + private final T payload; + private final long registrationTimeUTC; + private final ServiceType serviceType; + private final UriSpec uriSpec; + private final boolean enabled; + private final String new1; + private final Long new2; + private final Date new3; + private final URI new4; + + public NewServiceInstance(String name, String id, String address, Integer port, Integer sslPort, T payload, long registrationTimeUTC, ServiceType serviceType, UriSpec uriSpec, boolean enabled, String new1, Long new2, Date new3, URI new4) + { + name = Preconditions.checkNotNull(name, "name cannot be null"); + id = Preconditions.checkNotNull(id, "id cannot be null"); + + this.new1 = new1; + this.new2 = new2; + this.new3 = new3; + this.new4 = new4; + this.serviceType = serviceType; + this.uriSpec = uriSpec; + this.name = name; + this.id = id; + this.address = address; + this.port = port; + this.sslPort = sslPort; + this.payload = payload; + this.registrationTimeUTC = registrationTimeUTC; + this.enabled = enabled; + } + + /** + * Inits to default values. Only exists for deserialization + */ + NewServiceInstance() + { + this("", "", null, null, null, null, 0, ServiceType.DYNAMIC, null, true, null, null, null, null); + } + + public String getName() + { + return name; + } + + public String getId() + { + return id; + } + + public String getAddress() + { + return address; + } + + public Integer getPort() + { + return port; + } + + public Integer getSslPort() + { + return sslPort; + } + + @JsonTypeInfo(use = Id.CLASS, defaultImpl = Object.class) + public T getPayload() + { + return payload; + } + + public long getRegistrationTimeUTC() + { + return registrationTimeUTC; + } + + public ServiceType getServiceType() + { + return serviceType; + } + + public UriSpec getUriSpec() + { + return uriSpec; + } + + public boolean isEnabled() + { + return enabled; + } + + public String getNew1() + { + return new1; + } + + public Long getNew2() + { + return new2; + } + + public Date getNew3() + { + return new3; + } + + public URI getNew4() + { + return new4; + } +} diff --git a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java new file mode 100644 index 0000000000..c612a1f600 --- /dev/null +++ b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java @@ -0,0 +1,79 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.curator.x.discovery.details; + +import org.apache.curator.x.discovery.ServiceInstance; +import org.apache.curator.x.discovery.ServiceType; +import org.apache.curator.x.discovery.TestJsonInstanceSerializer; +import org.apache.curator.x.discovery.UriSpec; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.JavaType; +import org.testng.Assert; +import org.testng.annotations.Test; +import java.net.URI; +import java.util.Date; + +public class TestJsonInstanceSerializerCompatibility +{ + @Test + public void testCompatibilityMode() throws Exception + { + JsonInstanceSerializer serializer = new JsonInstanceSerializer(TestJsonInstanceSerializer.Payload.class, true, true); + ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, new TestJsonInstanceSerializer.Payload("test"), 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true); + byte[] bytes = serializer.serialize(instance); + + OldServiceInstance oldInstance = new OldServiceInstance("name", "id", "address", 10, 20, new TestJsonInstanceSerializer.Payload("test"), 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}")); + ObjectMapper mapper = new ObjectMapper(); + byte[] oldBytes = mapper.writeValueAsBytes(oldInstance); + Assert.assertEquals(bytes, oldBytes, String.format("%s vs %s", new String(bytes), new String(oldBytes))); + } + + @Test + public void testBackwardCompatibility() throws Exception + { + JsonInstanceSerializer serializer = new JsonInstanceSerializer(TestJsonInstanceSerializer.Payload.class, true, true); + ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, new TestJsonInstanceSerializer.Payload("test"), 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false); + byte[] bytes = serializer.serialize(instance); + + instance = serializer.deserialize(bytes); + Assert.assertTrue(instance.isEnabled()); // passed false for enabled in the ctor but that is lost with compatibleSerializationMode + + ObjectMapper mapper = new ObjectMapper(); + JavaType type = mapper.getTypeFactory().constructType(OldServiceInstance.class); + OldServiceInstance rawServiceInstance = mapper.readValue(bytes, type); + TestJsonInstanceSerializer.Payload.class.cast(rawServiceInstance.getPayload()); // just to verify that it's the correct type + //noinspection unchecked + OldServiceInstance check = (OldServiceInstance)rawServiceInstance; + Assert.assertEquals(check.getName(), "name"); + Assert.assertEquals(check.getPayload(), new TestJsonInstanceSerializer.Payload("test")); + } + + @Test + public void testFutureChanges() throws Exception + { + NewServiceInstance newInstance = new NewServiceInstance("name", "id", "address", 10, 20, "hey", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false, "what", 10101L, new Date(), new URI("http://hey")); + byte[] newInstanceBytes = new ObjectMapper().writeValueAsBytes(newInstance); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(String.class); + ServiceInstance instance = serializer.deserialize(newInstanceBytes); + Assert.assertEquals(instance.getName(), "name"); + Assert.assertEquals(instance.getPayload(), "hey"); + Assert.assertEquals(instance.isEnabled(), false); + } +} From b6b9e1cc48b4713c1ded50c9d4c60a5071908e61 Mon Sep 17 00:00:00 2001 From: randgalt Date: Fri, 24 Mar 2017 19:26:53 -0500 Subject: [PATCH 2/8] bad commit --- .../org/apache/curator/x/discovery/ServiceInstanceBuilder.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstanceBuilder.java b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstanceBuilder.java index 0f6a0b7d83..c2ea40ed5c 100644 --- a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstanceBuilder.java +++ b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstanceBuilder.java @@ -19,7 +19,6 @@ package org.apache.curator.x.discovery; import com.google.common.collect.Lists; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; @@ -31,7 +30,6 @@ /** * Builder for service instances */ -@JsonIgnoreProperties(ignoreUnknown = true) public class ServiceInstanceBuilder { private T payload; From ee18fd55f71e320050671541c7ed9435f3895a81 Mon Sep 17 00:00:00 2001 From: randgalt Date: Fri, 24 Mar 2017 19:28:11 -0500 Subject: [PATCH 3/8] bad commit --- .../discovery/TestJsonInstanceSerializer.java | 136 +++++++----------- 1 file changed, 55 insertions(+), 81 deletions(-) diff --git a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java index ae49dbf747..f17919d33b 100644 --- a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java +++ b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java @@ -16,27 +16,27 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.curator.x.discovery; -import org.apache.curator.x.discovery.details.JsonInstanceSerializer; -import org.testng.Assert; -import org.testng.annotations.Test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.curator.x.discovery.details.JsonInstanceSerializer; +import org.testng.Assert; +import org.testng.annotations.Test; + public class TestJsonInstanceSerializer { @Test - public void testBasic() throws Exception + public void testBasic() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(String.class); - ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, "payload", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true); - byte[] bytes = serializer.serialize(instance); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(String.class); + ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, "payload", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true); + byte[] bytes = serializer.serialize(instance); - ServiceInstance rhs = serializer.deserialize(bytes); + ServiceInstance rhs = serializer.deserialize(bytes); Assert.assertEquals(instance, rhs); Assert.assertEquals(instance.getId(), rhs.getId()); Assert.assertEquals(instance.getName(), rhs.getName()); @@ -49,12 +49,12 @@ public void testBasic() throws Exception } @Test - public void testWrongPayloadType() throws Exception + public void testWrongPayloadType() throws Exception { - JsonInstanceSerializer stringSerializer = new JsonInstanceSerializer(String.class); - JsonInstanceSerializer doubleSerializer = new JsonInstanceSerializer(Double.class); + JsonInstanceSerializer stringSerializer = new JsonInstanceSerializer(String.class); + JsonInstanceSerializer doubleSerializer = new JsonInstanceSerializer(Double.class); - byte[] bytes = stringSerializer.serialize(new ServiceInstance("name", "id", "address", 10, 20, "payload", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true)); + byte[] bytes = stringSerializer.serialize(new ServiceInstance("name", "id", "address", 10, 20, "payload", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true)); try { doubleSerializer.deserialize(bytes); @@ -67,13 +67,13 @@ public void testWrongPayloadType() throws Exception } @Test - public void testNoPayload() throws Exception + public void testNoPayload() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(Void.class); - ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, null, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true); - byte[] bytes = serializer.serialize(instance); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(Void.class); + ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, null, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true); + byte[] bytes = serializer.serialize(instance); - ServiceInstance rhs = serializer.deserialize(bytes); + ServiceInstance rhs = serializer.deserialize(bytes); Assert.assertEquals(instance, rhs); Assert.assertEquals(instance.getId(), rhs.getId()); Assert.assertEquals(instance.getName(), rhs.getName()); @@ -86,26 +86,26 @@ public void testNoPayload() throws Exception } @Test - public void testNoEnabledState() throws Exception + public void testNoEnabledState() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(Void.class); - byte[] bytes = "{}".getBytes("utf-8"); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(Void.class); + byte[] bytes = "{}".getBytes("utf-8"); - ServiceInstance instance = serializer.deserialize(bytes); + ServiceInstance instance = serializer.deserialize(bytes); Assert.assertTrue(instance.isEnabled(), "Instance that has no 'enabled' should be assumed enabled"); } @Test - public void testPayloadAsList() throws Exception + public void testPayloadAsList() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(Object.class); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(Object.class); List payload = new ArrayList(); payload.add("Test value 1"); payload.add("Test value 2"); - ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false); - byte[] bytes = serializer.serialize(instance); + ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false); + byte[] bytes = serializer.serialize(instance); - ServiceInstance rhs = serializer.deserialize(bytes); + ServiceInstance rhs = serializer.deserialize(bytes); Assert.assertEquals(instance, rhs); Assert.assertEquals(instance.getId(), rhs.getId()); Assert.assertEquals(instance.getName(), rhs.getName()); @@ -117,17 +117,18 @@ public void testPayloadAsList() throws Exception Assert.assertEquals(instance.isEnabled(), rhs.isEnabled()); } + @Test - public void testPayloadAsMap() throws Exception + public void testPayloadAsMap() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(Object.class); - Map payload = new HashMap(); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(Object.class); + Map payload = new HashMap(); payload.put("1", "Test value 1"); payload.put("2", "Test value 2"); - ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false); - byte[] bytes = serializer.serialize(instance); + ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false); + byte[] bytes = serializer.serialize(instance); - ServiceInstance rhs = serializer.deserialize(bytes); + ServiceInstance rhs = serializer.deserialize(bytes); Assert.assertEquals(instance, rhs); Assert.assertEquals(instance.getId(), rhs.getId()); Assert.assertEquals(instance.getName(), rhs.getName()); @@ -140,15 +141,15 @@ public void testPayloadAsMap() throws Exception } @Test - public void testPayloadClass() throws Exception + public void testPayloadClass() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(Payload.class); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(Payload.class); Payload payload = new Payload(); payload.setVal("Test value"); - ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true); - byte[] bytes = serializer.serialize(instance); + ServiceInstance instance = new ServiceInstance("name", "id", "address", 10, 20, payload, 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), true); + byte[] bytes = serializer.serialize(instance); - ServiceInstance rhs = serializer.deserialize(bytes); + ServiceInstance rhs = serializer.deserialize(bytes); Assert.assertEquals(instance, rhs); Assert.assertEquals(instance.getId(), rhs.getId()); Assert.assertEquals(instance.getName(), rhs.getName()); @@ -160,48 +161,21 @@ public void testPayloadClass() throws Exception Assert.assertEquals(instance.isEnabled(), rhs.isEnabled()); } - public static class Payload - { - private String val; - - public Payload(String val) - { - this.val = val; - } - - public Payload() - { - } - - public String getVal() - { - return val; - } - - public void setVal(String val) - { - this.val = val; - } - - @Override - public int hashCode() - { - return val != null ? val.hashCode() : 0; - } - - @Override - public boolean equals(Object other) - { - if ( other == null || !(other instanceof Payload) ) - { - return false; - } - String otherVal = ((Payload)other).getVal(); - if ( val == null ) - { - return val.equals(otherVal); - } - return val.equals(otherVal); - } + public static class Payload { + private String val; + public String getVal() { + return val; + } + public void setVal(String val) { + this.val = val; + } + @Override + public boolean equals(Object other) { + if (other == null || !(other instanceof Payload)) return false; + String otherVal = ((Payload)other).getVal(); + if (val == null) return val == otherVal; + return val.equals(otherVal); + } } + } From 9ac224a3803c6d0ee4ed2081f36871e9d852f75c Mon Sep 17 00:00:00 2001 From: randgalt Date: Fri, 24 Mar 2017 20:04:30 -0500 Subject: [PATCH 4/8] for safety check all the fields --- .../x/discovery/TestJsonInstanceSerializer.java | 12 +++++++++++- .../TestJsonInstanceSerializerCompatibility.java | 11 +++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java index f17919d33b..4b6325d9e3 100644 --- a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java +++ b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java @@ -166,7 +166,17 @@ public static class Payload { public String getVal() { return val; } - public void setVal(String val) { + + public Payload() + { + } + + public Payload(String val) + { + this.val = val; + } + + public void setVal(String val) { this.val = val; } @Override diff --git a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java index c612a1f600..41674b2e78 100644 --- a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java +++ b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java @@ -61,8 +61,15 @@ public void testBackwardCompatibility() throws Exception TestJsonInstanceSerializer.Payload.class.cast(rawServiceInstance.getPayload()); // just to verify that it's the correct type //noinspection unchecked OldServiceInstance check = (OldServiceInstance)rawServiceInstance; - Assert.assertEquals(check.getName(), "name"); - Assert.assertEquals(check.getPayload(), new TestJsonInstanceSerializer.Payload("test")); + Assert.assertEquals(check.getName(), instance.getName()); + Assert.assertEquals(check.getId(), instance.getId()); + Assert.assertEquals(check.getAddress(), instance.getAddress()); + Assert.assertEquals(check.getPort(), instance.getPort()); + Assert.assertEquals(check.getSslPort(), instance.getSslPort()); + Assert.assertEquals(check.getPayload(), instance.getPayload()); + Assert.assertEquals(check.getRegistrationTimeUTC(), instance.getRegistrationTimeUTC()); + Assert.assertEquals(check.getServiceType(), instance.getServiceType()); + Assert.assertEquals(check.getUriSpec(), instance.getUriSpec()); } @Test From a193ce02c37d3ef5a6b9c4a81beffd4d8deba1d0 Mon Sep 17 00:00:00 2001 From: randgalt Date: Sun, 26 Mar 2017 10:23:38 -0500 Subject: [PATCH 5/8] Don't serialize enabled by default. This is the most compatible solution --- .../curator/x/discovery/ServiceInstance.java | 15 +++++++++++++++ .../discovery/details/JsonInstanceSerializer.java | 13 +++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstance.java b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstance.java index ebdd6bc0e5..af2a2c71f7 100644 --- a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstance.java +++ b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstance.java @@ -82,6 +82,12 @@ public ServiceInstance(String name, String id, String address, Integer port, Int } /** + * IMPORTANT: Due to CURATOR-275 the enabled field is NOT supported + * by default. If you wish to use the enabled field, you must set a {@link org.apache.curator.x.discovery.details.InstanceSerializer} + * that serializes this field. The default serializer, {@link org.apache.curator.x.discovery.details.JsonInstanceSerializer} does not + * serialize the field by default. You must use the alternate constructor {@link org.apache.curator.x.discovery.details.JsonInstanceSerializer#JsonInstanceSerializer(Class, boolean)} + * passing false for compatibleSerializationMode. + * * @param name name of the service * @param id id of this instance (must be unique) * @param address address of this instance @@ -164,6 +170,15 @@ public UriSpec getUriSpec() return uriSpec; } + /** + * IMPORTANT: Due to CURATOR-275 the enabled field is NOT supported + * by default. If you wish to use the enabled field, you must set a {@link org.apache.curator.x.discovery.details.InstanceSerializer} + * that serializes this field. The default serializer, {@link org.apache.curator.x.discovery.details.JsonInstanceSerializer} does not + * serialize the field by default. You must use the alternate constructor {@link org.apache.curator.x.discovery.details.JsonInstanceSerializer#JsonInstanceSerializer(Class, boolean)} + * passing false for compatibleSerializationMode. + * + * @return true/false + */ public boolean isEnabled() { return enabled; diff --git a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/JsonInstanceSerializer.java b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/JsonInstanceSerializer.java index 983c48dc00..715ec1d085 100644 --- a/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/JsonInstanceSerializer.java +++ b/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/details/JsonInstanceSerializer.java @@ -37,11 +37,19 @@ public class JsonInstanceSerializer implements InstanceSerializer private final JavaType type; /** + * CURATOR-275 introduced a new field into {@link org.apache.curator.x.discovery.ServiceInstance}. This caused a potential + * {@link org.codehaus.jackson.map.exc.UnrecognizedPropertyException} in older clients that + * read newly serialized ServiceInstances. Therefore the default behavior of JsonInstanceSerializer + * has been changed to NOT serialize the enabled field. If you wish to use that field, use the + * alternate constructor {@link #JsonInstanceSerializer(Class, boolean)} and pass true for + * compatibleSerializationMode. Note: future versions of Curator may change this + * behavior. + * * @param payloadClass used to validate payloads when deserializing */ public JsonInstanceSerializer(Class payloadClass) { - this(payloadClass, false, false); + this(payloadClass, true, false); } /** @@ -50,7 +58,8 @@ public JsonInstanceSerializer(Class payloadClass) * read newly serialized ServiceInstances. If you are susceptible to this you should set the * serializer to be an instance of {@link org.apache.curator.x.discovery.details.JsonInstanceSerializer} * with compatibleSerializationMode set to true. IMPORTANT: when this is done, the new enabled - * field of ServiceInstance is not serialized. + * field of ServiceInstance is not serialized. If however you do want + * to use the enabled field, set compatibleSerializationMode to false. * * @param payloadClass used to validate payloads when deserializing * @param compatibleSerializationMode pass true to serialize in a manner that supports clients pre-CURATOR-275 From 6f3b178fdd6cc6ae914d4eead2ee74e4afbd5ec8 Mon Sep 17 00:00:00 2001 From: randgalt Date: Sun, 26 Mar 2017 10:25:57 -0500 Subject: [PATCH 6/8] updated tests --- .../curator/x/discovery/TestJsonInstanceSerializer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java index 4b6325d9e3..0ed6c3dbd1 100644 --- a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java +++ b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/TestJsonInstanceSerializer.java @@ -98,7 +98,7 @@ public void testNoEnabledState() throws Exception @Test public void testPayloadAsList() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(Object.class); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(Object.class, false); List payload = new ArrayList(); payload.add("Test value 1"); payload.add("Test value 2"); @@ -121,7 +121,7 @@ public void testPayloadAsList() throws Exception @Test public void testPayloadAsMap() throws Exception { - JsonInstanceSerializer serializer = new JsonInstanceSerializer(Object.class); + JsonInstanceSerializer serializer = new JsonInstanceSerializer(Object.class, false); Map payload = new HashMap(); payload.put("1", "Test value 1"); payload.put("2", "Test value 2"); From e7f55f89056f1447cb2ed73a0cdfd66759e11f91 Mon Sep 17 00:00:00 2001 From: randgalt Date: Fri, 31 Mar 2017 13:25:04 -0500 Subject: [PATCH 7/8] rename NewServiceInstance to make it clear it's only for testing --- .../details/TestJsonInstanceSerializerCompatibility.java | 2 +- ...wServiceInstance.java => TestNewServiceInstance.java} | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) rename curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/{NewServiceInstance.java => TestNewServiceInstance.java} (90%) diff --git a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java index 41674b2e78..6ac19c2e3d 100644 --- a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java +++ b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java @@ -75,7 +75,7 @@ public void testBackwardCompatibility() throws Exception @Test public void testFutureChanges() throws Exception { - NewServiceInstance newInstance = new NewServiceInstance("name", "id", "address", 10, 20, "hey", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false, "what", 10101L, new Date(), new URI("http://hey")); + TestNewServiceInstance newInstance = new TestNewServiceInstance("name", "id", "address", 10, 20, "hey", 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}"), false, "what", 10101L, new Date(), new URI("http://hey")); byte[] newInstanceBytes = new ObjectMapper().writeValueAsBytes(newInstance); JsonInstanceSerializer serializer = new JsonInstanceSerializer(String.class); ServiceInstance instance = serializer.deserialize(newInstanceBytes); diff --git a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/NewServiceInstance.java b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestNewServiceInstance.java similarity index 90% rename from curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/NewServiceInstance.java rename to curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestNewServiceInstance.java index 407ce6f664..e627474054 100644 --- a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/NewServiceInstance.java +++ b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestNewServiceInstance.java @@ -26,10 +26,7 @@ import java.net.URI; import java.util.Date; -/** - * POJO that represents a service instance - */ -class NewServiceInstance +class TestNewServiceInstance { private final String name; private final String id; @@ -46,7 +43,7 @@ class NewServiceInstance private final Date new3; private final URI new4; - public NewServiceInstance(String name, String id, String address, Integer port, Integer sslPort, T payload, long registrationTimeUTC, ServiceType serviceType, UriSpec uriSpec, boolean enabled, String new1, Long new2, Date new3, URI new4) + public TestNewServiceInstance(String name, String id, String address, Integer port, Integer sslPort, T payload, long registrationTimeUTC, ServiceType serviceType, UriSpec uriSpec, boolean enabled, String new1, Long new2, Date new3, URI new4) { name = Preconditions.checkNotNull(name, "name cannot be null"); id = Preconditions.checkNotNull(id, "id cannot be null"); @@ -70,7 +67,7 @@ public NewServiceInstance(String name, String id, String address, Integer port, /** * Inits to default values. Only exists for deserialization */ - NewServiceInstance() + TestNewServiceInstance() { this("", "", null, null, null, null, 0, ServiceType.DYNAMIC, null, true, null, null, null, null); } From 3ca02ea7f076d40333d664dd609962d0fe2e4c5f Mon Sep 17 00:00:00 2001 From: randgalt Date: Thu, 18 May 2017 11:39:20 +0200 Subject: [PATCH 8/8] Added testForwardCompatibility --- ...stJsonInstanceSerializerCompatibility.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java index 6ac19c2e3d..6e0e63e9f0 100644 --- a/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java +++ b/curator-x-discovery/src/test/java/org/apache/curator/x/discovery/details/TestJsonInstanceSerializerCompatibility.java @@ -72,6 +72,27 @@ public void testBackwardCompatibility() throws Exception Assert.assertEquals(check.getUriSpec(), instance.getUriSpec()); } + @Test + public void testForwardCompatibility() throws Exception + { + OldServiceInstance oldInstance = new OldServiceInstance("name", "id", "address", 10, 20, new TestJsonInstanceSerializer.Payload("test"), 0, ServiceType.DYNAMIC, new UriSpec("{a}/b/{c}")); + ObjectMapper mapper = new ObjectMapper(); + byte[] oldJson = mapper.writeValueAsBytes(oldInstance); + + JsonInstanceSerializer serializer = new JsonInstanceSerializer(TestJsonInstanceSerializer.Payload.class); + ServiceInstance instance = serializer.deserialize(oldJson); + Assert.assertEquals(oldInstance.getName(), instance.getName()); + Assert.assertEquals(oldInstance.getId(), instance.getId()); + Assert.assertEquals(oldInstance.getAddress(), instance.getAddress()); + Assert.assertEquals(oldInstance.getPort(), instance.getPort()); + Assert.assertEquals(oldInstance.getSslPort(), instance.getSslPort()); + Assert.assertEquals(oldInstance.getPayload(), instance.getPayload()); + Assert.assertEquals(oldInstance.getRegistrationTimeUTC(), instance.getRegistrationTimeUTC()); + Assert.assertEquals(oldInstance.getServiceType(), instance.getServiceType()); + Assert.assertEquals(oldInstance.getUriSpec(), instance.getUriSpec()); + Assert.assertTrue(instance.isEnabled()); + } + @Test public void testFutureChanges() throws Exception {