From 43022fbd1782d6ff4811ae3cb4501b683e3d0436 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Mon, 25 Nov 2024 13:59:56 +0100 Subject: [PATCH] GH-970 - Prevent archiving JPA entity from being included in non-archiving setups.\n\nFixes GH-970. --- .../events/jpa/JpaEventPublication.java | 36 ++------------ .../JpaEventPublicationAutoConfiguration.java | 3 +- .../ArchivedJpaEventPublication.java | 37 +++++++++++++++ .../archiving/ArchivingAutoConfiguration.java | 37 +++++++++++++++ .../updating/DefaultJpaEventPublication.java | 37 +++++++++++++++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + ...tionAutoConfigurationIntegrationTests.java | 47 +++++++++++-------- 7 files changed, 146 insertions(+), 52 deletions(-) create mode 100644 spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/archiving/ArchivedJpaEventPublication.java create mode 100644 spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/archiving/ArchivingAutoConfiguration.java create mode 100644 spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/updating/DefaultJpaEventPublication.java diff --git a/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublication.java b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublication.java index f4fce0660..96963b218 100644 --- a/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublication.java +++ b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublication.java @@ -16,15 +16,15 @@ package org.springframework.modulith.events.jpa; import jakarta.persistence.Column; -import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.MappedSuperclass; -import jakarta.persistence.Table; import java.time.Instant; import java.util.Objects; import java.util.UUID; +import org.springframework.modulith.events.jpa.archiving.ArchivedJpaEventPublication; +import org.springframework.modulith.events.jpa.updating.DefaultJpaEventPublication; import org.springframework.modulith.events.support.CompletionMode; import org.springframework.util.Assert; @@ -37,7 +37,7 @@ * @author Cora Iberkleid */ @MappedSuperclass -abstract class JpaEventPublication { +public abstract class JpaEventPublication { final @Id @Column(length = 16) UUID id; final Instant publicationDate; @@ -45,7 +45,7 @@ abstract class JpaEventPublication { final String serializedEvent; final Class eventType; - Instant completionDate; + protected Instant completionDate; /** * Creates a new {@link JpaEventPublication} for the given publication date, listener id, serialized event and event @@ -56,7 +56,7 @@ abstract class JpaEventPublication { * @param serializedEvent must not be {@literal null} or empty. * @param eventType must not be {@literal null}. */ - private JpaEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent, + protected JpaEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent, Class eventType) { Assert.notNull(id, "Identifier must not be null!"); @@ -128,30 +128,4 @@ public boolean equals(Object obj) { public int hashCode() { return id.hashCode(); } - - @Entity(name = "DefaultJpaEventPublication") - @Table(name = "EVENT_PUBLICATION") - private static class DefaultJpaEventPublication extends JpaEventPublication { - - private DefaultJpaEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent, - Class eventType) { - super(id, publicationDate, listenerId, serializedEvent, eventType); - } - - @SuppressWarnings("unused") - DefaultJpaEventPublication() {} - } - - @Entity(name = "ArchivedJpaEventPublication") - @Table(name = "EVENT_PUBLICATION_ARCHIVE") - private static class ArchivedJpaEventPublication extends JpaEventPublication { - - private ArchivedJpaEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent, - Class eventType) { - super(id, publicationDate, listenerId, serializedEvent, eventType); - } - - @SuppressWarnings("unused") - ArchivedJpaEventPublication() {} - } } diff --git a/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublicationAutoConfiguration.java b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublicationAutoConfiguration.java index 57ee44033..2a055d3b8 100644 --- a/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublicationAutoConfiguration.java +++ b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublicationAutoConfiguration.java @@ -20,6 +20,7 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.modulith.events.config.EventPublicationAutoConfiguration; +import org.springframework.modulith.events.jpa.updating.DefaultJpaEventPublication; /** * Auto-configuration for JPA based event publication. Registers this class' package as auto-configuration package, so @@ -29,5 +30,5 @@ */ @AutoConfiguration @AutoConfigureBefore({ HibernateJpaAutoConfiguration.class, EventPublicationAutoConfiguration.class }) -@AutoConfigurationPackage +@AutoConfigurationPackage(basePackageClasses = DefaultJpaEventPublication.class) class JpaEventPublicationAutoConfiguration extends JpaEventPublicationConfiguration {} diff --git a/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/archiving/ArchivedJpaEventPublication.java b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/archiving/ArchivedJpaEventPublication.java new file mode 100644 index 000000000..83644de8e --- /dev/null +++ b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/archiving/ArchivedJpaEventPublication.java @@ -0,0 +1,37 @@ +/* + * Copyright 2024 the original author or 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 + * + * https://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 org.springframework.modulith.events.jpa.archiving; + +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +import java.time.Instant; +import java.util.UUID; + +import org.springframework.modulith.events.jpa.JpaEventPublication; + +@Entity(name = "ArchivedJpaEventPublication") +@Table(name = "EVENT_PUBLICATION_ARCHIVE") +public class ArchivedJpaEventPublication extends JpaEventPublication { + + public ArchivedJpaEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent, + Class eventType) { + super(id, publicationDate, listenerId, serializedEvent, eventType); + } + + @SuppressWarnings("unused") + ArchivedJpaEventPublication() {} +} diff --git a/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/archiving/ArchivingAutoConfiguration.java b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/archiving/ArchivingAutoConfiguration.java new file mode 100644 index 000000000..7fab8e61f --- /dev/null +++ b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/archiving/ArchivingAutoConfiguration.java @@ -0,0 +1,37 @@ +/* + * Copyright 2024 the original author or 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 + * + * https://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 org.springframework.modulith.events.jpa.archiving; + +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigurationPackage; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.modulith.events.config.EventPublicationAutoConfiguration; +import org.springframework.modulith.events.support.CompletionMode; + +/** + * Auto-configuration adding the current package as auto-configuration package for {@link ArchivedJpaEventPublication} + * to be included in the JPA setup. + * + * @author Oliver Drotbohm + * @since 1.3.1 + */ +@ConditionalOnProperty(name = CompletionMode.PROPERTY, havingValue = "archive") +@AutoConfiguration +@AutoConfigureBefore({ HibernateJpaAutoConfiguration.class, EventPublicationAutoConfiguration.class }) +@AutoConfigurationPackage +class ArchivingAutoConfiguration {} diff --git a/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/updating/DefaultJpaEventPublication.java b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/updating/DefaultJpaEventPublication.java new file mode 100644 index 000000000..3bd5b8035 --- /dev/null +++ b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/updating/DefaultJpaEventPublication.java @@ -0,0 +1,37 @@ +/* + * Copyright 2024 the original author or 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 + * + * https://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 org.springframework.modulith.events.jpa.updating; + +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +import java.time.Instant; +import java.util.UUID; + +import org.springframework.modulith.events.jpa.JpaEventPublication; + +@Entity(name = "DefaultJpaEventPublication") +@Table(name = "EVENT_PUBLICATION") +public class DefaultJpaEventPublication extends JpaEventPublication { + + public DefaultJpaEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent, + Class eventType) { + super(id, publicationDate, listenerId, serializedEvent, eventType); + } + + @SuppressWarnings("unused") + DefaultJpaEventPublication() {} +} diff --git a/spring-modulith-events/spring-modulith-events-jpa/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-modulith-events/spring-modulith-events-jpa/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 4dc0fb5bf..e528f6e98 100644 --- a/spring-modulith-events/spring-modulith-events-jpa/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-modulith-events/spring-modulith-events-jpa/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1,2 @@ org.springframework.modulith.events.jpa.JpaEventPublicationAutoConfiguration +org.springframework.modulith.events.jpa.archiving.ArchivingAutoConfiguration diff --git a/spring-modulith-events/spring-modulith-events-jpa/src/test/java/org/springframework/modulith/events/jpa/JpaEventPublicationAutoConfigurationIntegrationTests.java b/spring-modulith-events/spring-modulith-events-jpa/src/test/java/org/springframework/modulith/events/jpa/JpaEventPublicationAutoConfigurationIntegrationTests.java index b3919386f..1cf5d5ffe 100644 --- a/spring-modulith-events/spring-modulith-events-jpa/src/test/java/org/springframework/modulith/events/jpa/JpaEventPublicationAutoConfigurationIntegrationTests.java +++ b/spring-modulith-events/spring-modulith-events-jpa/src/test/java/org/springframework/modulith/events/jpa/JpaEventPublicationAutoConfigurationIntegrationTests.java @@ -16,42 +16,49 @@ package org.springframework.modulith.events.jpa; import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; import example.ExampleApplication; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.BeanFactory; import org.springframework.boot.autoconfigure.AutoConfigurationPackages; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.modulith.events.core.EventSerializer; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestConstructor; -import org.springframework.test.context.TestConstructor.AutowireMode; +import org.springframework.modulith.events.jpa.archiving.ArchivedJpaEventPublication; +import org.springframework.modulith.events.jpa.updating.DefaultJpaEventPublication; +import org.springframework.modulith.events.support.CompletionMode; /** * @author Oliver Drotbohm */ -@SpringBootTest -@ContextConfiguration(classes = ExampleApplication.class) -@TestConstructor(autowireMode = AutowireMode.ALL) class JpaEventPublicationAutoConfigurationIntegrationTests { - private final BeanFactory factory; + String examplePackage = ExampleApplication.class.getPackageName(); + String eventPublicationPackage = DefaultJpaEventPublication.class.getPackageName(); + String archivingPackage = ArchivedJpaEventPublication.class.getPackageName(); - @MockitoBean EventSerializer serializer; + @Test // GH-10 + void registersJpaEventPublicationPackageForAutoConfiguration() { + assertAutoConfigurationPackages(null, examplePackage, eventPublicationPackage); + } - JpaEventPublicationAutoConfigurationIntegrationTests(BeanFactory factory) { - this.factory = factory; - } + @Test // GH-964 + void registersArchivingJpaEventPublicationPackageForAutoConfiguration() { + assertAutoConfigurationPackages("ARCHIVE", examplePackage, eventPublicationPackage, archivingPackage); + } - @Test // GH-10 - void registersJpaEventPublicationPackageForAutoConfiguration() { + private void assertAutoConfigurationPackages(String propertyValue, String... packages) { + + var runner = new ApplicationContextRunner(); - var examplePackage = ExampleApplication.class.getPackageName(); - var eventPublicationPackage = JpaEventPublication.class.getPackageName(); + if (propertyValue != null) { + runner = runner.withPropertyValues(CompletionMode.PROPERTY + "=" + propertyValue); + } - assertThat(AutoConfigurationPackages.get(factory)) - .containsExactlyInAnyOrder(examplePackage, eventPublicationPackage); + runner.withBean(EventSerializer.class, () -> mock(EventSerializer.class)) + .withUserConfiguration(ExampleApplication.class) + .run(context -> { + assertThat(AutoConfigurationPackages.get(context)).containsExactlyInAnyOrder(packages); + }); } }