From a0fea8ffc5997e20b453a11d7894010310ac19a4 Mon Sep 17 00:00:00 2001 From: David Turanski Date: Tue, 3 Dec 2019 16:25:48 -0500 Subject: [PATCH] Replace ZonedDateTime with valid String representation Signed-off-by: David Turanski --- api/pom.xml | 7 +++ .../main/java/io/cloudevents/json/Json.java | 2 - .../json/ZonedDateTimeDeserializer.java | 47 ------------------- .../json/ZonedDateTimeSerializer.java | 46 ------------------ .../io/cloudevents/v02/AttributesImpl.java | 25 +++++----- .../io/cloudevents/v02/CloudEventBuilder.java | 1 + .../io/cloudevents/v02/CloudEventImpl.java | 7 +-- .../io/cloudevents/v03/AttributesImpl.java | 46 +++++++++--------- .../io/cloudevents/v03/CloudEventImpl.java | 4 +- .../io/cloudevents/v1/AttributesImpl.java | 40 ++++++++-------- .../io/cloudevents/v1/CloudEventBuilder.java | 5 +- .../io/cloudevents/v1/CloudEventImpl.java | 7 +-- .../v02/CloudEventJacksonTest.java | 6 +++ .../cloudevents/v1/CloudEventJacksonTest.java | 5 -- 14 files changed, 85 insertions(+), 163 deletions(-) delete mode 100644 api/src/main/java/io/cloudevents/json/ZonedDateTimeDeserializer.java delete mode 100644 api/src/main/java/io/cloudevents/json/ZonedDateTimeSerializer.java diff --git a/api/pom.xml b/api/pom.xml index a6da5f127..d54a892f1 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -73,6 +73,12 @@ 3.10.0 test + + com.google.code.gson + gson + ${gson.version} + test + @@ -80,6 +86,7 @@ 2.10.1 6.0.17.Final 3.0.3 + 2.8.6 diff --git a/api/src/main/java/io/cloudevents/json/Json.java b/api/src/main/java/io/cloudevents/json/Json.java index a0aae898a..f5b08c8bb 100644 --- a/api/src/main/java/io/cloudevents/json/Json.java +++ b/api/src/main/java/io/cloudevents/json/Json.java @@ -39,8 +39,6 @@ public final class Json { MAPPER.registerModule(new Jdk8Module()); final SimpleModule module = new SimpleModule(); - module.addSerializer(ZonedDateTime.class, new ZonedDateTimeSerializer()); - module.addDeserializer(ZonedDateTime.class, new ZonedDateTimeDeserializer()); MAPPER.registerModule(module); } diff --git a/api/src/main/java/io/cloudevents/json/ZonedDateTimeDeserializer.java b/api/src/main/java/io/cloudevents/json/ZonedDateTimeDeserializer.java deleted file mode 100644 index aec2fe55c..000000000 --- a/api/src/main/java/io/cloudevents/json/ZonedDateTimeDeserializer.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright 2018 The CloudEvents 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.cloudevents.json; - -import java.io.IOException; -import java.time.DateTimeException; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; - -public class ZonedDateTimeDeserializer extends StdDeserializer { - private static final long serialVersionUID = 1L; - - public ZonedDateTimeDeserializer() { - this(null); - } - - public ZonedDateTimeDeserializer(Class vc) { - super(vc); - } - - @Override - public ZonedDateTime deserialize(JsonParser jsonparser, DeserializationContext ctxt) throws IOException { - // not serializing timezone data yet - try { - return ZonedDateTime.parse(jsonparser.getText(), DateTimeFormatter.ISO_OFFSET_DATE_TIME); - } catch (DateTimeException e) { - throw new IllegalArgumentException("could not parse"); - } - } -} diff --git a/api/src/main/java/io/cloudevents/json/ZonedDateTimeSerializer.java b/api/src/main/java/io/cloudevents/json/ZonedDateTimeSerializer.java deleted file mode 100644 index 484e0473d..000000000 --- a/api/src/main/java/io/cloudevents/json/ZonedDateTimeSerializer.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright 2018 The CloudEvents 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.cloudevents.json; - -import java.io.IOException; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; - -public class ZonedDateTimeSerializer extends StdSerializer { - - private static final long serialVersionUID = 6245182835980474796L; - - public ZonedDateTimeSerializer() { - this(null, false); - } - - protected ZonedDateTimeSerializer(Class t, boolean dummy) { - super(t, dummy); - } - - @Override - public void serialize(ZonedDateTime time, JsonGenerator generator, - SerializerProvider provider) throws IOException { - - generator.writeString(time.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); - - } - -} diff --git a/api/src/main/java/io/cloudevents/v02/AttributesImpl.java b/api/src/main/java/io/cloudevents/v02/AttributesImpl.java index d4ecff74c..0d3747353 100644 --- a/api/src/main/java/io/cloudevents/v02/AttributesImpl.java +++ b/api/src/main/java/io/cloudevents/v02/AttributesImpl.java @@ -33,14 +33,13 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import io.cloudevents.Attributes; -import io.cloudevents.json.ZonedDateTimeDeserializer; /** * * @author fabiojose + * @author dturanski * @version 0.2 */ @JsonInclude(value = Include.NON_ABSENT) @@ -58,10 +57,11 @@ public class AttributesImpl implements Attributes { @NotBlank private final String id; - + private final ZonedDateTime time; private final URI schemaurl; private final String contenttype; + AttributesImpl(String type, String specversion, URI source, String id, ZonedDateTime time, URI schemaurl, String contenttype) { @@ -113,7 +113,6 @@ public URI getSource() { /** * Timestamp of when the event happened. */ - @JsonDeserialize(using = ZonedDateTimeDeserializer.class) public Optional getTime() { return Optional.ofNullable(time); } @@ -145,11 +144,11 @@ public static AttributesImpl build( @JsonProperty("source") URI source, @JsonProperty("specversion") String specversion, @JsonProperty("type") String type, - @JsonProperty("time") ZonedDateTime time, + @JsonProperty("time") String time, @JsonProperty("schemaurl") URI schemaurl, @JsonProperty("contenttype") String contenttype) { - return new AttributesImpl(type, specversion, source, id, time, + return new AttributesImpl(type, specversion, source, id, parseZonedDateTime(time).orElse(null), schemaurl, contenttype); } @@ -159,11 +158,7 @@ public static AttributesImpl build( */ public static AttributesImpl unmarshal(Map attributes) { String type = attributes.get(ContextAttributes.type.name()); - ZonedDateTime time = - Optional.ofNullable(attributes.get(ContextAttributes.time.name())) - .map((t) -> ZonedDateTime.parse(t, - ISO_ZONED_DATE_TIME)) - .orElse(null); + String time = attributes.get(ContextAttributes.time.name()); String specversion = attributes.get(ContextAttributes.specversion.name()); URI source = URI.create(attributes.get(ContextAttributes.source.name())); @@ -209,4 +204,12 @@ public static Map marshal(AttributesImpl attributes) { return result; } + + static Optional formatZonedDateTime(ZonedDateTime zonedDateTime) { + return zonedDateTime == null? Optional.empty() : Optional.of(zonedDateTime.format(ISO_ZONED_DATE_TIME)); + } + + static Optional parseZonedDateTime(String zonedDateTime) { + return zonedDateTime == null ? Optional.empty(): Optional.of(ZonedDateTime.parse(zonedDateTime)); + } } diff --git a/api/src/main/java/io/cloudevents/v02/CloudEventBuilder.java b/api/src/main/java/io/cloudevents/v02/CloudEventBuilder.java index f6f651c99..d74d4f2de 100644 --- a/api/src/main/java/io/cloudevents/v02/CloudEventBuilder.java +++ b/api/src/main/java/io/cloudevents/v02/CloudEventBuilder.java @@ -39,6 +39,7 @@ * CloudEvent instances builder * * @author fabiojose + * @author dturanski * @version 0.2 */ public class CloudEventBuilder implements EventBuilder, diff --git a/api/src/main/java/io/cloudevents/v02/CloudEventImpl.java b/api/src/main/java/io/cloudevents/v02/CloudEventImpl.java index 72a48e694..d09408129 100644 --- a/api/src/main/java/io/cloudevents/v02/CloudEventImpl.java +++ b/api/src/main/java/io/cloudevents/v02/CloudEventImpl.java @@ -16,7 +16,7 @@ package io.cloudevents.v02; import java.net.URI; -import java.time.ZonedDateTime; + import java.util.Collections; import java.util.Map; import java.util.Optional; @@ -42,6 +42,7 @@ * The event implementation * * @author fabiojose + * @author dturanski * */ @JsonInclude(value = Include.NON_ABSENT) @@ -118,7 +119,7 @@ public static CloudEventImpl build( @JsonProperty("id") String id, @JsonProperty("source") URI source, @JsonProperty("type") String type, - @JsonProperty("time") ZonedDateTime time, + @JsonProperty("time") String time, @JsonProperty("schemaurl") URI schemaurl, @JsonProperty("contenttype") String contenttype, @JsonProperty("data") T data) { @@ -127,7 +128,7 @@ public static CloudEventImpl build( .withId(id) .withSource(source) .withType(type) - .withTime(time) + .withTime(AttributesImpl.parseZonedDateTime(time).orElse(null)) .withSchemaurl(schemaurl) .withContenttype(contenttype) .withData(data) diff --git a/api/src/main/java/io/cloudevents/v03/AttributesImpl.java b/api/src/main/java/io/cloudevents/v03/AttributesImpl.java index f40f76825..14640d00c 100644 --- a/api/src/main/java/io/cloudevents/v03/AttributesImpl.java +++ b/api/src/main/java/io/cloudevents/v03/AttributesImpl.java @@ -15,11 +15,16 @@ */ package io.cloudevents.v03; -import static java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; import java.net.URI; + import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; + import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -30,19 +35,15 @@ import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; - import io.cloudevents.Attributes; -import io.cloudevents.json.ZonedDateTimeDeserializer; + +import static java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME; /** * The event attributes implementation for v0.3 * * @author fabiojose + * @author dturanski * */ @JsonInclude(value = Include.NON_ABSENT) @@ -60,8 +61,7 @@ public class AttributesImpl implements Attributes { @NotBlank private final String type; - - @JsonDeserialize(using = ZonedDateTimeDeserializer.class) + private final ZonedDateTime time; private final URI schemaurl; @@ -71,15 +71,15 @@ public class AttributesImpl implements Attributes { @Size(min = 1) private final String subject; - + AttributesImpl(String id, URI source, String specversion, String type, - ZonedDateTime time, URI schemaurl, String datacontentencoding, - String datacontenttype, String subject) { + ZonedDateTime time, URI schemaurl, String datacontentencoding, + String datacontenttype, String subject) { this.id = id; this.source = source; this.specversion = specversion; this.type = type; - + this.time = time; this.schemaurl = schemaurl; this.datacontentencoding = datacontentencoding; @@ -140,13 +140,13 @@ public static AttributesImpl build( @JsonProperty("source") URI source, @JsonProperty("specversion") String specversion, @JsonProperty("type") String type, - @JsonProperty("time") ZonedDateTime time, + @JsonProperty("time") String time, @JsonProperty("schemaurl") URI schemaurl, @JsonProperty("datacontentenconding") String datacontentencoding, @JsonProperty("datacontenttype") String datacontenttype, @JsonProperty("subject") String subject) { - return new AttributesImpl(id, source, specversion, type, time, + return new AttributesImpl(id, source, specversion, type, parseZonedDateTime(time).orElse(null), schemaurl, datacontentencoding, datacontenttype, subject); } @@ -185,11 +185,7 @@ public static Map marshal(AttributesImpl attributes) { */ public static AttributesImpl unmarshal(Map attributes) { String type = attributes.get(ContextAttributes.type.name()); - ZonedDateTime time = - Optional.ofNullable(attributes.get(ContextAttributes.time.name())) - .map((t) -> ZonedDateTime.parse(t, - ISO_ZONED_DATE_TIME)) - .orElse(null); + String time = attributes.get(ContextAttributes.time.name()); String specversion = attributes.get(ContextAttributes.specversion.name()); URI source = URI.create(attributes.get(ContextAttributes.source.name())); @@ -213,4 +209,12 @@ public static AttributesImpl unmarshal(Map attributes) { time, schemaurl, datacontentencoding, datacontenttype, subject); } + + static Optional formatZonedDateTime(ZonedDateTime zonedDateTime) { + return zonedDateTime == null? Optional.empty() : Optional.of(zonedDateTime.format(ISO_ZONED_DATE_TIME)); + } + + static Optional parseZonedDateTime(String zonedDateTime) { + return zonedDateTime == null ? Optional.empty(): Optional.of(ZonedDateTime.parse(zonedDateTime)); + } } \ No newline at end of file diff --git a/api/src/main/java/io/cloudevents/v03/CloudEventImpl.java b/api/src/main/java/io/cloudevents/v03/CloudEventImpl.java index 05d4764d9..568ef05ef 100644 --- a/api/src/main/java/io/cloudevents/v03/CloudEventImpl.java +++ b/api/src/main/java/io/cloudevents/v03/CloudEventImpl.java @@ -115,7 +115,7 @@ public static CloudEventImpl build( @JsonProperty("id") String id, @JsonProperty("source") URI source, @JsonProperty("type") String type, - @JsonProperty("time") ZonedDateTime time, + @JsonProperty("time") String time, @JsonProperty("schemaurl") URI schemaurl, @JsonProperty("datacontentencoding") String datacontentencoding, @JsonProperty("datacontenttype") String datacontenttype, @@ -126,7 +126,7 @@ public static CloudEventImpl build( .withId(id) .withSource(source) .withType(type) - .withTime(time) + .withTime(AttributesImpl.parseZonedDateTime(time).orElse(null)) .withSchemaurl(schemaurl) .withDatacontentencoding(datacontentencoding) .withDatacontenttype(datacontenttype) diff --git a/api/src/main/java/io/cloudevents/v1/AttributesImpl.java b/api/src/main/java/io/cloudevents/v1/AttributesImpl.java index 8c51cae4e..b6fb1d5de 100644 --- a/api/src/main/java/io/cloudevents/v1/AttributesImpl.java +++ b/api/src/main/java/io/cloudevents/v1/AttributesImpl.java @@ -15,8 +15,11 @@ */ package io.cloudevents.v1; -import static java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME; - +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.cloudevents.Attributes; import java.net.URI; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; @@ -24,24 +27,17 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; - import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; - -import io.cloudevents.Attributes; -import io.cloudevents.json.ZonedDateTimeDeserializer; +import static java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME; /** * * @author fabiojose + * @author dturanski * @version 1.0 */ @JsonInclude(value = Include.NON_ABSENT) @@ -66,14 +62,12 @@ public class AttributesImpl implements Attributes { @Size(min = 1) private final String subject; - - @JsonDeserialize(using = ZonedDateTimeDeserializer.class) + private final ZonedDateTime time; public AttributesImpl(String id, URI source, String specversion, String type, String datacontenttype, URI dataschema, String subject, ZonedDateTime time) { - this.id = id; this.source = source; this.specversion = specversion; @@ -142,10 +136,10 @@ public static AttributesImpl build( @JsonProperty("datacontenttype") String datacontenttype, @JsonProperty("dataschema") URI dataschema, @JsonProperty("subject") String subject, - @JsonProperty("time") ZonedDateTime time) { + @JsonProperty("time") String time) { return new AttributesImpl(id, source, specversion, type, - datacontenttype, dataschema, subject, time); + datacontenttype, dataschema, subject, parseZonedDateTime(time).get()); } /** @@ -181,11 +175,7 @@ public static Map marshal(AttributesImpl attributes) { */ public static AttributesImpl unmarshal(Map attributes) { String type = attributes.get(ContextAttributes.type.name()); - ZonedDateTime time = - Optional.ofNullable(attributes.get(ContextAttributes.time.name())) - .map((t) -> ZonedDateTime.parse(t, - ISO_ZONED_DATE_TIME)) - .orElse(null); + String time = attributes.get(ContextAttributes.time.name()); String specversion = attributes.get(ContextAttributes.specversion.name()); URI source = URI.create(attributes.get(ContextAttributes.source.name())); @@ -205,4 +195,12 @@ public static AttributesImpl unmarshal(Map attributes) { return AttributesImpl.build(id, source, specversion, type, datacontenttype, dataschema, subject, time); } + + static Optional formatZonedDateTime(ZonedDateTime zonedDateTime) { + return zonedDateTime == null? Optional.empty() : Optional.of(zonedDateTime.format(ISO_ZONED_DATE_TIME)); + } + + static Optional parseZonedDateTime(String zonedDateTime) { + return zonedDateTime == null ? Optional.empty(): Optional.of(ZonedDateTime.parse(zonedDateTime)); + } } diff --git a/api/src/main/java/io/cloudevents/v1/CloudEventBuilder.java b/api/src/main/java/io/cloudevents/v1/CloudEventBuilder.java index c2d456f69..afc0d1b66 100644 --- a/api/src/main/java/io/cloudevents/v1/CloudEventBuilder.java +++ b/api/src/main/java/io/cloudevents/v1/CloudEventBuilder.java @@ -22,6 +22,7 @@ /** * * @author fabiojose + * @author dturanski * @version 1.0 */ public class CloudEventBuilder implements @@ -188,12 +189,12 @@ public CloudEventBuilder withSubject( this.subject = subject; return this; } - + public CloudEventBuilder withTime(ZonedDateTime time) { this.time = time; return this; } - + public CloudEventBuilder withData(T data) { this.data = data; return this; diff --git a/api/src/main/java/io/cloudevents/v1/CloudEventImpl.java b/api/src/main/java/io/cloudevents/v1/CloudEventImpl.java index 72784631b..e2af3b157 100644 --- a/api/src/main/java/io/cloudevents/v1/CloudEventImpl.java +++ b/api/src/main/java/io/cloudevents/v1/CloudEventImpl.java @@ -16,7 +16,7 @@ package io.cloudevents.v1; import java.net.URI; -import java.time.ZonedDateTime; + import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -43,6 +43,7 @@ /** * * @author fabiojose + * @author dturanski * @version 1.0 */ @JsonInclude(value = Include.NON_ABSENT) @@ -145,7 +146,7 @@ public static CloudEventImpl build( @JsonProperty("datacontenttype") String datacontenttype, @JsonProperty("dataschema") URI dataschema, @JsonProperty("subject") String subject, - @JsonProperty("time") ZonedDateTime time, + @JsonProperty("time") String time, @JsonProperty("data") @JsonAlias("data_base64") T data){ @@ -154,7 +155,7 @@ public static CloudEventImpl build( .withId(id) .withSource(source) .withType(type) - .withTime(time) + .withTime(AttributesImpl.parseZonedDateTime(time).orElse(null)) .withDataschema(dataschema) .withDataContentType(datacontenttype) .withData(data) diff --git a/api/src/test/java/io/cloudevents/v02/CloudEventJacksonTest.java b/api/src/test/java/io/cloudevents/v02/CloudEventJacksonTest.java index ee3235890..8d232cbdd 100644 --- a/api/src/test/java/io/cloudevents/v02/CloudEventJacksonTest.java +++ b/api/src/test/java/io/cloudevents/v02/CloudEventJacksonTest.java @@ -20,9 +20,15 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import com.google.gson.Gson; import java.io.InputStream; +import java.io.InputStreamReader; import java.net.URI; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Map; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; diff --git a/api/src/test/java/io/cloudevents/v1/CloudEventJacksonTest.java b/api/src/test/java/io/cloudevents/v1/CloudEventJacksonTest.java index 48e59bcbc..72487ef9a 100644 --- a/api/src/test/java/io/cloudevents/v1/CloudEventJacksonTest.java +++ b/api/src/test/java/io/cloudevents/v1/CloudEventJacksonTest.java @@ -27,7 +27,6 @@ import java.util.Base64; import java.util.regex.Matcher; import java.util.regex.Pattern; - import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -39,9 +38,6 @@ import io.cloudevents.extensions.ExtensionFormat; import io.cloudevents.json.Json; import io.cloudevents.json.types.Much; -import io.cloudevents.v1.AttributesImpl; -import io.cloudevents.v1.CloudEventBuilder; -import io.cloudevents.v1.CloudEventImpl; /** * @@ -345,5 +341,4 @@ public void should_marshal_data_byte_array_as_data_base64() { assertTrue(encoded.contains("\"data_base64\"")); assertTrue(encoded.contains("\"" + expected +"\"")); } - }