From 047ae729a2276dadec92760eb3ce4bb28a849510 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Wed, 7 Aug 2024 21:22:55 +0200 Subject: [PATCH] GH-755 - Avoid superfluous, repeated deserialization in JdbcEventPublication.getEvent(). --- .../jdbc/JdbcEventPublicationRepository.java | 34 +++++++++---------- ...PublicationRepositoryIntegrationTests.java | 21 ++++++++++++ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepository.java b/spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepository.java index 53d1f5f5..90c191ca 100644 --- a/spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepository.java +++ b/spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepository.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.UUID; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -323,7 +324,8 @@ class JdbcEventPublicationRepository implements EventPublicationRepository, Bean var listenerId = rs.getString("LISTENER_ID"); var serializedEvent = rs.getString("SERIALIZED_EVENT"); - return new JdbcEventPublication(id, publicationDate, listenerId, serializedEvent, eventClass, serializer, + return new JdbcEventPublication(id, publicationDate, listenerId, + () -> serializer.deserialize(serializedEvent, eventClass), completionDate == null ? null : completionDate.toInstant()); } @@ -368,11 +370,10 @@ class JdbcEventPublicationRepository implements EventPublicationRepository, Bean private final UUID id; private final Instant publicationDate; private final String listenerId; - private final String serializedEvent; - private final Class eventType; + private final Supplier eventSupplier; - private final EventSerializer serializer; private @Nullable Instant completionDate; + private @Nullable Object event; /** * @param id must not be {@literal null}. @@ -383,22 +384,17 @@ class JdbcEventPublicationRepository implements EventPublicationRepository, Bean * @param serializer must not be {@literal null}. * @param completionDate can be {@literal null}. */ - public JdbcEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent, - Class eventType, EventSerializer serializer, @Nullable Instant completionDate) { + public JdbcEventPublication(UUID id, Instant publicationDate, String listenerId, Supplier event, + @Nullable Instant completionDate) { Assert.notNull(id, "Id must not be null!"); Assert.notNull(publicationDate, "Publication date must not be null!"); Assert.hasText(listenerId, "Listener id must not be null or empty!"); - Assert.hasText(serializedEvent, "Serialized event must not be null or empty!"); - Assert.notNull(eventType, "Event type must not be null!"); - Assert.notNull(serializer, "EventSerializer must not be null!"); this.id = id; this.publicationDate = publicationDate; this.listenerId = listenerId; - this.serializedEvent = serializedEvent; - this.eventType = eventType; - this.serializer = serializer; + this.eventSupplier = event; this.completionDate = completionDate; } @@ -416,8 +412,14 @@ class JdbcEventPublicationRepository implements EventPublicationRepository, Bean * @see org.springframework.modulith.events.EventPublication#getEvent() */ @Override + @SuppressWarnings("null") public Object getEvent() { - return serializer.deserialize(serializedEvent, eventType); + + if (event == null) { + this.event = eventSupplier.get(); + } + + return event; } /* @@ -481,12 +483,10 @@ class JdbcEventPublicationRepository implements EventPublicationRepository, Bean } return Objects.equals(completionDate, that.completionDate) // - && Objects.equals(eventType, that.eventType) // && Objects.equals(id, that.id) // && Objects.equals(listenerId, that.listenerId) // && Objects.equals(publicationDate, that.publicationDate) // - && Objects.equals(serializedEvent, that.serializedEvent) // - && Objects.equals(serializer, that.serializer); + && Objects.equals(getEvent(), that.getEvent()); } /* @@ -495,7 +495,7 @@ class JdbcEventPublicationRepository implements EventPublicationRepository, Bean */ @Override public int hashCode() { - return Objects.hash(completionDate, eventType, id, listenerId, publicationDate, serializedEvent, serializer); + return Objects.hash(completionDate, id, listenerId, publicationDate, getEvent()); } } } diff --git a/spring-modulith-events/spring-modulith-events-jdbc/src/test/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepositoryIntegrationTests.java b/spring-modulith-events/spring-modulith-events-jdbc/src/test/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepositoryIntegrationTests.java index 8b327e4b..73190585 100644 --- a/spring-modulith-events/spring-modulith-events-jdbc/src/test/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepositoryIntegrationTests.java +++ b/spring-modulith-events/spring-modulith-events-jdbc/src/test/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepositoryIntegrationTests.java @@ -310,6 +310,25 @@ class JdbcEventPublicationRepositoryIntegrationTests { .isEqualTo(event); } + @Test // GH-753 + void returnsSameEventInstanceFromPublication() { + + // An event not implementing equals(…) / hashCode() + var event = new Sample(); + + // Serialize to whatever + doReturn("").when(serializer).serialize(event); + + // Return fresh instances for every deserialization attempt + doAnswer(__ -> new Sample()).when(serializer).deserialize("", Sample.class); + + repository.create(TargetEventPublication.of(event, TARGET_IDENTIFIER)); + + var publication = repository.findIncompletePublications().get(0); + + assertThat(publication.getEvent()).isSameAs(publication.getEvent()); + } + private TargetEventPublication createPublication(Object event) { var token = event.toString(); @@ -343,4 +362,6 @@ class JdbcEventPublicationRepositoryIntegrationTests { private static final class TestEvent { String eventId; } + + private static final class Sample {} }