GH-1192 - Migrate code base to jSpecify for nullness verification.

This commit is contained in:
Oliver Drotbohm
2025-02-17 17:10:47 +01:00
parent a136ff920b
commit 9ea2b24b53
134 changed files with 548 additions and 211 deletions

View File

@@ -17,6 +17,11 @@
<dependencies>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.modulith</groupId>
<artifactId>spring-modulith-api</artifactId>

View File

@@ -1,5 +1,5 @@
/**
* AMQP event externalization support.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.amqp;

View File

@@ -17,6 +17,11 @@
<dependencies>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>

View File

@@ -25,6 +25,7 @@ import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.modulith.events.RoutingTarget.ParsedRoutingTarget;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -45,7 +46,7 @@ class AnnotationTargetLookup implements Supplier<Optional<ParsedRoutingTarget>>
private static Map<Class<?>, AnnotationTargetLookup> LOOKUPS = new ConcurrentReferenceHashMap<>(25);
private static final String JMOLECULES_EXTERNALIZED = "org.jmolecules.event.annotation.Externalized";
private static final Class<? extends Annotation> JMOLECULES_ANNOTATION = loadJMoleculesExternalizedIfPresent();
private static final @Nullable Class<? extends Annotation> JMOLECULES_ANNOTATION = loadJMoleculesExternalizedIfPresent();
private final Class<?> type;
private final Supplier<Optional<ParsedRoutingTarget>> lookup;
@@ -159,7 +160,7 @@ class AnnotationTargetLookup implements Supplier<Optional<ParsedRoutingTarget>>
}
@SuppressWarnings("unchecked")
private static Class<? extends Annotation> loadJMoleculesExternalizedIfPresent() {
private static @Nullable Class<? extends Annotation> loadJMoleculesExternalizedIfPresent() {
var classLoader = DefaultEventExternalizationConfiguration.class.getClassLoader();

View File

@@ -28,8 +28,8 @@ import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;
import org.jspecify.annotations.Nullable;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.lang.Nullable;
import org.springframework.modulith.events.RoutingTarget.ParsedRoutingTarget;
import org.springframework.modulith.events.RoutingTarget.RoutingTargetBuilder;
import org.springframework.util.Assert;
@@ -359,7 +359,16 @@ public interface EventExternalizationConfiguration {
}
private static <T extends Annotation> T findAnnotation(Object event, Class<T> annotationType) {
return findMergedAnnotation(event.getClass(), annotationType);
var type = event.getClass();
var result = findMergedAnnotation(type, annotationType);
if (result == null) {
throw new IllegalStateException(
"Couldn't find annotation %s on type %s!".formatted(annotationType, type));
}
return result;
}
}

View File

@@ -17,9 +17,10 @@ package org.springframework.modulith.events;
import java.util.Objects;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.springframework.core.ResolvableType;
import org.springframework.core.ResolvableTypeProvider;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -103,7 +104,7 @@ public class EventExternalized<S, T> implements ResolvableTypeProvider {
*
* @return can be {@literal null}.
*/
public T getBrokerResult() {
public @Nullable T getBrokerResult() {
return brokerResult;
}
@@ -112,7 +113,7 @@ public class EventExternalized<S, T> implements ResolvableTypeProvider {
* @see org.springframework.core.ResolvableTypeProvider#getResolvableType()
*/
@Override
public ResolvableType getResolvableType() {
public @NonNull ResolvableType getResolvableType() {
return type;
}

View File

@@ -17,7 +17,7 @@ package org.springframework.modulith.events;
import java.util.Objects;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -238,14 +238,14 @@ public class RoutingTarget {
/**
* @return the target
*/
public String getTarget() {
public @Nullable String getTarget() {
return target;
}
/**
* @return the key
*/
public String getKey() {
public @Nullable String getKey() {
return key;
}

View File

@@ -1,5 +1,5 @@
/**
* API of the event publication registry abstraction.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events;

View File

@@ -17,6 +17,11 @@
</properties>
<dependencies>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.modulith</groupId>

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.modulith.events.aot;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.ExecutableMode;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
@@ -32,7 +33,7 @@ public class ApplicationListenerMethodAdapterRuntimeHints implements RuntimeHint
* @see org.springframework.aot.hint.RuntimeHintsRegistrar#registerHints(org.springframework.aot.hint.RuntimeHints, java.lang.ClassLoader)
*/
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
var reflection = hints.reflection();

View File

@@ -17,6 +17,7 @@ package org.springframework.modulith.events.aot;
import java.util.Arrays;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aot.hint.MemberCategory;
@@ -43,7 +44,7 @@ public class TransactionalEventListenerAotProcessor implements BeanRegistrationA
* @see org.springframework.beans.factory.aot.BeanRegistrationAotProcessor#processAheadOfTime(org.springframework.beans.factory.support.RegisteredBean)
*/
@Override
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
public @Nullable BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
Class<?> type = registeredBean.getBeanType().resolve(Object.class);

View File

@@ -1,5 +1,5 @@
/**
* AOT support for the Event Publication Registry.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.aot;

View File

@@ -19,6 +19,7 @@ import java.time.Clock;
import java.time.Duration;
import java.util.Arrays;
import org.jspecify.annotations.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
@@ -37,7 +38,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Role;
import org.springframework.core.env.Environment;
import org.springframework.lang.NonNull;
import org.springframework.modulith.events.config.EventPublicationAutoConfiguration.AsyncEnablingConfiguration;
import org.springframework.modulith.events.core.DefaultEventPublicationRegistry;
import org.springframework.modulith.events.core.EventPublicationRegistry;

View File

@@ -1,5 +1,5 @@
/**
* Spring configuration for the Event Publication Registry.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.config;

View File

@@ -20,7 +20,7 @@ import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**

View File

@@ -27,10 +27,10 @@ import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.lang.Nullable;
import org.springframework.modulith.events.CompletedEventPublications;
import org.springframework.modulith.events.EventPublication;
import org.springframework.transaction.annotation.Propagation;

View File

@@ -21,8 +21,8 @@ import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationListener;
import org.springframework.lang.Nullable;
import org.springframework.modulith.events.EventPublication;
/**

View File

@@ -17,7 +17,7 @@ package org.springframework.modulith.events.core;
import java.util.Objects;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**

View File

@@ -1,5 +1,5 @@
/**
* The event publication registry abstraction.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.core;

View File

@@ -15,11 +15,11 @@
*/
package org.springframework.modulith.events.support;
import org.jspecify.annotations.Nullable;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.lang.Nullable;
import org.springframework.modulith.events.RoutingTarget;
import org.springframework.util.Assert;

View File

@@ -22,6 +22,8 @@ import java.util.function.Supplier;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.MethodMatcher;
@@ -31,7 +33,6 @@ import org.springframework.aop.support.StaticMethodMatcher;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.lang.NonNull;
import org.springframework.modulith.events.core.EventPublicationRegistry;
import org.springframework.modulith.events.core.PublicationTargetIdentifier;
import org.springframework.transaction.event.TransactionPhase;
@@ -160,7 +161,7 @@ public class CompletionRegisteringAdvisor extends AbstractPointcutAdvisor {
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
public @Nullable Object invoke(MethodInvocation invocation) throws Throwable {
Object result = null;
var method = invocation.getMethod();
@@ -232,9 +233,8 @@ public class CompletionRegisteringAdvisor extends AbstractPointcutAdvisor {
registry.get().markFailed(event, identifier);
}
@SuppressWarnings("null")
private static String lookupListenerId(Method method) {
return new TransactionalApplicationListenerMethodAdapter(null, method.getDeclaringClass(), method)
return new TransactionalApplicationListenerMethodAdapter("¯\\_(ツ)_/¯", method.getDeclaringClass(), method)
.getListenerId();
}
}

View File

@@ -19,12 +19,15 @@ import java.lang.reflect.Method;
import java.time.Duration;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
@@ -36,8 +39,6 @@ import org.springframework.context.event.ApplicationListenerMethodAdapter;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.Environment;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.modulith.events.EventPublication;
import org.springframework.modulith.events.IncompleteEventPublications;
import org.springframework.modulith.events.core.ConditionalEventListener;
@@ -64,10 +65,12 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv
implements IncompleteEventPublications, SmartInitializingSingleton {
private static final Logger LOGGER = LoggerFactory.getLogger(PersistentApplicationEventMulticaster.class);
private static final Method LEGACY_SHOULD_HANDLE = ReflectionUtils.findMethod(ApplicationListenerMethodAdapter.class,
"shouldHandle", ApplicationEvent.class, Object[].class);
private static final Method SHOULD_HANDLE = ReflectionUtils.findMethod(ApplicationListenerMethodAdapter.class,
"shouldHandle", ApplicationEvent.class);
private static final Method LEGACY_SHOULD_HANDLE = Objects
.requireNonNull(ReflectionUtils.findMethod(ApplicationListenerMethodAdapter.class,
"shouldHandle", ApplicationEvent.class, Object[].class));
private static final Method SHOULD_HANDLE = Objects
.requireNonNull(ReflectionUtils.findMethod(ApplicationListenerMethodAdapter.class,
"shouldHandle", ApplicationEvent.class));
static final String REPUBLISH_ON_RESTART = "spring.modulith.events.republish-outstanding-events-on-restart";
static final String REPUBLISH_ON_RESTART_LEGACY = "spring.modulith.republish-outstanding-events-on-restart";
@@ -251,16 +254,19 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv
* @param payload the actual payload, must not be {@literal null}.
* @return whether the event should be handled by the given candidate.
*/
@SuppressWarnings("null")
private static boolean invokeShouldHandle(ApplicationListener<?> candidate, ApplicationEvent event, Object payload) {
if (!(candidate instanceof ApplicationListenerMethodAdapter listener)) {
return true;
}
return SHOULD_HANDLE != null
? listener.shouldHandle(event)
: (boolean) ReflectionUtils.invokeMethod(LEGACY_SHOULD_HANDLE, candidate, event, new Object[] { payload });
if (SHOULD_HANDLE != null) {
return listener.shouldHandle(event);
}
var result = ReflectionUtils.invokeMethod(LEGACY_SHOULD_HANDLE, candidate, event, new Object[] { payload });
return result == null ? false : (boolean) result;
}
/**

View File

@@ -1,5 +1,5 @@
/**
* Spring Framework extensions to integrate the event publication registry.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.support;

View File

@@ -23,6 +23,7 @@ import java.time.Instant;
import java.time.ZoneId;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
@@ -35,7 +36,6 @@ import org.springframework.boot.test.context.assertj.AssertableApplicationContex
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.ContextConsumer;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.lang.Nullable;
import org.springframework.modulith.events.CompletedEventPublications;
import org.springframework.modulith.events.IncompleteEventPublications;
import org.springframework.modulith.events.config.EventPublicationAutoConfiguration.AsyncPropertiesDefaulter;

View File

@@ -17,6 +17,11 @@
<dependencies>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.modulith</groupId>
<artifactId>spring-modulith-events-core</artifactId>

View File

@@ -1,5 +1,5 @@
/**
* A Jackson based implementation of the {@link org.springframework.modulith.events.core.EventSerializer}.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.jackson;

View File

@@ -29,6 +29,11 @@
<dependencies>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-modulith-events-core</artifactId>
@@ -51,7 +56,6 @@
<optional>true</optional>
</dependency>
<!-- Testing -->
<dependency>

View File

@@ -16,6 +16,7 @@
package org.springframework.modulith.events.jdbc;
import java.sql.Connection;
import java.util.Objects;
import javax.sql.DataSource;
@@ -39,7 +40,8 @@ class DatabaseSchemaInitializer implements InitializingBean {
private final JdbcOperations jdbcOperations;
private final JdbcRepositorySettings settings;
DatabaseSchemaInitializer(DataSource dataSource, ResourceLoader resourceLoader, JdbcOperations jdbcOperations, JdbcRepositorySettings settings) {
DatabaseSchemaInitializer(DataSource dataSource, ResourceLoader resourceLoader, JdbcOperations jdbcOperations,
JdbcRepositorySettings settings) {
this.dataSource = dataSource;
this.resourceLoader = resourceLoader;
@@ -63,7 +65,7 @@ class DatabaseSchemaInitializer implements InitializingBean {
if (useSchema) { // A schema name has been specified.
if (eventPublicationTableExists(schemaName)) {
if (eventPublicationTableExists(Objects.requireNonNull(schemaName))) {
return;
}

View File

@@ -15,10 +15,10 @@
*/
package org.springframework.modulith.events.jdbc;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.ConstructorBinding;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.lang.Nullable;
/**
* Configuration properties for JDBC.
@@ -30,7 +30,7 @@ import org.springframework.lang.Nullable;
class JdbcConfigurationProperties {
private final SchemaInitialization schemaInitialization;
private final String schema;
private final @Nullable String schema;
/**
* Creates a new {@link JdbcConfigurationProperties} instance.
@@ -57,8 +57,7 @@ class JdbcConfigurationProperties {
*
* @return can be {@literal null}.
*/
@Nullable
public String getSchema() {
public @Nullable String getSchema() {
return schema;
}

View File

@@ -29,11 +29,11 @@ import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.lang.Nullable;
import org.springframework.modulith.events.core.EventPublicationRepository;
import org.springframework.modulith.events.core.EventSerializer;
import org.springframework.modulith.events.core.PublicationTargetIdentifier;
@@ -150,7 +150,7 @@ class JdbcEventPublicationRepository implements EventPublicationRepository, Bean
INSERT INTO %s (ID, LISTENER_ID, EVENT_TYPE, SERIALIZED_EVENT, PUBLICATION_DATE, COMPLETION_DATE)
SELECT ID, LISTENER_ID, EVENT_TYPE, SERIALIZED_EVENT, PUBLICATION_DATE, ?
FROM %s
WHERE ID = ?
WHERE ID = ?
AND NOT EXISTS (SELECT 1 FROM %s WHERE ID = EVENT_PUBLICATION.ID)
""";
@@ -161,7 +161,7 @@ class JdbcEventPublicationRepository implements EventPublicationRepository, Bean
FROM %s
WHERE LISTENER_ID = ?
AND SERIALIZED_EVENT = ?
AND NOT EXISTS (SELECT 1 FROM %s WHERE ID = EVENT_PUBLICATION.ID)
AND NOT EXISTS (SELECT 1 FROM %s WHERE ID = EVENT_PUBLICATION.ID)
""";
private static final int DELETE_BATCH_SIZE = 100;
@@ -170,7 +170,7 @@ class JdbcEventPublicationRepository implements EventPublicationRepository, Bean
private final EventSerializer serializer;
private final JdbcRepositorySettings settings;
private ClassLoader classLoader;
private @Nullable ClassLoader classLoader;
private final String sqlStatementInsert,
sqlStatementFindCompleted,
@@ -222,8 +222,10 @@ class JdbcEventPublicationRepository implements EventPublicationRepository, Bean
this.sqlStatementDeleteById = SQL_STATEMENT_DELETE_BY_ID.formatted(table);
this.sqlStatementDeleteCompleted = SQL_STATEMENT_DELETE_COMPLETED.formatted(completedTable);
this.sqlStatementDeleteCompletedBefore = SQL_STATEMENT_DELETE_COMPLETED_BEFORE.formatted(completedTable);
this.sqlStatementCopyToArchive = SQL_STATEMENT_COPY_TO_ARCHIVE_BY_ID.formatted(completedTable, table, completedTable);
this.sqlStatementCopyToArchiveByEventAndListenerId = SQL_STATEMENT_COPY_TO_ARCHIVE_BY_EVENT_AND_LISTENER_ID.formatted(completedTable, table, completedTable);
this.sqlStatementCopyToArchive = SQL_STATEMENT_COPY_TO_ARCHIVE_BY_ID.formatted(completedTable, table,
completedTable);
this.sqlStatementCopyToArchiveByEventAndListenerId = SQL_STATEMENT_COPY_TO_ARCHIVE_BY_EVENT_AND_LISTENER_ID
.formatted(completedTable, table, completedTable);
}
/*
@@ -342,9 +344,11 @@ class JdbcEventPublicationRepository implements EventPublicationRepository, Bean
@Override
@Transactional(readOnly = true)
@SuppressWarnings("null")
public List<TargetEventPublication> findIncompletePublications() {
return operations.query(sqlStatementFindUncompleted, this::resultSetToPublications);
var result = operations.query(sqlStatementFindUncompleted, this::resultSetToPublications);
return result == null ? Collections.emptyList() : result;
}
/*
@@ -428,8 +432,7 @@ class JdbcEventPublicationRepository implements EventPublicationRepository, Bean
* @return can be {@literal null}.
* @throws SQLException
*/
@Nullable
private TargetEventPublication resultSetToPublication(ResultSet rs) throws SQLException {
private @Nullable TargetEventPublication resultSetToPublication(ResultSet rs) throws SQLException {
var id = getUuidFromResultSet(rs);
var eventClass = loadClass(id, rs.getString("EVENT_TYPE"));
@@ -456,8 +459,7 @@ class JdbcEventPublicationRepository implements EventPublicationRepository, Bean
return settings.getDatabaseType().databaseToUUID(rs.getObject("ID"));
}
@Nullable
private Class<?> loadClass(UUID id, String className) {
private @Nullable Class<?> loadClass(UUID id, String className) {
try {
return ClassUtils.forName(className, classLoader);

View File

@@ -15,7 +15,7 @@
*/
package org.springframework.modulith.events.jdbc;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.modulith.events.support.CompletionMode;
import org.springframework.util.Assert;
@@ -29,7 +29,7 @@ import org.springframework.util.Assert;
public class JdbcRepositorySettings {
private final DatabaseType databaseType;
private final String schema;
private final @Nullable String schema;
private final CompletionMode completionMode;
/**
@@ -67,8 +67,7 @@ public class JdbcRepositorySettings {
*
* @return can be {@literal null}.
*/
@Nullable
public String getSchema() {
public @Nullable String getSchema() {
return schema;
}
@@ -82,10 +81,14 @@ public class JdbcRepositorySettings {
/**
* Returns whether we use the archiving completion mode.
*/
public boolean isArchiveCompletion() { return completionMode == CompletionMode.ARCHIVE; }
public boolean isArchiveCompletion() {
return completionMode == CompletionMode.ARCHIVE;
}
/**
* Returns whether we use the updating completion mode.
*/
public boolean isUpdateCompletion() { return completionMode == CompletionMode.UPDATE; }
public boolean isUpdateCompletion() {
return completionMode == CompletionMode.UPDATE;
}
}

View File

@@ -1,5 +1,5 @@
/**
* JDBC integration for {@link org.springframework.modulith.events.core.EventPublicationRepository}.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.jdbc;

View File

@@ -17,6 +17,11 @@
<dependencies>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.modulith</groupId>
<artifactId>spring-modulith-api</artifactId>

View File

@@ -1,5 +1,5 @@
/**
* JMS event externalization support.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.jms;

View File

@@ -18,6 +18,11 @@
<dependencies>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-modulith-events-core</artifactId>

View File

@@ -23,6 +23,8 @@ import java.time.Instant;
import java.util.Objects;
import java.util.UUID;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.modulith.events.jpa.archiving.ArchivedJpaEventPublication;
import org.springframework.modulith.events.jpa.updating.DefaultJpaEventPublication;
import org.springframework.modulith.events.support.CompletionMode;
@@ -45,7 +47,7 @@ public abstract class JpaEventPublication {
final String serializedEvent;
final Class<?> eventType;
protected Instant completionDate;
protected @Nullable Instant completionDate;
/**
* Creates a new {@link JpaEventPublication} for the given publication date, listener id, serialized event and event
@@ -72,6 +74,7 @@ public abstract class JpaEventPublication {
this.eventType = eventType;
}
@NullUnmarked
protected JpaEventPublication() {
this.id = null;

View File

@@ -24,6 +24,7 @@ import java.util.Optional;
import java.util.UUID;
import java.util.stream.IntStream;
import org.jspecify.annotations.Nullable;
import org.springframework.modulith.events.core.EventPublicationRepository;
import org.springframework.modulith.events.core.EventSerializer;
import org.springframework.modulith.events.core.PublicationTargetIdentifier;
@@ -383,7 +384,7 @@ class JpaEventPublicationRepository implements EventPublicationRepository {
private final JpaEventPublication publication;
private final EventSerializer serializer;
private Object deserializedEvent;
private @Nullable Object deserializedEvent;
/**
* Creates a new {@link JpaEventPublicationAdapter} for the given {@link JpaEventPublication} and

View File

@@ -0,0 +1,5 @@
/**
* JPA integration for {@link org.springframework.modulith.events.core.EventPublicationRepository}.
*/
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.jpa.archiving;

View File

@@ -1,5 +1,5 @@
/**
* JPA integration for {@link org.springframework.modulith.events.core.EventPublicationRepository}.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.jpa;

View File

@@ -0,0 +1,5 @@
/**
* JPA integration for {@link org.springframework.modulith.events.core.EventPublicationRepository}.
*/
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.jpa.updating;

View File

@@ -17,6 +17,11 @@
<dependencies>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.modulith</groupId>
<artifactId>spring-modulith-api</artifactId>

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.modulith.events.kafka;
import org.jspecify.annotations.NullUnmarked;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
@@ -53,6 +54,7 @@ class KafkaEventExternalizerConfiguration {
private static final Logger logger = LoggerFactory.getLogger(KafkaEventExternalizerConfiguration.class);
@Bean
@NullUnmarked
DelegatingEventExternalizer kafkaEventExternalizer(EventExternalizationConfiguration configuration,
KafkaOperations<Object, Object> operations, BeanFactory factory) {

View File

@@ -1,5 +1,5 @@
/**
* Kafka event externalization support.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.kafka;

View File

@@ -22,12 +22,12 @@ import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.kafka.core.KafkaOperations;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.modulith.events.EventExternalizationConfiguration;

View File

@@ -17,6 +17,11 @@
<dependencies>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.modulith</groupId>
<artifactId>spring-modulith-api</artifactId>

View File

@@ -1,5 +1,5 @@
/**
* Messaging event externalization support.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.messaging;

View File

@@ -17,6 +17,11 @@
<dependencies>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-modulith-events-core</artifactId>
@@ -26,6 +31,7 @@
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>5.0.0-SNAPSHOT</version>
</dependency>
<dependency>

View File

@@ -18,9 +18,9 @@ package org.springframework.modulith.events.mongodb;
import java.time.Instant;
import java.util.UUID;
import org.jspecify.annotations.Nullable;
import org.springframework.data.annotation.PersistenceCreator;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -85,7 +85,6 @@ class MongoDbEventPublication {
MongoDbEventPublication markCompleted(Instant instant) {
Assert.notNull(instant, "Instant must not be null!");
this.completionDate = instant;
return this;
}

View File

@@ -1,5 +1,5 @@
/**
* MongoDB integration for {@link org.springframework.modulith.events.core.EventPublicationRepository}.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.mongodb;

View File

@@ -17,6 +17,11 @@
<dependencies>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-modulith-events-core</artifactId>
@@ -59,4 +64,5 @@
</dependency>
</dependencies>
</project>

View File

@@ -18,7 +18,7 @@ package org.springframework.modulith.events.neo4j;
import java.time.Instant;
import java.util.UUID;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* The event publication entity definition.

View File

@@ -29,6 +29,7 @@ import java.util.UUID;
import java.util.function.BiFunction;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.neo4j.cypherdsl.core.Cypher;
import org.neo4j.cypherdsl.core.Node;
import org.neo4j.cypherdsl.core.ResultStatement;
@@ -40,7 +41,6 @@ import org.neo4j.driver.Values;
import org.neo4j.driver.types.TypeSystem;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.data.util.Lazy;
import org.springframework.lang.Nullable;
import org.springframework.modulith.events.core.EventPublicationRepository;
import org.springframework.modulith.events.core.EventSerializer;
import org.springframework.modulith.events.core.PublicationTargetIdentifier;

View File

@@ -1,5 +1,5 @@
/**
* Neo4j integration for {@link org.springframework.modulith.events.core.EventPublicationRepository}.
*/
@org.springframework.lang.NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.modulith.events.neo4j;