From 26655a9e9d26967c19459fd6e5b06895265e60b1 Mon Sep 17 00:00:00 2001 From: Stephen Murby Date: Tue, 13 Feb 2024 09:14:08 +0000 Subject: [PATCH 1/3] Add support for serializing DateTime in self-describing data (close #378) PR #379 --------- Co-authored-by: Matus Tomlein --- build.gradle | 1 + .../com/snowplowanalytics/snowplow/tracker/Utils.java | 7 ++++++- .../snowplowanalytics/snowplow/tracker/UtilsTest.java | 10 ++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e6a84507..03267c77 100644 --- a/build.gradle +++ b/build.gradle @@ -73,6 +73,7 @@ dependencies { // Jackson JSON processor api 'com.fasterxml.jackson.core:jackson-databind:2.16.1' + api 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.1' // Testing libraries testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.1' diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/Utils.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Utils.java index 5e3c936a..af7e94a3 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/Utils.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/Utils.java @@ -20,6 +20,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,7 +31,10 @@ public class Utils { private static final Logger LOGGER = LoggerFactory.getLogger(Utils.class); - private static final ObjectMapper objectMapper = new ObjectMapper(); + private static final ObjectMapper objectMapper + = new ObjectMapper() + .registerModule(new JavaTimeModule()) + .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); // Tracker Utils diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilsTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilsTest.java index e74ea851..24ba8e44 100644 --- a/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilsTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilsTest.java @@ -17,6 +17,8 @@ // Java import java.nio.charset.StandardCharsets; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.LinkedHashMap; import java.util.Map; @@ -68,6 +70,14 @@ public void testMapToJSONString() { Map payload2 = new LinkedHashMap<>(); payload2.put("k1", new Object()); assertEquals("", Utils.mapToJSONString(payload2)); + + Map payload3 = new LinkedHashMap<>(); + payload3.put("k1", LocalDateTime.of(2020, 1, 1, 0, 0)); + assertEquals("{\"k1\":\"2020-01-01T00:00:00\"}", Utils.mapToJSONString(payload3)); + + Map payload4 = new LinkedHashMap<>(); + payload4.put("k1", LocalDate.of(2020, 1, 1)); + assertEquals("{\"k1\":\"2020-01-01\"}", Utils.mapToJSONString(payload4)); } @Test From edc2d2378841d6ae7e7ac5efc6800fd58894b3f6 Mon Sep 17 00:00:00 2001 From: Stephen Murby Date: Wed, 14 Feb 2024 15:10:38 +0000 Subject: [PATCH 2/3] Add equality functions for SelfDescribing and SelfDescribingJson so that they can be compared in unit tests (close #380) PR #381 --- .../tracker/events/SelfDescribing.java | 18 ++++++ .../tracker/payload/SelfDescribingJson.java | 15 +++++ .../tracker/events/SelfDescribingTest.java | 37 +++++++++++ .../payload/SelfDescribingJsonTest.java | 63 +++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 src/test/java/com/snowplowanalytics/snowplow/tracker/events/SelfDescribingTest.java diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/events/SelfDescribing.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/events/SelfDescribing.java index 5ff1dc61..b515b7e6 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/events/SelfDescribing.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/events/SelfDescribing.java @@ -95,4 +95,22 @@ public TrackerPayload getPayload() { Parameter.SELF_DESCRIBING_ENCODED, Parameter.SELF_DESCRIBING); return putTrueTimestamp(payload); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SelfDescribing that = (SelfDescribing) o; + + if (base64Encode != that.base64Encode) return false; + return Objects.equals(eventData, that.eventData); + } + + @Override + public int hashCode() { + int result = eventData != null ? eventData.hashCode() : 0; + result = 31 * result + (base64Encode ? 1 : 0); + return result; + } } diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SelfDescribingJson.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SelfDescribingJson.java index c2c17ac0..915c17d8 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SelfDescribingJson.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SelfDescribingJson.java @@ -198,4 +198,19 @@ public long getByteSize() { public String toString() { return Utils.mapToJSONString(payload); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SelfDescribingJson that = (SelfDescribingJson) o; + + return payload.equals(that.payload); + } + + @Override + public int hashCode() { + return payload.hashCode(); + } } diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/events/SelfDescribingTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/events/SelfDescribingTest.java new file mode 100644 index 00000000..01e21e61 --- /dev/null +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/events/SelfDescribingTest.java @@ -0,0 +1,37 @@ +package com.snowplowanalytics.snowplow.tracker.events; + +import com.snowplowanalytics.snowplow.tracker.payload.SelfDescribingJson; + +// JUnit +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +public class SelfDescribingTest { + + @Test + public void testEqualityOfTwoInstances() { + SelfDescribing.Builder builder = SelfDescribing.builder() + .eventData(new SelfDescribingJson("schema-name")); + + SelfDescribing a = new SelfDescribing( builder ); + SelfDescribing b = new SelfDescribing( builder ); + + assertEquals(a, b); + } + + @Test + public void testNegativeEqualityOfTwoInstances() { + SelfDescribing.Builder builderOne = SelfDescribing.builder() + .eventData(new SelfDescribingJson("schema-name-one")); + + SelfDescribing.Builder builderTwo = SelfDescribing.builder() + .eventData(new SelfDescribingJson("schema-name-two")); + + SelfDescribing a = new SelfDescribing( builderOne ); + SelfDescribing b = new SelfDescribing( builderTwo ); + + assertNotEquals(a, b); + } + +} \ No newline at end of file diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/payload/SelfDescribingJsonTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/payload/SelfDescribingJsonTest.java index 8cfdd414..68f144e1 100644 --- a/src/test/java/com/snowplowanalytics/snowplow/tracker/payload/SelfDescribingJsonTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/payload/SelfDescribingJsonTest.java @@ -20,6 +20,9 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotEquals; + + public class SelfDescribingJsonTest { @@ -67,4 +70,64 @@ public void testMakeSdjWithSdj() { assertNotNull(sdj); assertEquals(expected, sdjString); } + + @Test + public void testEqualityOfTwoInstances_withSchemaNameOnly() { + SelfDescribingJson a = new SelfDescribingJson("schema"); + SelfDescribingJson b = new SelfDescribingJson("schema"); + assertEquals(a, b); + } + + @Test + public void testEqualityOfTwoInstances_withTrackerPayload() { + TrackerPayload nestedData = new TrackerPayload(); + nestedData.add("key", "value"); + SelfDescribingJson a = new SelfDescribingJson("schema", nestedData); + SelfDescribingJson b = new SelfDescribingJson("schema", nestedData); + assertEquals(a, b); + } + + @Test + public void testEqualityOfTwoInstances_withNestedEvent() { + TrackerPayload nestedData = new TrackerPayload(); + nestedData.add("key", "value"); + SelfDescribingJson nestedEvent = new SelfDescribingJson("nested_event", nestedData); + SelfDescribingJson a = new SelfDescribingJson("schema", nestedEvent); + SelfDescribingJson b = new SelfDescribingJson("schema", nestedEvent); + assertEquals(a, b); + } + + @Test + public void testNegativeEqualityOfTwoInstances_withSchemaNameOnly() { + SelfDescribingJson a = new SelfDescribingJson("schema-one"); + SelfDescribingJson b = new SelfDescribingJson("schema-two"); + assertNotEquals(a, b); + } + + @Test + public void testNegativeEqualityOfTwoInstances_withTrackerPayload() { + TrackerPayload nestedDataOne = new TrackerPayload(); + nestedDataOne.add("key", "value-one"); + TrackerPayload nestedDataTwo = new TrackerPayload(); + nestedDataTwo.add("key", "value-two"); + SelfDescribingJson a = new SelfDescribingJson("schema", nestedDataOne); + SelfDescribingJson b = new SelfDescribingJson("schema", nestedDataTwo); + assertNotEquals(a, b); + } + + @Test + public void testNegativeEqualityOfTwoInstances_withNestedEvent() { + TrackerPayload nestedDataOne = new TrackerPayload(); + nestedDataOne.add("key", "value-one"); + SelfDescribingJson nestedEventOne = new SelfDescribingJson("nested_event", nestedDataOne); + + TrackerPayload nestedDataTwo = new TrackerPayload(); + nestedDataTwo.add("key", "value-two"); + SelfDescribingJson nestedEventTwo = new SelfDescribingJson("nested_event", nestedDataTwo); + + + SelfDescribingJson a = new SelfDescribingJson("schema", nestedEventOne); + SelfDescribingJson b = new SelfDescribingJson("schema", nestedEventTwo); + assertNotEquals(a, b); + } } From b9636fd0caf83ae495cef6fe9bf05c75b1a95f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matu=CC=81s=CC=8C=20Tomlein?= Date: Wed, 14 Feb 2024 18:52:02 +0100 Subject: [PATCH 3/3] Prepare for 2.1.0 release --- CHANGELOG | 5 +++++ build.gradle | 2 +- .../com/snowplowanalytics/snowplow/tracker/TrackerTest.java | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d55c6742..c750412a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +Java 2.1.0 (2024-02-14) +----------------------- +Add support for serializing DateTime in self-describing data (#378) (thanks to @stephen-murby for the contribution!) +Add equality functions for SelfDescribing and SelfDescribingJson so that they can be compared in unit tests (#380) (thanks to @stephen-murby for the contribution!) + Java 2.0.0 (2024-01-12) ----------------------- Add builder methods Subject to allow method chaining (#303) diff --git a/build.gradle b/build.gradle index 03267c77..95b21d8e 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ wrapper.gradleVersion = '6.5.0' group = 'com.snowplowanalytics' archivesBaseName = 'snowplow-java-tracker' -version = '2.0.0' +version = '2.1.0' sourceCompatibility = '1.8' targetCompatibility = '1.8' diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java index d6733765..c2bbbd36 100644 --- a/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java @@ -576,7 +576,7 @@ public void testCreateWithConfiguration() { @Test public void testGetTrackerVersion() { Tracker tracker = new Tracker(new TrackerConfiguration("namespace", "an-app-id"), mockEmitter); - assertEquals("java-2.0.0", tracker.getTrackerVersion()); + assertEquals("java-2.1.0", tracker.getTrackerVersion()); } @Test