Skip to content

Commit 6a85fb3

Browse files
ciberkleidodrotbohm
andcommitted
GH-806 - Add archive support for JPA.
Co-authored-by: Oliver Drotbohm <oliver.drotbohm@broadcom.com>
1 parent dc11486 commit 6a85fb3

File tree

4 files changed

+300
-165
lines changed

4 files changed

+300
-165
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.springframework.modulith.events.jpa;
2+
3+
import jakarta.persistence.Entity;
4+
import jakarta.persistence.Table;
5+
6+
import java.time.Instant;
7+
import java.util.UUID;
8+
9+
/**
10+
* JPA entity to represent archived event publications.
11+
*
12+
* @author Oliver Drotbohm
13+
*/
14+
@Entity
15+
@Table(name = "EVENT_PUBLICATION_ARCHIVE")
16+
class ArchivedJpaEventPublication extends JpaEventPublication {
17+
18+
/**
19+
* Creates a new {@link ArchivedJpaEventPublication} for the given publication date, listener id, serialized event and
20+
* event type.
21+
*
22+
* @param id
23+
* @param publicationDate must not be {@literal null}.
24+
* @param listenerId must not be {@literal null} or empty.
25+
* @param serializedEvent must not be {@literal null} or empty.
26+
* @param eventType must not be {@literal null}.
27+
*/
28+
public ArchivedJpaEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent,
29+
Class<?> eventType) {
30+
super(id, publicationDate, listenerId, serializedEvent, eventType);
31+
}
32+
33+
public ArchivedJpaEventPublication() {}
34+
}

spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublication.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@
1515
*/
1616
package org.springframework.modulith.events.jpa;
1717

18-
import jakarta.persistence.Column;
19-
import jakarta.persistence.Entity;
20-
import jakarta.persistence.Id;
21-
import jakarta.persistence.Table;
18+
import jakarta.persistence.*;
2219

2320
import java.time.Instant;
2421
import java.util.UUID;
@@ -34,6 +31,7 @@
3431
*/
3532
@Entity
3633
@Table(name = "EVENT_PUBLICATION")
34+
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
3735
class JpaEventPublication {
3836

3937
final @Id @Column(length = 16) UUID id;
@@ -68,7 +66,7 @@ class JpaEventPublication {
6866
this.eventType = eventType;
6967
}
7068

71-
JpaEventPublication() {
69+
protected JpaEventPublication() {
7270

7371
this.id = null;
7472
this.publicationDate = null;
@@ -77,9 +75,11 @@ class JpaEventPublication {
7775
this.eventType = null;
7876
}
7977

80-
JpaEventPublication markCompleted() {
78+
ArchivedJpaEventPublication archive(Instant instant) {
8179

82-
this.completionDate = Instant.now();
83-
return this;
80+
var result = new ArchivedJpaEventPublication(id, publicationDate, listenerId, serializedEvent, eventType);
81+
result.completionDate = instant;
82+
83+
return result;
8484
}
8585
}

spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublicationRepository.java

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
* @author Oliver Drotbohm
3939
* @author Dmitry Belyaev
4040
* @author Björn Kieling
41+
* @author Cora Iberkleid
4142
*/
4243
@Transactional
4344
class JpaEventPublicationRepository implements EventPublicationRepository {
@@ -53,7 +54,7 @@ class JpaEventPublicationRepository implements EventPublicationRepository {
5354

5455
private static String COMPLETE = """
5556
select p
56-
from JpaEventPublication p
57+
from %s p
5758
where
5859
p.completionDate is not null
5960
order by
@@ -113,14 +114,14 @@ class JpaEventPublicationRepository implements EventPublicationRepository {
113114

114115
private static final String DELETE_COMPLETED = """
115116
delete
116-
from JpaEventPublication p
117+
from %s p
117118
where
118119
p.completionDate is not null
119120
""";
120121

121122
private static final String DELETE_COMPLETED_BEFORE = """
122123
delete
123-
from JpaEventPublication p
124+
from %s p
124125
where
125126
p.completionDate < ?1
126127
""";
@@ -131,6 +132,8 @@ class JpaEventPublicationRepository implements EventPublicationRepository {
131132
private final EventSerializer serializer;
132133
private final CompletionMode completionMode;
133134

135+
private final String getCompleted, deleteCompleted, deleteCompletedBefore;
136+
134137
/**
135138
* Creates a new {@link JpaEventPublicationRepository} for the given {@link EntityManager} and
136139
* {@link EventSerializer}.
@@ -148,7 +151,15 @@ public JpaEventPublicationRepository(EntityManager entityManager, EventSerialize
148151
this.entityManager = entityManager;
149152
this.serializer = serializer;
150153
this.completionMode = completionMode;
151-
}
154+
155+
var archiveEntityName = completionMode == CompletionMode.ARCHIVE
156+
? ArchivedJpaEventPublication.class.getSimpleName()
157+
: JpaEventPublication.class.getSimpleName();
158+
159+
this.getCompleted = COMPLETE.formatted(archiveEntityName);
160+
this.deleteCompleted = DELETE_COMPLETED.formatted(archiveEntityName);
161+
this.deleteCompletedBefore = DELETE_COMPLETED_BEFORE.formatted(archiveEntityName);
162+
}
152163

153164
/*
154165
* (non-Javadoc)
@@ -179,6 +190,18 @@ public void markCompleted(Object event, PublicationTargetIdentifier identifier,
179190
.setParameter(2, identifierValue)
180191
.executeUpdate();
181192

193+
} else if (completionMode == CompletionMode.ARCHIVE) {
194+
195+
var publication = entityManager.createQuery(BY_EVENT_AND_LISTENER_ID, JpaEventPublication.class)
196+
.setParameter(1, serializedEvent)
197+
.setParameter(2, identifierValue)
198+
.getSingleResult();
199+
200+
var archived = publication.archive(completionDate);
201+
202+
entityManager.remove(publication);
203+
entityManager.persist(archived);
204+
182205
} else {
183206

184207
entityManager.createQuery(MARK_COMPLETED_BY_EVENT_AND_LISTENER_ID)
@@ -202,6 +225,15 @@ public void markCompleted(UUID identifier, Instant completionDate) {
202225
.setParameter(1, identifier)
203226
.executeUpdate();
204227

228+
} else if (completionMode == CompletionMode.ARCHIVE) {
229+
230+
var publication = entityManager.find(JpaEventPublication.class, identifier);
231+
232+
var archived = publication.archive(completionDate);
233+
234+
entityManager.remove(publication);
235+
entityManager.persist(archived);
236+
205237
} else {
206238

207239
entityManager.createQuery(MARK_COMPLETED_BY_ID)
@@ -260,7 +292,11 @@ public Optional<TargetEventPublication> findIncompletePublicationsByEventAndTarg
260292
@Override
261293
public List<TargetEventPublication> findCompletedPublications() {
262294

263-
return entityManager.createQuery(COMPLETE, JpaEventPublication.class)
295+
var type = completionMode == CompletionMode.ARCHIVE
296+
? ArchivedJpaEventPublication.class
297+
: JpaEventPublication.class;
298+
299+
return entityManager.createQuery(getCompleted, type)
264300
.getResultList()
265301
.stream()
266302
.map(this::entityToDomain)
@@ -285,7 +321,7 @@ public void deletePublications(List<UUID> identifiers) {
285321
*/
286322
@Override
287323
public void deleteCompletedPublications() {
288-
entityManager.createQuery(DELETE_COMPLETED).executeUpdate();
324+
entityManager.createQuery(deleteCompleted).executeUpdate();
289325
}
290326

291327
/*
@@ -297,7 +333,7 @@ public void deleteCompletedPublicationsBefore(Instant instant) {
297333

298334
Assert.notNull(instant, "Instant must not be null!");
299335

300-
entityManager.createQuery(DELETE_COMPLETED_BEFORE)
336+
entityManager.createQuery(deleteCompletedBefore)
301337
.setParameter(1, instant)
302338
.executeUpdate();
303339
}
@@ -341,6 +377,7 @@ private static class JpaEventPublicationAdapter implements TargetEventPublicatio
341377

342378
private final JpaEventPublication publication;
343379
private final EventSerializer serializer;
380+
private Object deserializedEvent;
344381

345382
/**
346383
* Creates a new {@link JpaEventPublicationAdapter} for the given {@link JpaEventPublication} and
@@ -373,7 +410,12 @@ public UUID getIdentifier() {
373410
*/
374411
@Override
375412
public Object getEvent() {
376-
return serializer.deserialize(publication.serializedEvent, publication.eventType);
413+
414+
if (deserializedEvent == null) {
415+
this.deserializedEvent = serializer.deserialize(publication.serializedEvent, publication.eventType);
416+
}
417+
418+
return deserializedEvent;
377419
}
378420

379421
/*

0 commit comments

Comments
 (0)