GH-2 - Upgrade to Spring Boot 3.
Upgrade to Spring Boot 3 and Java 17 as project baselines. Removed legacy JavaEE modules and replaced them by ones compatible with JakartaEE 9. Disabled the Observability module for now as Spring Cloud Sleuth has been removed the Boot 3 compatible Spring Cloud branch and we need to migrate the module to Micrometer first.
This commit is contained in:
16
pom.xml
16
pom.xml
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.7.1</version>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
<relativePath />
|
||||
</parent>
|
||||
|
||||
@@ -22,10 +22,9 @@
|
||||
<module>spring-modulith-events</module>
|
||||
<module>spring-modulith-test</module>
|
||||
<module>spring-modulith-docs</module>
|
||||
<module>spring-modulith-observability</module>
|
||||
<!--<module>spring-modulith-observability</module>-->
|
||||
<module>spring-modulith-moments</module>
|
||||
<module>spring-modulith-starter-jpa</module>
|
||||
<module>spring-modulith-starter-jpa-jakarta</module>
|
||||
<module>spring-modulith-starter-test</module>
|
||||
</modules>
|
||||
|
||||
@@ -111,6 +110,13 @@ limitations under the License.
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
</profile>
|
||||
|
||||
@@ -201,8 +207,8 @@ limitations under the License.
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ class Types {
|
||||
@UtilityClass
|
||||
static class JavaXTypes {
|
||||
|
||||
private static final String BASE_PACKAGE = "javax";
|
||||
private static final String BASE_PACKAGE = "jakarta";
|
||||
|
||||
static final String AT_ENTITY = BASE_PACKAGE + ".persistence.Entity";
|
||||
static final String AT_INJECT = BASE_PACKAGE + ".inject.Inject";
|
||||
|
||||
@@ -17,24 +17,24 @@ package org.springframework.modulith.model;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
import org.jmolecules.event.annotation.DomainEventHandler;
|
||||
import org.junit.jupiter.api.DynamicTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestFactory;
|
||||
import org.springframework.modulith.model.ArchitecturallyEvidentType.SpringAwareArchitecturallyEvidentType;
|
||||
import org.springframework.modulith.model.ArchitecturallyEvidentType.SpringDataAwareArchitecturallyEvidentType;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.modulith.model.ArchitecturallyEvidentType.SpringAwareArchitecturallyEvidentType;
|
||||
import org.springframework.modulith.model.ArchitecturallyEvidentType.SpringDataAwareArchitecturallyEvidentType;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.tngtech.archunit.core.domain.JavaClass;
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
<modules>
|
||||
<module>spring-modulith-events-core</module>
|
||||
<module>spring-modulith-events-jpa</module>
|
||||
<module>spring-modulith-events-jpa-jakarta</module>
|
||||
<module>spring-modulith-events-jackson</module>
|
||||
<module>spring-modulith-events-tests</module>
|
||||
<module>spring-modulith-events-starter</module>
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.experimental</groupId>
|
||||
<artifactId>spring-modulith-events</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<name>Spring Modulith - Events - Jakarta JPA-based registry</name>
|
||||
<artifactId>spring-modulith-events-jpa-jakarta</artifactId>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<module.name>org.springframework.modulith.events.jpa.jakarta</module.name>
|
||||
<spring-framework.version>6.0.0-M1</spring-framework.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-modulith-events-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jakarta Persistence -->
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.persistence</groupId>
|
||||
<artifactId>jakarta.persistence-api</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Testing -->
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate.orm</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>6.0.0.CR2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.transaction</groupId>
|
||||
<artifactId>jakarta.transaction-api</artifactId>
|
||||
<version>2.0.1-RC1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
</project>
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 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
|
||||
*
|
||||
* http://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;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@NoArgsConstructor(force = true)
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
class JpaEventPublication {
|
||||
|
||||
private final @Id @Column(length = 16) UUID id;
|
||||
private final Instant publicationDate;
|
||||
private final String listenerId;
|
||||
private final String serializedEvent;
|
||||
private final Class<?> eventType;
|
||||
|
||||
private Instant completionDate;
|
||||
|
||||
@Builder
|
||||
static JpaEventPublication of(Instant publicationDate, String listenerId, Object serializedEvent,
|
||||
Class<?> eventType) {
|
||||
return new JpaEventPublication(UUID.randomUUID(), publicationDate, listenerId, serializedEvent.toString(),
|
||||
eventType);
|
||||
}
|
||||
|
||||
JpaEventPublication markCompleted() {
|
||||
|
||||
this.completionDate = Instant.now();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 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;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfigurationPackage
|
||||
class JpaEventPublicationAutoConfiguration {}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 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
|
||||
*
|
||||
* http://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;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import org.springframework.modulith.events.EventSerializer;
|
||||
import org.springframework.modulith.events.config.EventPublicationConfigurationExtension;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@RequiredArgsConstructor
|
||||
class JpaEventPublicationConfiguration implements EventPublicationConfigurationExtension {
|
||||
|
||||
@Bean
|
||||
public JpaEventPublicationRegistry jpaEventPublicationRegistry(JpaEventPublicationRepository repository,
|
||||
EventSerializer serializer) {
|
||||
return new JpaEventPublicationRegistry(repository, serializer);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JpaEventPublicationRepository jpaEventPublicationRepository(EntityManager em) {
|
||||
return new JpaEventPublicationRepository(em);
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-2020 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
|
||||
*
|
||||
* http://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;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.modulith.events.CompletableEventPublication;
|
||||
import org.springframework.modulith.events.EventPublication;
|
||||
import org.springframework.modulith.events.EventPublicationRegistry;
|
||||
import org.springframework.modulith.events.EventSerializer;
|
||||
import org.springframework.modulith.events.PublicationTargetIdentifier;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* JPA based {@link EventPublicationRegistry}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
class JpaEventPublicationRegistry implements EventPublicationRegistry, DisposableBean {
|
||||
|
||||
private final @NonNull JpaEventPublicationRepository events;
|
||||
private final @NonNull EventSerializer serializer;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.events.EventPublicationRegistry#store(java.lang.Object, java.util.Collection)
|
||||
*/
|
||||
@Override
|
||||
public void store(Object event, Stream<PublicationTargetIdentifier> listeners) {
|
||||
|
||||
listeners.map(it -> CompletableEventPublication.of(event, it)) //
|
||||
.map(this::map) //
|
||||
.forEach(it -> events.create(it));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.events.EventPublicationRegistry#findIncompletePublications()
|
||||
*/
|
||||
@Override
|
||||
public Iterable<EventPublication> findIncompletePublications() {
|
||||
|
||||
List<EventPublication> result = events.findByCompletionDateIsNull().stream() //
|
||||
.map(it -> JpaEventPublicationAdapter.of(it, serializer)) //
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.events.EventPublicationRegistry#markCompleted(java.lang.Object, org.springframework.events.ListenerId)
|
||||
*/
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void markCompleted(Object event, PublicationTargetIdentifier listener) {
|
||||
|
||||
Assert.notNull(event, "Domain event must not be null!");
|
||||
Assert.notNull(listener, "Listener identifier must not be null!");
|
||||
|
||||
events.findBySerializedEventAndListenerId(serializer.serialize(event), listener.toString()) //
|
||||
.map(JpaEventPublicationRegistry::LOGCompleted) //
|
||||
.ifPresent(it -> events.update(it.markCompleted()));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
|
||||
List<JpaEventPublication> publications = events.findByCompletionDateIsNull();
|
||||
|
||||
if (publications.isEmpty()) {
|
||||
|
||||
LOG.info("No publications outstanding!");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.info("Shutting down with the following publications left unfinished:");
|
||||
|
||||
for (int i = 0; i < publications.size(); i++) {
|
||||
|
||||
String prefix = (i + 1) == publications.size() ? "└─" : "├─";
|
||||
JpaEventPublication it = publications.get(i);
|
||||
|
||||
LOG.info("{} {} - {} - {}", prefix, it.getId(), it.getEventType().getName(), it.getListenerId());
|
||||
}
|
||||
}
|
||||
|
||||
private JpaEventPublication map(EventPublication publication) {
|
||||
|
||||
JpaEventPublication result = JpaEventPublication.builder() //
|
||||
.eventType(publication.getEvent().getClass()) //
|
||||
.publicationDate(publication.getPublicationDate()) //
|
||||
.listenerId(publication.getTargetIdentifier().toString()) //
|
||||
.serializedEvent(serializer.serialize(publication.getEvent()).toString()) //
|
||||
.build();
|
||||
|
||||
LOG.debug("Registering publication of {} with id {} for {}.", //
|
||||
result.getEventType(), result.getId(), result.getListenerId());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JpaEventPublication LOGCompleted(JpaEventPublication publication) {
|
||||
|
||||
LOG.debug("Marking publication of event {} with id {} to listener {} completed.", //
|
||||
publication.getEventType(), publication.getId(), publication.getListenerId());
|
||||
|
||||
return publication;
|
||||
}
|
||||
|
||||
@EqualsAndHashCode
|
||||
@RequiredArgsConstructor(staticName = "of")
|
||||
static class JpaEventPublicationAdapter implements EventPublication {
|
||||
|
||||
private final JpaEventPublication publication;
|
||||
private final EventSerializer serializer;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.events.EventPublication#getEvent()
|
||||
*/
|
||||
@Override
|
||||
public Object getEvent() {
|
||||
return serializer.deserialize(publication.getSerializedEvent(), publication.getEventType());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.events.EventPublication#getListenerId()
|
||||
*/
|
||||
@Override
|
||||
public PublicationTargetIdentifier getTargetIdentifier() {
|
||||
return PublicationTargetIdentifier.of(publication.getListenerId());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.events.EventPublication#getPublicationDate()
|
||||
*/
|
||||
@Override
|
||||
public Instant getPublicationDate() {
|
||||
return publication.getPublicationDate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 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;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.TypedQuery;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Repository to store {@link JpaEventPublication}s.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class JpaEventPublicationRepository {
|
||||
|
||||
private final EntityManager entityManager;
|
||||
|
||||
@Transactional
|
||||
JpaEventPublication create(JpaEventPublication publication) {
|
||||
|
||||
entityManager.persist(publication);
|
||||
return publication;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
JpaEventPublication update(JpaEventPublication publication) {
|
||||
|
||||
entityManager.merge(publication);
|
||||
entityManager.flush();
|
||||
|
||||
return publication;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all {@link JpaEventPublication} that have not been completed yet.
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
List<JpaEventPublication> findByCompletionDateIsNull() {
|
||||
|
||||
String query = "select p from JpaEventPublication p where p.completionDate is null";
|
||||
|
||||
return entityManager.createQuery(query, JpaEventPublication.class).getResultList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link JpaEventPublication} for the given serialized event and listener identifier.
|
||||
*
|
||||
* @param event must not be {@literal null}.
|
||||
* @param listenerId must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
Optional<JpaEventPublication> findBySerializedEventAndListenerId(Object event, String listenerId) {
|
||||
|
||||
String query = "select p from JpaEventPublication p where p.serializedEvent = ?1 and p.listenerId = ?2";
|
||||
|
||||
TypedQuery<JpaEventPublication> typedQuery = entityManager.createQuery(query, JpaEventPublication.class)
|
||||
.setParameter(1, event)
|
||||
.setParameter(2, listenerId);
|
||||
|
||||
try {
|
||||
return Optional.of(typedQuery.getSingleResult());
|
||||
} catch (Exception o_O) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
@org.springframework.lang.NonNullApi
|
||||
package org.springframework.modulith.events.jpa;
|
||||
@@ -1 +0,0 @@
|
||||
restart.include.spring-modulith-events:/spring-modulith-events-jpa-[\\w-\\.]+\.jar
|
||||
@@ -1,6 +0,0 @@
|
||||
org.springframework.modulith.events.config.EventPublicationConfigurationExtension=\
|
||||
org.springframework.modulith.events.jpa.JpaEventPublicationConfiguration
|
||||
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.modulith.events.jpa.JpaEventPublicationAutoConfiguration,\
|
||||
org.springframework.modulith.events.jpa.JpaEventPublicationConfiguration
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 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;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.TypedQuery;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.modulith.events.EventSerializer;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.TestConstructor;
|
||||
import org.springframework.test.context.TestConstructor.AutowireMode;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
/**
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestConstructor(autowireMode = AutowireMode.ALL)
|
||||
@RequiredArgsConstructor
|
||||
public class JpaEventPublicationConfigurationIntegrationTests {
|
||||
|
||||
private final ApplicationContext context;
|
||||
|
||||
@Configuration
|
||||
@Import(JpaEventPublicationConfiguration.class)
|
||||
static class TestConfig {
|
||||
|
||||
@Bean
|
||||
EventSerializer eventSerializer() {
|
||||
return mock(EventSerializer.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
EntityManager entityManager() {
|
||||
|
||||
EntityManager em = mock(EntityManager.class);
|
||||
|
||||
// Mock API for query executed at bootstrap time
|
||||
TypedQuery<?> query = mock(TypedQuery.class);
|
||||
doReturn(query).when(em).createQuery(any(String.class), any());
|
||||
|
||||
return em;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void bootstrapsApplicationComponents() {
|
||||
|
||||
assertThat(context.getBean(JpaEventPublicationRegistry.class)).isNotNull();
|
||||
assertThat(context.getBean(JpaEventPublicationRepository.class)).isNotNull();
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 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;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.modulith.events.EventSerializer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.SharedEntityManagerCreator;
|
||||
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.test.context.TestConstructor;
|
||||
import org.springframework.test.context.TestConstructor.AutowireMode;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestConstructor(autowireMode = AutowireMode.ALL)
|
||||
@Transactional
|
||||
@RequiredArgsConstructor
|
||||
class JpaEventPublicationRepositoryIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@Import(JpaEventPublicationConfiguration.class)
|
||||
static class TestConfig {
|
||||
|
||||
@Bean
|
||||
EventSerializer eventSerializer() {
|
||||
return mock(EventSerializer.class);
|
||||
}
|
||||
|
||||
// Database
|
||||
|
||||
@Bean
|
||||
EmbeddedDatabase hsqlDatabase() {
|
||||
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).build();
|
||||
}
|
||||
|
||||
// JPA
|
||||
|
||||
@Bean
|
||||
LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
|
||||
|
||||
AbstractJpaVendorAdapter vendor = new HibernateJpaVendorAdapter();
|
||||
vendor.setGenerateDdl(true);
|
||||
|
||||
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
|
||||
factory.setJpaVendorAdapter(vendor);
|
||||
factory.setDataSource(dataSource);
|
||||
factory.setPackagesToScan(getClass().getPackage().getName());
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
EntityManager entityManager(EntityManagerFactory factory) {
|
||||
return SharedEntityManagerCreator.createSharedEntityManager(factory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
JpaTransactionManager transactionManager(EntityManagerFactory factory) {
|
||||
return new JpaTransactionManager(factory);
|
||||
}
|
||||
}
|
||||
|
||||
private final JpaEventPublicationRepository repository;
|
||||
|
||||
@Test
|
||||
void persistsJpaEventPublication() {
|
||||
|
||||
JpaEventPublication publication = JpaEventPublication.of(Instant.now(), "listener", "", Object.class);
|
||||
|
||||
// Store publication
|
||||
repository.create(publication);
|
||||
|
||||
assertThat(repository.findByCompletionDateIsNull()).containsExactly(publication);
|
||||
assertThat(repository.findBySerializedEventAndListenerId("", "listener")).isPresent();
|
||||
|
||||
// Complete publication
|
||||
repository.update(publication.markCompleted());
|
||||
|
||||
assertThat(repository.findByCompletionDateIsNull()).isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="error">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
<logger name="org.springframework.modulith" level="info" />
|
||||
|
||||
</configuration>
|
||||
@@ -12,6 +12,7 @@
|
||||
<artifactId>spring-modulith-events-jpa</artifactId>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<module.name>org.springframework.modulith.events.jpa</module.name>
|
||||
</properties>
|
||||
|
||||
@@ -23,11 +24,11 @@
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JPA -->
|
||||
<!-- Jakarta Persistence -->
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.persistence</groupId>
|
||||
<artifactId>javax.persistence-api</artifactId>
|
||||
<groupId>jakarta.persistence</groupId>
|
||||
<artifactId>jakarta.persistence-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -37,13 +38,27 @@
|
||||
</dependency>
|
||||
|
||||
<!-- Testing -->
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate.orm</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>6.1.1.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.transaction</groupId>
|
||||
<artifactId>jakarta.transaction-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
@@ -64,4 +79,14 @@
|
||||
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
</project>
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.modulith.events.jpa;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -24,10 +27,6 @@ import lombok.RequiredArgsConstructor;
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
|
||||
@@ -23,6 +23,4 @@ import org.springframework.context.annotation.Configuration;
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfigurationPackage
|
||||
class JpaEventPublicationAutoConfiguration {
|
||||
|
||||
}
|
||||
class JpaEventPublicationAutoConfiguration {}
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.modulith.events.jpa;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import org.springframework.modulith.events.EventSerializer;
|
||||
import org.springframework.modulith.events.config.EventPublicationConfigurationExtension;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-2020 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.
|
||||
@@ -85,7 +85,7 @@ class JpaEventPublicationRegistry implements EventPublicationRegistry, Disposabl
|
||||
Assert.notNull(listener, "Listener identifier must not be null!");
|
||||
|
||||
events.findBySerializedEventAndListenerId(serializer.serialize(event), listener.toString()) //
|
||||
.map(JpaEventPublicationRegistry::logCompleted) //
|
||||
.map(JpaEventPublicationRegistry::LOGCompleted) //
|
||||
.ifPresent(it -> events.update(it.markCompleted()));
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ class JpaEventPublicationRegistry implements EventPublicationRegistry, Disposabl
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JpaEventPublication logCompleted(JpaEventPublication publication) {
|
||||
private static JpaEventPublication LOGCompleted(JpaEventPublication publication) {
|
||||
|
||||
LOG.debug("Marking publication of event {} with id {} to listener {} completed.", //
|
||||
publication.getEventType(), publication.getId(), publication.getListenerId());
|
||||
@@ -145,20 +145,13 @@ class JpaEventPublicationRegistry implements EventPublicationRegistry, Disposabl
|
||||
private final JpaEventPublication publication;
|
||||
private final EventSerializer serializer;
|
||||
|
||||
private Object deserializedEvent;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.events.EventPublication#getEvent()
|
||||
*/
|
||||
@Override
|
||||
public Object getEvent() {
|
||||
|
||||
if (deserializedEvent == null) {
|
||||
this.deserializedEvent = serializer.deserialize(publication.getSerializedEvent(), publication.getEventType());
|
||||
}
|
||||
|
||||
return deserializedEvent;
|
||||
return serializer.deserialize(publication.getSerializedEvent(), publication.getEventType());
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -15,14 +15,13 @@
|
||||
*/
|
||||
package org.springframework.modulith.events.jpa;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.TypedQuery;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
org.springframework.modulith.events.jpa.JpaEventPublicationAutoConfiguration
|
||||
org.springframework.modulith.events.jpa.JpaEventPublicationConfiguration
|
||||
@@ -19,11 +19,10 @@ import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.TypedQuery;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.modulith.events.EventSerializer;
|
||||
|
||||
@@ -18,12 +18,12 @@ package org.springframework.modulith.events.jpa;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -102,14 +102,13 @@ class JpaEventPublicationRepositoryIntegrationTests {
|
||||
@Test
|
||||
void persistsJpaEventPublication() {
|
||||
|
||||
String listenerId = "listener";
|
||||
JpaEventPublication publication = JpaEventPublication.of(Instant.now(), listenerId, "", Object.class);
|
||||
JpaEventPublication publication = JpaEventPublication.of(Instant.now(), "listener", "", Object.class);
|
||||
|
||||
// Store publication
|
||||
repository.create(publication);
|
||||
|
||||
assertThat(repository.findByCompletionDateIsNull()).containsExactly(publication);
|
||||
assertThat(repository.findBySerializedEventAndListenerId("", listenerId)).isPresent();
|
||||
assertThat(repository.findBySerializedEventAndListenerId("", "listener")).isPresent();
|
||||
|
||||
// Complete publication
|
||||
repository.update(publication.markCompleted());
|
||||
|
||||
@@ -34,8 +34,9 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<groupId>org.hibernate.orm</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>6.1.1.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
*/
|
||||
package example.events;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.acme.myproject.stereotypes;
|
||||
import lombok.Value;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.ConstructorBinding;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@@ -67,7 +66,6 @@ public class Stereotypes {
|
||||
static class SomeAppInterfaceImplementation implements SomeAppInterface {}
|
||||
|
||||
@Value
|
||||
@ConstructorBinding
|
||||
@ConfigurationProperties("org.springframework.modulith.sample")
|
||||
static class SomeConfigurationProperties {
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.experimental</groupId>
|
||||
<artifactId>spring-modulith</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>spring-modulith-starter-jpa-jakarta</artifactId>
|
||||
<name>Spring Modulith - Starter JPA (Jakarta)</name>
|
||||
|
||||
<properties>
|
||||
<module.name>org.springframework.modulith.starter.jpa.jakarta</module.name>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.experimental</groupId>
|
||||
<artifactId>spring-modulith-api</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.experimental</groupId>
|
||||
<artifactId>spring-modulith-moments</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Events -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.experimental</groupId>
|
||||
<artifactId>spring-modulith-events-core</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.experimental</groupId>
|
||||
<artifactId>spring-modulith-events-jackson</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.experimental</groupId>
|
||||
<artifactId>spring-modulith-events-jpa-jakarta</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
Reference in New Issue
Block a user