Skip to content

Commit 9e2d963

Browse files
committed
GH-964 - Prevent archiving JPA entity from being included in non-archiving setups.
We now keep the JPA entity classes to store current and archived event publications in separate packages so that the archiving one can be included only when the archiving mode is selected.
1 parent 0d3025d commit 9e2d963

File tree

7 files changed

+146
-52
lines changed

7 files changed

+146
-52
lines changed

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

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616
package org.springframework.modulith.events.jpa;
1717

1818
import jakarta.persistence.Column;
19-
import jakarta.persistence.Entity;
2019
import jakarta.persistence.Id;
2120
import jakarta.persistence.MappedSuperclass;
22-
import jakarta.persistence.Table;
2321

2422
import java.time.Instant;
2523
import java.util.Objects;
2624
import java.util.UUID;
2725

26+
import org.springframework.modulith.events.jpa.archiving.ArchivedJpaEventPublication;
27+
import org.springframework.modulith.events.jpa.updating.DefaultJpaEventPublication;
2828
import org.springframework.modulith.events.support.CompletionMode;
2929
import org.springframework.util.Assert;
3030

@@ -37,15 +37,15 @@
3737
* @author Cora Iberkleid
3838
*/
3939
@MappedSuperclass
40-
abstract class JpaEventPublication {
40+
public abstract class JpaEventPublication {
4141

4242
final @Id @Column(length = 16) UUID id;
4343
final Instant publicationDate;
4444
final String listenerId;
4545
final String serializedEvent;
4646
final Class<?> eventType;
4747

48-
Instant completionDate;
48+
protected Instant completionDate;
4949

5050
/**
5151
* Creates a new {@link JpaEventPublication} for the given publication date, listener id, serialized event and event
@@ -56,7 +56,7 @@ abstract class JpaEventPublication {
5656
* @param serializedEvent must not be {@literal null} or empty.
5757
* @param eventType must not be {@literal null}.
5858
*/
59-
private JpaEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent,
59+
protected JpaEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent,
6060
Class<?> eventType) {
6161

6262
Assert.notNull(id, "Identifier must not be null!");
@@ -128,30 +128,4 @@ public boolean equals(Object obj) {
128128
public int hashCode() {
129129
return id.hashCode();
130130
}
131-
132-
@Entity(name = "DefaultJpaEventPublication")
133-
@Table(name = "EVENT_PUBLICATION")
134-
private static class DefaultJpaEventPublication extends JpaEventPublication {
135-
136-
private DefaultJpaEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent,
137-
Class<?> eventType) {
138-
super(id, publicationDate, listenerId, serializedEvent, eventType);
139-
}
140-
141-
@SuppressWarnings("unused")
142-
DefaultJpaEventPublication() {}
143-
}
144-
145-
@Entity(name = "ArchivedJpaEventPublication")
146-
@Table(name = "EVENT_PUBLICATION_ARCHIVE")
147-
private static class ArchivedJpaEventPublication extends JpaEventPublication {
148-
149-
private ArchivedJpaEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent,
150-
Class<?> eventType) {
151-
super(id, publicationDate, listenerId, serializedEvent, eventType);
152-
}
153-
154-
@SuppressWarnings("unused")
155-
ArchivedJpaEventPublication() {}
156-
}
157131
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
2121
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
2222
import org.springframework.modulith.events.config.EventPublicationAutoConfiguration;
23+
import org.springframework.modulith.events.jpa.updating.DefaultJpaEventPublication;
2324

2425
/**
2526
* Auto-configuration for JPA based event publication. Registers this class' package as auto-configuration package, so
@@ -29,5 +30,5 @@
2930
*/
3031
@AutoConfiguration
3132
@AutoConfigureBefore({ HibernateJpaAutoConfiguration.class, EventPublicationAutoConfiguration.class })
32-
@AutoConfigurationPackage
33+
@AutoConfigurationPackage(basePackageClasses = DefaultJpaEventPublication.class)
3334
class JpaEventPublicationAutoConfiguration extends JpaEventPublicationConfiguration {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.modulith.events.jpa.archiving;
17+
18+
import jakarta.persistence.Entity;
19+
import jakarta.persistence.Table;
20+
21+
import java.time.Instant;
22+
import java.util.UUID;
23+
24+
import org.springframework.modulith.events.jpa.JpaEventPublication;
25+
26+
@Entity(name = "ArchivedJpaEventPublication")
27+
@Table(name = "EVENT_PUBLICATION_ARCHIVE")
28+
public class ArchivedJpaEventPublication extends JpaEventPublication {
29+
30+
public ArchivedJpaEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent,
31+
Class<?> eventType) {
32+
super(id, publicationDate, listenerId, serializedEvent, eventType);
33+
}
34+
35+
@SuppressWarnings("unused")
36+
ArchivedJpaEventPublication() {}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.modulith.events.jpa.archiving;
17+
18+
import org.springframework.boot.autoconfigure.AutoConfiguration;
19+
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
20+
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
21+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
22+
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
23+
import org.springframework.modulith.events.config.EventPublicationAutoConfiguration;
24+
import org.springframework.modulith.events.support.CompletionMode;
25+
26+
/**
27+
* Auto-configuration adding the current package as auto-configuration package for {@link ArchivedJpaEventPublication}
28+
* to be included in the JPA setup.
29+
*
30+
* @author Oliver Drotbohm
31+
* @since 1.3.1
32+
*/
33+
@ConditionalOnProperty(name = CompletionMode.PROPERTY, havingValue = "archive")
34+
@AutoConfiguration
35+
@AutoConfigureBefore({ HibernateJpaAutoConfiguration.class, EventPublicationAutoConfiguration.class })
36+
@AutoConfigurationPackage
37+
class ArchivingAutoConfiguration {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.modulith.events.jpa.updating;
17+
18+
import jakarta.persistence.Entity;
19+
import jakarta.persistence.Table;
20+
21+
import java.time.Instant;
22+
import java.util.UUID;
23+
24+
import org.springframework.modulith.events.jpa.JpaEventPublication;
25+
26+
@Entity(name = "DefaultJpaEventPublication")
27+
@Table(name = "EVENT_PUBLICATION")
28+
public class DefaultJpaEventPublication extends JpaEventPublication {
29+
30+
public DefaultJpaEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent,
31+
Class<?> eventType) {
32+
super(id, publicationDate, listenerId, serializedEvent, eventType);
33+
}
34+
35+
@SuppressWarnings("unused")
36+
DefaultJpaEventPublication() {}
37+
}
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
org.springframework.modulith.events.jpa.JpaEventPublicationAutoConfiguration
2+
org.springframework.modulith.events.jpa.archiving.ArchivingAutoConfiguration

spring-modulith-events/spring-modulith-events-jpa/src/test/java/org/springframework/modulith/events/jpa/JpaEventPublicationAutoConfigurationIntegrationTests.java

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,42 +16,49 @@
1616
package org.springframework.modulith.events.jpa;
1717

1818
import static org.assertj.core.api.Assertions.*;
19+
import static org.mockito.Mockito.*;
1920

2021
import example.ExampleApplication;
2122

2223
import org.junit.jupiter.api.Test;
23-
import org.springframework.beans.factory.BeanFactory;
2424
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
25-
import org.springframework.boot.test.context.SpringBootTest;
26-
import org.springframework.test.context.bean.override.mockito.MockitoBean;
25+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
2726
import org.springframework.modulith.events.core.EventSerializer;
28-
import org.springframework.test.context.ContextConfiguration;
29-
import org.springframework.test.context.TestConstructor;
30-
import org.springframework.test.context.TestConstructor.AutowireMode;
27+
import org.springframework.modulith.events.jpa.archiving.ArchivedJpaEventPublication;
28+
import org.springframework.modulith.events.jpa.updating.DefaultJpaEventPublication;
29+
import org.springframework.modulith.events.support.CompletionMode;
3130

3231
/**
3332
* @author Oliver Drotbohm
3433
*/
35-
@SpringBootTest
36-
@ContextConfiguration(classes = ExampleApplication.class)
37-
@TestConstructor(autowireMode = AutowireMode.ALL)
3834
class JpaEventPublicationAutoConfigurationIntegrationTests {
3935

40-
private final BeanFactory factory;
36+
String examplePackage = ExampleApplication.class.getPackageName();
37+
String eventPublicationPackage = DefaultJpaEventPublication.class.getPackageName();
38+
String archivingPackage = ArchivedJpaEventPublication.class.getPackageName();
4139

42-
@MockitoBean EventSerializer serializer;
40+
@Test // GH-10
41+
void registersJpaEventPublicationPackageForAutoConfiguration() {
42+
assertAutoConfigurationPackages(null, examplePackage, eventPublicationPackage);
43+
}
4344

44-
JpaEventPublicationAutoConfigurationIntegrationTests(BeanFactory factory) {
45-
this.factory = factory;
46-
}
45+
@Test // GH-964
46+
void registersArchivingJpaEventPublicationPackageForAutoConfiguration() {
47+
assertAutoConfigurationPackages("ARCHIVE", examplePackage, eventPublicationPackage, archivingPackage);
48+
}
4749

48-
@Test // GH-10
49-
void registersJpaEventPublicationPackageForAutoConfiguration() {
50+
private void assertAutoConfigurationPackages(String propertyValue, String... packages) {
51+
52+
var runner = new ApplicationContextRunner();
5053

51-
var examplePackage = ExampleApplication.class.getPackageName();
52-
var eventPublicationPackage = JpaEventPublication.class.getPackageName();
54+
if (propertyValue != null) {
55+
runner = runner.withPropertyValues(CompletionMode.PROPERTY + "=" + propertyValue);
56+
}
5357

54-
assertThat(AutoConfigurationPackages.get(factory))
55-
.containsExactlyInAnyOrder(examplePackage, eventPublicationPackage);
58+
runner.withBean(EventSerializer.class, () -> mock(EventSerializer.class))
59+
.withUserConfiguration(ExampleApplication.class)
60+
.run(context -> {
61+
assertThat(AutoConfigurationPackages.get(context)).containsExactlyInAnyOrder(packages);
62+
});
5663
}
5764
}

0 commit comments

Comments
 (0)