From 183dbed71cc83d0628c03c8f017578fc57dbb379 Mon Sep 17 00:00:00 2001 From: Jiandong Ma Date: Sat, 19 Jul 2025 15:46:23 +0800 Subject: [PATCH 1/2] Apply Nullability to MongoDb module Related to: #10083 Signed-off-by: Jiandong Ma --- .../mongodb/config/package-info.java | 1 + .../integration/mongodb/dsl/package-info.java | 3 +- .../inbound/AbstractMongoDbMessageSource.java | 11 +- .../MongoDbChangeStreamMessageProducer.java | 2 +- .../mongodb/inbound/MongoDbMessageSource.java | 10 +- .../inbound/ReactiveMongoDbMessageSource.java | 7 +- .../mongodb/inbound/package-info.java | 1 + .../metadata/MongoDbMetadataStore.java | 7 +- .../mongodb/metadata/package-info.java | 1 + .../outbound/MessageCollectionCallback.java | 2 +- .../outbound/MongoDbOutboundGateway.java | 23 ++- .../MongoDbStoringMessageHandler.java | 12 +- .../ReactiveMongoDbStoringMessageHandler.java | 10 +- .../mongodb/outbound/package-info.java | 1 + ...stractConfigurableMongoDbMessageStore.java | 31 ++-- .../ConfigurableMongoDbMessageStore.java | 14 +- .../mongodb/store/MessageDocument.java | 20 ++- .../store/MongoDbChannelMessageStore.java | 8 +- .../mongodb/store/MongoDbMessageStore.java | 169 +++++++++--------- .../mongodb/store/package-info.java | 1 + .../support/MessageToBinaryConverter.java | 4 +- .../mongodb/support/package-info.java | 1 + .../inbound/MongoDbMessageSourceTests.java | 16 +- .../ReactiveMongoDbMessageSourceTests.java | 8 +- .../store/MongoDbMessageGroupStoreTests.java | 1 + ...essageStoreClaimCheckIntegrationTests.java | 2 + .../store/MongoDbMessageStoreTests.java | 2 + 27 files changed, 212 insertions(+), 156 deletions(-) diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/config/package-info.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/config/package-info.java index 2369ec73232..20f8ceabf2b 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/config/package-info.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/config/package-info.java @@ -1,4 +1,5 @@ /** * Contains parser classes for the MongoDb namespace support. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.mongodb.config; diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/dsl/package-info.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/dsl/package-info.java index 8f05105290b..2e4a5fc95fc 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/dsl/package-info.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/dsl/package-info.java @@ -1,6 +1,5 @@ /** * Provides MongoDB Components support for Java DSL. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.integration.mongodb.dsl; diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/AbstractMongoDbMessageSource.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/AbstractMongoDbMessageSource.java index 54aa25aebc5..62781776d88 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/AbstractMongoDbMessageSource.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/AbstractMongoDbMessageSource.java @@ -18,9 +18,11 @@ import java.util.Collection; import java.util.Map; +import java.util.Objects; import com.mongodb.DBObject; import org.bson.Document; +import org.jspecify.annotations.Nullable; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; @@ -40,7 +42,6 @@ import org.springframework.expression.common.LiteralExpression; import org.springframework.expression.spel.support.StandardTypeLocator; import org.springframework.integration.endpoint.AbstractMessageSource; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -64,14 +65,16 @@ public abstract class AbstractMongoDbMessageSource extends AbstractMessageSou private Expression collectionNameExpression = new LiteralExpression("data"); + @SuppressWarnings("NullAway.Init") private MongoConverter mongoConverter; private Class entityClass = DBObject.class; private boolean expectSingleResult = false; - private Expression updateExpression; + private @Nullable Expression updateExpression; + @SuppressWarnings("NullAway.Init") private ApplicationContext applicationContext; private volatile boolean initialized = false; @@ -156,7 +159,7 @@ public boolean isExpectSingleResult() { return this.expectSingleResult; } - public Expression getUpdateExpression() { + public @Nullable Expression getUpdateExpression() { return this.updateExpression; } @@ -261,7 +264,7 @@ else if (value instanceof Update castUpdate) { } private static Pair idFieldFromMap(Map map) { - return Pair.of(ID_FIELD, map.get(ID_FIELD)); + return Pair.of(ID_FIELD, Objects.requireNonNull(map.get(ID_FIELD))); } } diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/MongoDbChangeStreamMessageProducer.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/MongoDbChangeStreamMessageProducer.java index a91e366e4f5..160b69c7ab2 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/MongoDbChangeStreamMessageProducer.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/MongoDbChangeStreamMessageProducer.java @@ -17,6 +17,7 @@ package org.springframework.integration.mongodb.inbound; import org.bson.Document; +import org.jspecify.annotations.Nullable; import reactor.core.publisher.Flux; import org.springframework.data.mongodb.core.ChangeStreamOptions; @@ -24,7 +25,6 @@ import org.springframework.integration.endpoint.MessageProducerSupport; import org.springframework.integration.mongodb.support.MongoHeaders; import org.springframework.integration.support.MessageBuilder; -import org.springframework.lang.Nullable; import org.springframework.messaging.Message; import org.springframework.util.Assert; diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/MongoDbMessageSource.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/MongoDbMessageSource.java index cce005129bc..790d11cf272 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/MongoDbMessageSource.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/MongoDbMessageSource.java @@ -19,6 +19,8 @@ import java.util.Collection; import java.util.List; +import org.jspecify.annotations.Nullable; + import org.springframework.context.ApplicationContext; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoOperations; @@ -31,7 +33,6 @@ import org.springframework.integration.mongodb.support.MongoHeaders; import org.springframework.integration.support.AbstractIntegrationMessageBuilder; import org.springframework.integration.transaction.IntegrationResourceHolder; -import org.springframework.lang.Nullable; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; @@ -64,6 +65,7 @@ public class MongoDbMessageSource extends AbstractMongoDbMessageSource { @Nullable private final MongoDatabaseFactory mongoDbFactory; + @SuppressWarnings("NullAway.Init") private MongoOperations mongoTemplate; /** @@ -105,9 +107,7 @@ protected void onInit() { if (this.mongoDbFactory != null) { MongoTemplate template = new MongoTemplate(this.mongoDbFactory, getMongoConverter()); ApplicationContext applicationContext = getApplicationContext(); - if (applicationContext != null) { - template.setApplicationContext(applicationContext); - } + template.setApplicationContext(applicationContext); this.mongoTemplate = template; } setMongoConverter(this.mongoTemplate.getConverter()); @@ -124,7 +124,7 @@ protected void onInit() { * query will be provided in the {@link MongoHeaders#COLLECTION_NAME} header. */ @Override - protected Object doReceive() { + protected @Nullable Object doReceive() { Assert.isTrue(isInitialized(), "This class is not yet initialized. Invoke its afterPropertiesSet() method"); AbstractIntegrationMessageBuilder messageBuilder = null; diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/ReactiveMongoDbMessageSource.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/ReactiveMongoDbMessageSource.java index b8803f8b645..8b03dd366ae 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/ReactiveMongoDbMessageSource.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/inbound/ReactiveMongoDbMessageSource.java @@ -16,6 +16,7 @@ package org.springframework.integration.mongodb.inbound; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -30,7 +31,6 @@ import org.springframework.data.util.Pair; import org.springframework.expression.Expression; import org.springframework.integration.mongodb.support.MongoHeaders; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -57,6 +57,7 @@ public class ReactiveMongoDbMessageSource extends AbstractMongoDbMessageSource

collectionCallback; + private @Nullable MessageCollectionCallback collectionCallback; private boolean expectSingleResult = false; private Class entityClass = Document.class; + @SuppressWarnings("NullAway.Init") private Expression collectionNameExpression; public MongoDbOutboundGateway(MongoDatabaseFactory mongoDbFactory) { @@ -147,20 +153,21 @@ protected void doInit() { } if (this.mongoTemplate == null) { - this.mongoTemplate = new MongoTemplate(this.mongoDbFactory, this.mongoConverter); + this.mongoTemplate = new MongoTemplate(Objects.requireNonNull(this.mongoDbFactory), this.mongoConverter); } } @Override - protected Object handleRequestMessage(Message requestMessage) { + protected @Nullable Object handleRequestMessage(Message requestMessage) { String collectionName = this.collectionNameExpression.getValue(this.evaluationContext, requestMessage, String.class); Assert.notNull(collectionName, "'collectionNameExpression' cannot evaluate to null"); Object result; if (this.collectionCallback != null) { + var collectionCallbackToUse = this.collectionCallback; result = this.mongoTemplate.execute(collectionName, - collection -> this.collectionCallback.doInCollection(collection, requestMessage)); + collection -> collectionCallbackToUse.doInCollection(collection, requestMessage)); } else { Query query = buildQuery(requestMessage); @@ -178,7 +185,7 @@ protected Object handleRequestMessage(Message requestMessage) { private Query buildQuery(Message requestMessage) { Query query; - + Objects.requireNonNull(this.queryExpression); Object expressionValue = this.queryExpression.getValue(this.evaluationContext, requestMessage, Object.class); diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MongoDbStoringMessageHandler.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MongoDbStoringMessageHandler.java index 81eae6dad52..17b90e237a7 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MongoDbStoringMessageHandler.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MongoDbStoringMessageHandler.java @@ -16,6 +16,10 @@ package org.springframework.integration.mongodb.outbound; +import java.util.Objects; + +import org.jspecify.annotations.Nullable; + import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; @@ -42,12 +46,14 @@ */ public class MongoDbStoringMessageHandler extends AbstractMessageHandler { - private final MongoDatabaseFactory mongoDbFactory; + private final @Nullable MongoDatabaseFactory mongoDbFactory; + @SuppressWarnings("NullAway.Init") private MongoOperations mongoTemplate; - private MongoConverter mongoConverter; + private @Nullable MongoConverter mongoConverter; + @SuppressWarnings("NullAway.Init") private StandardEvaluationContext evaluationContext; private Expression collectionNameExpression = new LiteralExpression("data"); @@ -106,7 +112,7 @@ protected void onInit() { this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(this.getBeanFactory()); if (this.mongoTemplate == null) { - this.mongoTemplate = new MongoTemplate(this.mongoDbFactory, this.mongoConverter); + this.mongoTemplate = new MongoTemplate(Objects.requireNonNull(this.mongoDbFactory), this.mongoConverter); } this.initialized = true; } diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/ReactiveMongoDbStoringMessageHandler.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/ReactiveMongoDbStoringMessageHandler.java index 0eee02c712a..5c8acf824ba 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/ReactiveMongoDbStoringMessageHandler.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/ReactiveMongoDbStoringMessageHandler.java @@ -16,6 +16,9 @@ package org.springframework.integration.mongodb.outbound; +import java.util.Objects; + +import org.jspecify.annotations.Nullable; import reactor.core.publisher.Mono; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; @@ -42,12 +45,14 @@ */ public class ReactiveMongoDbStoringMessageHandler extends AbstractReactiveMessageHandler { + @SuppressWarnings("NullAway.Init") private ReactiveMongoOperations mongoTemplate; - private ReactiveMongoDatabaseFactory mongoDbFactory; + private @Nullable ReactiveMongoDatabaseFactory mongoDbFactory; - private MongoConverter mongoConverter; + private @Nullable MongoConverter mongoConverter; + @SuppressWarnings("NullAway.Init") private StandardEvaluationContext evaluationContext; private Expression collectionNameExpression = new LiteralExpression("data"); @@ -105,6 +110,7 @@ protected void onInit() { super.onInit(); this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory()); if (this.mongoTemplate == null) { + Objects.requireNonNull(this.mongoDbFactory); ReactiveMongoTemplate template = new ReactiveMongoTemplate(this.mongoDbFactory, this.mongoConverter); template.setApplicationContext(getApplicationContext()); this.mongoTemplate = template; diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/package-info.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/package-info.java index 64a9f6806d2..3352a1a9123 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/package-info.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes related to the Mongo outbound channel adapters */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.mongodb.outbound; diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/AbstractConfigurableMongoDbMessageStore.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/AbstractConfigurableMongoDbMessageStore.java index 7703957f301..99501a5f04e 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/AbstractConfigurableMongoDbMessageStore.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/AbstractConfigurableMongoDbMessageStore.java @@ -21,10 +21,12 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.UUID; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; @@ -78,12 +80,14 @@ public abstract class AbstractConfigurableMongoDbMessageStore extends AbstractMe protected final String collectionName; // NOSONAR - final - protected final MongoDatabaseFactory mongoDbFactory; // NOSONAR - final + protected final @Nullable MongoDatabaseFactory mongoDbFactory; + @SuppressWarnings("NullAway.Init") private MongoTemplate mongoTemplate; - private MappingMongoConverter mappingMongoConverter; + private @Nullable MappingMongoConverter mappingMongoConverter; + @SuppressWarnings("NullAway.Init") private ApplicationContext applicationContext; private MessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory(); @@ -103,7 +107,7 @@ public AbstractConfigurableMongoDbMessageStore(MongoDatabaseFactory mongoDbFacto } public AbstractConfigurableMongoDbMessageStore(MongoDatabaseFactory mongoDbFactory, - MappingMongoConverter mappingMongoConverter, String collectionName) { + @Nullable MappingMongoConverter mappingMongoConverter, String collectionName) { Assert.notNull(mongoDbFactory, "'mongoDbFactory' must not be null"); Assert.hasText(collectionName, "'collectionName' must not be empty"); this.collectionName = collectionName; @@ -129,7 +133,7 @@ protected MongoTemplate getMongoTemplate() { return this.mongoTemplate; } - protected MappingMongoConverter getMappingMongoConverter() { + protected @Nullable MappingMongoConverter getMappingMongoConverter() { return this.mappingMongoConverter; } @@ -144,6 +148,7 @@ protected MessageBuilderFactory getMessageBuilderFactory() { @Override public void afterPropertiesSet() { if (this.mongoTemplate == null) { + Objects.requireNonNull(this.mongoDbFactory); if (this.mappingMongoConverter == null) { this.mappingMongoConverter = new MappingMongoConverter(new DefaultDbRefResolver(this.mongoDbFactory), new MongoMappingContext()); @@ -180,14 +185,14 @@ protected void createIndexes() { .on(MessageDocumentFields.SEQUENCE, Sort.Direction.DESC)); } - public Message getMessage(UUID id) { + public @Nullable Message getMessage(UUID id) { Assert.notNull(id, "'id' must not be null"); Query query = Query.query(Criteria.where(MessageDocumentFields.MESSAGE_ID).is(id)); MessageDocument document = this.mongoTemplate.findOne(query, MessageDocument.class, this.collectionName); return document != null ? document.getMessage() : null; } - public MessageMetadata getMessageMetadata(UUID id) { + public @Nullable MessageMetadata getMessageMetadata(UUID id) { Assert.notNull(id, "'id' must not be null"); Query query = Query.query(Criteria.where(MessageDocumentFields.MESSAGE_ID).is(id)); MessageDocument document = this.mongoTemplate.findOne(query, MessageDocument.class, this.collectionName); @@ -222,11 +227,13 @@ public int messageGroupSize(Object groupId) { protected long getNextId() { Query query = Query.query(Criteria.where("_id").is(SEQUENCE_NAME)); query.fields().include(MessageDocumentFields.SEQUENCE); - return ((Number) this.mongoTemplate.findAndModify(query, - new Update().inc(MessageDocumentFields.SEQUENCE, 1L), - FindAndModifyOptions.options().returnNew(true).upsert(true), - Map.class, this.collectionName) - .get(MessageDocumentFields.SEQUENCE)) // NOSONAR - never returns null + Map result = this.mongoTemplate.findAndModify(query, + new Update().inc(MessageDocumentFields.SEQUENCE, 1L), + FindAndModifyOptions.options().returnNew(true).upsert(true), + Map.class, this.collectionName); + Objects.requireNonNull(result); + return ((Number) Objects.requireNonNull(result + .get(MessageDocumentFields.SEQUENCE))) .longValue(); } @@ -276,7 +283,7 @@ protected void doCompleteGroup(Object groupId) { } @Override - public Message getOneMessageFromGroup(Object groupId) { + public @Nullable Message getOneMessageFromGroup(Object groupId) { throw NOT_IMPLEMENTED; } diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/ConfigurableMongoDbMessageStore.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/ConfigurableMongoDbMessageStore.java index 2866c705ca5..5ea1cf9695b 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/ConfigurableMongoDbMessageStore.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/ConfigurableMongoDbMessageStore.java @@ -21,11 +21,14 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; +import org.jspecify.annotations.Nullable; + import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.FindAndModifyOptions; @@ -38,7 +41,6 @@ import org.springframework.integration.store.MessageStore; import org.springframework.integration.store.SimpleMessageGroup; import org.springframework.jmx.export.annotation.ManagedAttribute; -import org.springframework.lang.Nullable; import org.springframework.messaging.Message; import org.springframework.util.Assert; @@ -88,7 +90,7 @@ public ConfigurableMongoDbMessageStore(MongoDatabaseFactory mongoDbFactory, Stri } public ConfigurableMongoDbMessageStore(MongoDatabaseFactory mongoDbFactory, - MappingMongoConverter mappingMongoConverter, String collectionName) { + @Nullable MappingMongoConverter mappingMongoConverter, String collectionName) { super(mongoDbFactory, mappingMongoConverter, collectionName); } @@ -101,7 +103,7 @@ public Message addMessage(Message message) { } @Override - public Message removeMessage(UUID id) { + public @Nullable Message removeMessage(UUID id) { Assert.notNull(id, "'id' must not be null"); Query query = Query.query(Criteria.where(MessageDocumentFields.MESSAGE_ID).is(id) .and(MessageDocumentFields.GROUP_ID).exists(false)); @@ -190,7 +192,7 @@ protected void doRemoveMessagesFromGroup(Object groupId, Collection> Collection ids = new ArrayList<>(); for (Message messageToRemove : messages) { - ids.add(messageToRemove.getHeaders().getId()); + ids.add(Objects.requireNonNull(messageToRemove.getHeaders().getId())); if (ids.size() >= getRemoveBatchSize()) { removeMessages(groupId, ids); ids.clear(); @@ -235,7 +237,7 @@ private void removeMessages(Object groupId, Collection ids) { } @Override - protected Message doPollMessageFromGroup(final Object groupId) { + protected @Nullable Message doPollMessageFromGroup(final Object groupId) { Assert.notNull(groupId, GROUP_ID_MUST_NOT_BE_NULL); Sort sort = Sort.by(MessageDocumentFields.LAST_MODIFIED_TIME, MessageDocumentFields.SEQUENCE); @@ -297,7 +299,7 @@ public int getMessageGroupCount() { } @Override - public Message getOneMessageFromGroup(Object groupId) { + public @Nullable Message getOneMessageFromGroup(Object groupId) { Assert.notNull(groupId, GROUP_ID_MUST_NOT_BE_NULL); Query query = groupOrderQuery(groupId); MessageDocument messageDocument = getMongoTemplate().findOne(query, MessageDocument.class, this.collectionName); diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MessageDocument.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MessageDocument.java index 50580c695c6..34b7353bf37 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MessageDocument.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MessageDocument.java @@ -16,13 +16,15 @@ package org.springframework.integration.mongodb.store; +import java.util.Objects; import java.util.UUID; +import org.jspecify.annotations.Nullable; + import org.springframework.data.annotation.AccessType; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.PersistenceCreator; import org.springframework.data.mongodb.core.mapping.Document; -import org.springframework.lang.Nullable; import org.springframework.messaging.Message; import org.springframework.util.Assert; @@ -42,19 +44,19 @@ public class MessageDocument { * currently Auditable. */ @Id - private String _id; // NOSONAR name + private @Nullable String _id; private final Message message; private final UUID messageId; - private Integer priority; + private @Nullable Integer priority; private Long createdTime = 0L; private Long groupCreatedTime = 0L; - private Object groupId; + private @Nullable Object groupId; private Long lastModifiedTime = 0L; @@ -62,12 +64,12 @@ public class MessageDocument { private Integer lastReleasedSequence = 0; - private String condition; + private @Nullable String condition; private long sequence; public MessageDocument(Message message) { - this(message, message.getHeaders().getId()); + this(message, Objects.requireNonNull(message.getHeaders().getId())); } /** @@ -97,7 +99,7 @@ public void setGroupId(Object groupId) { this.groupId = groupId; } - public void setPriority(Integer priority) { + public void setPriority(@Nullable Integer priority) { this.priority = priority; } @@ -145,11 +147,11 @@ public void setSequence(long sequence) { this.sequence = sequence; } - public Integer getPriority() { + public @Nullable Integer getPriority() { return this.priority; } - public Object getGroupId() { + public @Nullable Object getGroupId() { return this.groupId; } diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoDbChannelMessageStore.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoDbChannelMessageStore.java index 2d30aa88e84..4f367f0bb93 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoDbChannelMessageStore.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoDbChannelMessageStore.java @@ -16,6 +16,8 @@ package org.springframework.integration.mongodb.store; +import org.jspecify.annotations.Nullable; + import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoTemplate; @@ -80,8 +82,8 @@ public MongoDbChannelMessageStore(MongoDatabaseFactory mongoDbFactory, String co this(mongoDbFactory, null, collectionName); } - public MongoDbChannelMessageStore(MongoDatabaseFactory mongoDbFactory, MappingMongoConverter mappingMongoConverter, - String collectionName) { + public MongoDbChannelMessageStore(MongoDatabaseFactory mongoDbFactory, + @Nullable MappingMongoConverter mappingMongoConverter, String collectionName) { super(mongoDbFactory, mappingMongoConverter, collectionName); } @@ -133,7 +135,7 @@ public MessageGroup getMessageGroup(Object groupId) { } @Override - protected Message doPollMessageFromGroup(Object groupId) { + protected @Nullable Message doPollMessageFromGroup(Object groupId) { Assert.notNull(groupId, "'groupId' must not be null"); Sort sort = Sort.by(MessageDocumentFields.LAST_MODIFIED_TIME, MessageDocumentFields.SEQUENCE); diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoDbMessageStore.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoDbMessageStore.java index 598129edaea..68e7faaf92e 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoDbMessageStore.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoDbMessageStore.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -35,6 +36,7 @@ import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.Binary; +import org.jspecify.annotations.Nullable; import org.springframework.beans.BeanUtils; import org.springframework.beans.BeansException; @@ -77,7 +79,6 @@ import org.springframework.integration.support.MutableMessageBuilder; import org.springframework.integration.support.converter.AllowListDeserializingConverter; import org.springframework.jmx.export.annotation.ManagedAttribute; -import org.springframework.lang.Nullable; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.support.ErrorMessage; @@ -134,11 +135,13 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore private final String collectionName; - private ClassLoader classLoader = ClassUtils.getDefaultClassLoader(); + @SuppressWarnings("NullAway.Init") + private ClassLoader classLoader; + @SuppressWarnings("NullAway.Init") private ApplicationContext applicationContext; - private String[] allowedPatterns; + private String @Nullable [] allowedPatterns; /** * Create a MongoDbMessageStore using the provided {@link MongoDatabaseFactory}.and the default collection name. @@ -178,7 +181,7 @@ public void setApplicationContext(ApplicationContext applicationContext) throws * @param patterns the patterns. * @since 5.4 */ - public void addAllowedPatterns(String... patterns) { + public void addAllowedPatterns(String @Nullable ... patterns) { this.allowedPatterns = patterns != null ? Arrays.copyOf(patterns, patterns.length) : null; } @@ -197,9 +200,7 @@ public void setCustomConverters(Object... customConverters) { @Override public void afterPropertiesSet() { - if (this.applicationContext != null) { - this.converter.setApplicationContext(this.applicationContext); - } + this.converter.setApplicationContext(this.applicationContext); this.converter.afterPropertiesSet(); @@ -232,7 +233,7 @@ private void addMessageDocument(MessageWrapper document) { } @Override - public Message getMessage(UUID id) { + public @Nullable Message getMessage(UUID id) { Assert.notNull(id, "'id' must not be null"); MessageWrapper messageWrapper = this.template.findOne(whereMessageIdIs(id), MessageWrapper.class, this.collectionName); @@ -240,7 +241,7 @@ public Message getMessage(UUID id) { } @Override - public MessageMetadata getMessageMetadata(UUID id) { + public @Nullable MessageMetadata getMessageMetadata(UUID id) { Assert.notNull(id, "'id' must not be null"); MessageWrapper messageWrapper = this.template.findOne(whereMessageIdIs(id), MessageWrapper.class, this.collectionName); @@ -262,7 +263,7 @@ public long getMessageCount() { } @Override - public Message removeMessage(UUID id) { + public @Nullable Message removeMessage(UUID id) { Assert.notNull(id, "'id' must not be null"); Query query = Query.query(Criteria.where("headers.id").is(id).and(GROUP_ID_KEY).exists(false)); MessageWrapper messageWrapper = this.template.findAndRemove(query, MessageWrapper.class, this.collectionName); @@ -396,7 +397,7 @@ public Iterator iterator() { } @Override - protected Message doPollMessageFromGroup(final Object groupId) { + protected @Nullable Message doPollMessageFromGroup(final Object groupId) { Assert.notNull(groupId, GROUP_ID_MUST_NOT_BE_NULL); Query query = whereGroupIdIs(groupId).with(Sort.by(GROUP_UPDATE_TIMESTAMP_KEY, SEQUENCE)); MessageWrapper messageWrapper = this.template.findAndRemove(query, MessageWrapper.class, this.collectionName); @@ -431,7 +432,7 @@ protected void doCompleteGroup(Object groupId) { } @Override - public Message getOneMessageFromGroup(Object groupId) { + public @Nullable Message getOneMessageFromGroup(Object groupId) { Assert.notNull(groupId, GROUP_ID_MUST_NOT_BE_NULL); Query query = whereGroupIdOrder(groupId); MessageWrapper messageWrapper = this.template.findOne(query, MessageWrapper.class, this.collectionName); @@ -491,7 +492,7 @@ private static Query whereMessageIdIs(UUID id) { return new Query(Criteria.where("headers.id").is(id)); } - private static Query whereMessageIdIsAndGroupIdIs(UUID id, Object groupId) { + private static Query whereMessageIdIsAndGroupIdIs(UUID id, @Nullable Object groupId) { return new Query(Criteria.where("headers.id").is(id).and(GROUP_ID_KEY).is(groupId)); } @@ -511,11 +512,13 @@ private void updateGroup(Object groupId, Update update) { private long getNextId() { Query query = Query.query(Criteria.where("_id").is(SEQUENCE_NAME)); query.fields().include(SEQUENCE); - return ((Number) this.template.findAndModify(query, - new Update().inc(SEQUENCE, 1L), - FindAndModifyOptions.options().returnNew(true).upsert(true), - Map.class, this.collectionName) - .get(SEQUENCE)) // NOSONAR - never returns null + Map result = this.template.findAndModify(query, + new Update().inc(SEQUENCE, 1L), + FindAndModifyOptions.options().returnNew(true).upsert(true), + Map.class, this.collectionName); + Objects.requireNonNull(result); + return ((Number) Objects.requireNonNull(result + .get(SEQUENCE))) .longValue(); } @@ -523,6 +526,7 @@ private long getNextId() { private static void enhanceHeaders(MessageHeaders messageHeaders, Map headers) { Map innerMap = (Map) new DirectFieldAccessor(messageHeaders).getPropertyValue(HEADERS); + Objects.requireNonNull(innerMap); // using reflection to set ID and TIMESTAMP since they are immutable through MessageHeaders Object idHeader = headers.get(MessageHeaders.ID); if (idHeader != null) { @@ -555,14 +559,14 @@ private final class MessageReadingMongoConverter extends MappingMongoConverter { private static final String CLASS = "_class"; - private Object[] customConverters; + private Object @Nullable [] customConverters; MessageReadingMongoConverter(MongoDatabaseFactory mongoDbFactory, MappingContext, MongoPersistentProperty> mappingContext) { super(new DefaultDbRefResolver(mongoDbFactory), mappingContext); } - void setCustomConverters(Object... customConverters) { + void setCustomConverters(Object @Nullable ... customConverters) { this.customConverters = customConverters != null ? Arrays.copyOf(customConverters, customConverters.length) : null; } @@ -611,49 +615,47 @@ public S read(Class clazz, Bson source) { } private MessageWrapper readAsMessageWrapper(Bson source) { - if (source != null) { - Map sourceMap = asMap(source); - Message message; - Object messageType = sourceMap.get("_messageType"); - if (messageType == null) { - messageType = GenericMessage.class.getName(); - } - try { - message = (Message) read(ClassUtils.forName(messageType.toString(), - MongoDbMessageStore.this.classLoader), source); - } - catch (ClassNotFoundException e) { - throw new IllegalStateException("failed to load class: " + messageType, e); - } - - Long groupTimestamp = (Long) sourceMap.get(GROUP_TIMESTAMP_KEY); - Long lastModified = (Long) sourceMap.get(GROUP_UPDATE_TIMESTAMP_KEY); - Integer lastReleasedSequenceNumber = (Integer) sourceMap.get(LAST_RELEASED_SEQUENCE_NUMBER); - Boolean completeGroup = (Boolean) sourceMap.get(GROUP_COMPLETE_KEY); + Map sourceMap = asMap(source); + Message message; + Object messageType = sourceMap.get("_messageType"); + if (messageType == null) { + messageType = GenericMessage.class.getName(); + } + try { + message = (Message) read(ClassUtils.forName(messageType.toString(), + MongoDbMessageStore.this.classLoader), source); + } + catch (ClassNotFoundException e) { + throw new IllegalStateException("failed to load class: " + messageType, e); + } - MessageWrapper wrapper = new MessageWrapper(message); + Long groupTimestamp = (Long) sourceMap.get(GROUP_TIMESTAMP_KEY); + Long lastModified = (Long) sourceMap.get(GROUP_UPDATE_TIMESTAMP_KEY); + Integer lastReleasedSequenceNumber = (Integer) sourceMap.get(LAST_RELEASED_SEQUENCE_NUMBER); + Boolean completeGroup = (Boolean) sourceMap.get(GROUP_COMPLETE_KEY); - if (sourceMap.containsKey(GROUP_ID_KEY)) { - wrapper.set_GroupId(sourceMap.get(GROUP_ID_KEY)); - } - if (groupTimestamp != null) { - wrapper.set_Group_timestamp(groupTimestamp); - } - if (lastModified != null) { - wrapper.set_Group_update_timestamp(lastModified); - } - if (lastReleasedSequenceNumber != null) { - wrapper.set_LastReleasedSequenceNumber(lastReleasedSequenceNumber); - } + MessageWrapper wrapper = new MessageWrapper(message); - if (completeGroup != null) { - wrapper.set_Group_complete(completeGroup); - } - wrapper.setCondition((String) sourceMap.get("_condition")); + if (sourceMap.containsKey(GROUP_ID_KEY)) { + wrapper.set_GroupId(sourceMap.get(GROUP_ID_KEY)); + } + if (groupTimestamp != null) { + wrapper.set_Group_timestamp(groupTimestamp); + } + if (lastModified != null) { + wrapper.set_Group_update_timestamp(lastModified); + } + if (lastReleasedSequenceNumber != null) { + wrapper.set_LastReleasedSequenceNumber(lastReleasedSequenceNumber); + } - return wrapper; + if (completeGroup != null) { + wrapper.set_Group_complete(completeGroup); } - return null; + wrapper.setCondition((String) sourceMap.get("_condition")); + + return wrapper; + } @Override @@ -700,9 +702,10 @@ else if (source instanceof BasicDBList) { private Object extractPayload(Bson source) { Object payload = asMap(source).get("payload"); - + Objects.requireNonNull(payload); if (payload instanceof Bson payloadObject) { Object payloadType = asMap(payloadObject).get(CLASS); + Objects.requireNonNull(payloadType); try { Class payloadClass = ClassUtils.forName(payloadType.toString(), MongoDbMessageStore.this.classLoader); @@ -752,6 +755,7 @@ private static final class DocumentToMessageHistoryConverter implements Converte @SuppressWarnings("unchecked") public MessageHistory convert(Document source) { List components = (List) source.get("components"); + Objects.requireNonNull(components); List historyEntries = new ArrayList<>(components.size()); for (Document component : components) { MessageHistory.Entry entry = new MessageHistory.Entry(); @@ -774,8 +778,9 @@ private final class DocumentToGenericMessageConverter implements Converter convert(Document source) { @SuppressWarnings(UNCHECKED) + Map messageHeaders = Objects.requireNonNull((Map) source.get(HEADERS)); Map headers = - MongoDbMessageStore.this.converter.normalizeHeaders((Map) source.get(HEADERS)); + MongoDbMessageStore.this.converter.normalizeHeaders(messageHeaders); GenericMessage message = new GenericMessage<>(MongoDbMessageStore.this.converter.extractPayload(source), headers); @@ -794,8 +799,9 @@ private final class DocumentToMutableMessageConverter implements Converter convert(Document source) { @SuppressWarnings(UNCHECKED) + Map messageHeaders = Objects.requireNonNull((Map) source.get(HEADERS)); Map headers = - MongoDbMessageStore.this.converter.normalizeHeaders((Map) source.get(HEADERS)); + MongoDbMessageStore.this.converter.normalizeHeaders(messageHeaders); Object payload = MongoDbMessageStore.this.converter.extractPayload(source); return (MutableMessage) MutableMessageBuilder.withPayload(payload) @@ -814,14 +820,16 @@ private final class DocumentToAdviceMessageConverter implements Converter convert(Document source) { @SuppressWarnings(UNCHECKED) + Map messageHeaders = Objects.requireNonNull((Map) source.get(HEADERS)); Map headers = - MongoDbMessageStore.this.converter.normalizeHeaders((Map) source.get(HEADERS)); + MongoDbMessageStore.this.converter.normalizeHeaders(messageHeaders); Message inputMessage = null; if (source.get("inputMessage") != null) { Bson inputMessageObject = (Bson) source.get("inputMessage"); Object inputMessageType = asMap(inputMessageObject).get("_class"); + Objects.requireNonNull(inputMessageType); try { Class messageClass = ClassUtils.forName(inputMessageType.toString(), MongoDbMessageStore.this.classLoader); @@ -853,10 +861,12 @@ private final class DocumentToErrorMessageConverter implements Converter messageHeaders = Objects.requireNonNull((Map) source.get(HEADERS)); Map headers = - MongoDbMessageStore.this.converter.normalizeHeaders((Map) source.get(HEADERS)); + MongoDbMessageStore.this.converter.normalizeHeaders(messageHeaders); - Object payload = this.deserializingConverter.convert(((Binary) source.get("payload")).getData()); + Binary binary = (Binary) source.get("payload"); + Object payload = this.deserializingConverter.convert(Objects.requireNonNull(binary).getData()); ErrorMessage message = new ErrorMessage((Throwable) payload, headers); // NOSONAR not null enhanceHeaders(message.getHeaders(), headers); @@ -868,7 +878,7 @@ public ErrorMessage convert(Document source) { @WritingConverter private static final class ThrowableToBytesConverter implements Converter { - private final Converter serializingConverter = new SerializingConverter(); + private final SerializingConverter serializingConverter = new SerializingConverter(); ThrowableToBytesConverter() { } @@ -894,15 +904,14 @@ private static final class MessageWrapper { */ @SuppressWarnings(UNUSED) @Id - private String _id; // NOSONAR name + private @Nullable String _id; - private volatile Object _groupId; // NOSONAR name + private volatile @Nullable Object _groupId; - // @Transient - private final Message message; // NOSONAR name + private final Message message; @SuppressWarnings(UNUSED) - private final String _messageType; // NOSONAR name + private final String _messageType; @SuppressWarnings(UNUSED) private final Object payload; @@ -911,19 +920,19 @@ private static final class MessageWrapper { private final Map headers; @SuppressWarnings(UNUSED) - private final Message inputMessage; + private final @Nullable Message inputMessage; - private long _message_timestamp; // NOSONAR name + private long _message_timestamp; - private volatile long _group_timestamp; // NOSONAR name + private volatile long _group_timestamp; - private volatile long _group_update_timestamp; // NOSONAR name + private volatile long _group_update_timestamp; - private volatile int _last_released_sequence; // NOSONAR name + private volatile int _last_released_sequence; - private volatile boolean _group_complete; // NOSONAR name + private volatile boolean _group_complete; - private volatile String _condition; // NOSONAR name + private volatile @Nullable String _condition; @SuppressWarnings(UNUSED) private long sequence; @@ -955,7 +964,7 @@ public boolean get_Group_complete() { // NOSONAR name } @SuppressWarnings(UNUSED) - public Object get_GroupId() { // NOSONAR name + public @Nullable Object get_GroupId() { // NOSONAR name return this._groupId; } @@ -995,11 +1004,11 @@ public void set_Group_complete(boolean completedGroup) { // NOSONAR name this._group_complete = completedGroup; } - public String getCondition() { + public @Nullable String getCondition() { return this._condition; } - public void setCondition(String condition) { + public void setCondition(@Nullable String condition) { this._condition = condition; } diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/package-info.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/package-info.java index dfab2b9b867..64c78cd5c4d 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/package-info.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes related to the MongoDB message store. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.mongodb.store; diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/support/MessageToBinaryConverter.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/support/MessageToBinaryConverter.java index 653c7cec53f..f375895b27f 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/support/MessageToBinaryConverter.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/support/MessageToBinaryConverter.java @@ -16,6 +16,8 @@ package org.springframework.integration.mongodb.support; +import java.util.Objects; + import org.bson.types.Binary; import org.springframework.core.convert.converter.Converter; @@ -34,7 +36,7 @@ public class MessageToBinaryConverter implements Converter, Binary> { @Override public Binary convert(Message source) { - return new Binary(this.serializingConverter.convert(source)); + return new Binary(Objects.requireNonNull(this.serializingConverter.convert(source))); } } diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/support/package-info.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/support/package-info.java index 8004b4c31a0..f9bf8f2f40b 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/support/package-info.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/support/package-info.java @@ -1,4 +1,5 @@ /** * Provides supporting classes for this module. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.mongodb.support; diff --git a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/inbound/MongoDbMessageSourceTests.java b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/inbound/MongoDbMessageSourceTests.java index 0e4fcb0093b..9643ad635ee 100644 --- a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/inbound/MongoDbMessageSourceTests.java +++ b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/inbound/MongoDbMessageSourceTests.java @@ -90,7 +90,7 @@ void validateSuccessfulQueryWithSingleElementIfOneInListAsDbObject() { Expression queryExpression = new LiteralExpression("{'name' : 'Oleg'}"); MongoDbMessageSource messageSource = new MongoDbMessageSource(MONGO_DATABASE_FACTORY, queryExpression); - messageSource.setBeanFactory(TEST_INTEGRATION_CONTEXT); + messageSource.setApplicationContext(TEST_INTEGRATION_CONTEXT); messageSource.afterPropertiesSet(); @SuppressWarnings("unchecked") List results = ((List) messageSource.receive().getPayload()); @@ -110,7 +110,7 @@ void validateSuccessfulQueryWithSingleElementIfOneInList() { Expression queryExpression = new LiteralExpression("{'name' : 'Oleg'}"); MongoDbMessageSource messageSource = new MongoDbMessageSource(MONGO_DATABASE_FACTORY, queryExpression); messageSource.setEntityClass(Object.class); - messageSource.setBeanFactory(TEST_INTEGRATION_CONTEXT); + messageSource.setApplicationContext(TEST_INTEGRATION_CONTEXT); messageSource.afterPropertiesSet(); @SuppressWarnings("unchecked") List results = ((List) messageSource.receive().getPayload()); @@ -131,7 +131,7 @@ void validateSuccessfulQueryWithSingleElementIfOneInListAndSingleResult() { MongoDbMessageSource messageSource = new MongoDbMessageSource(MONGO_DATABASE_FACTORY, queryExpression); messageSource.setEntityClass(Object.class); messageSource.setExpectSingleResult(true); - messageSource.setBeanFactory(TEST_INTEGRATION_CONTEXT); + messageSource.setApplicationContext(TEST_INTEGRATION_CONTEXT); messageSource.afterPropertiesSet(); Person person = (Person) messageSource.receive().getPayload(); @@ -149,7 +149,7 @@ void validateSuccessfulSubObjectQueryWithSingleElementIfOneInList() { Expression queryExpression = new LiteralExpression("{'address.state' : 'PA'}"); MongoDbMessageSource messageSource = new MongoDbMessageSource(MONGO_DATABASE_FACTORY, queryExpression); messageSource.setEntityClass(Object.class); - messageSource.setBeanFactory(TEST_INTEGRATION_CONTEXT); + messageSource.setApplicationContext(TEST_INTEGRATION_CONTEXT); messageSource.afterPropertiesSet(); @SuppressWarnings("unchecked") List results = ((List) messageSource.receive().getPayload()); @@ -188,7 +188,7 @@ private List queryMultipleElements(Expression queryExpression) { template.save(MongoDbContainerTest.createPerson("Jack"), "data"); MongoDbMessageSource messageSource = new MongoDbMessageSource(MONGO_DATABASE_FACTORY, queryExpression); - messageSource.setBeanFactory(TEST_INTEGRATION_CONTEXT); + messageSource.setApplicationContext(TEST_INTEGRATION_CONTEXT); messageSource.afterPropertiesSet(); return (List) messageSource.receive().getPayload(); @@ -206,7 +206,7 @@ void validateSuccessfulQueryWithNullReturn() { Expression queryExpression = new LiteralExpression("{'address.state' : 'NJ'}"); MongoDbMessageSource messageSource = new MongoDbMessageSource(MONGO_DATABASE_FACTORY, queryExpression); - messageSource.setBeanFactory(TEST_INTEGRATION_CONTEXT); + messageSource.setApplicationContext(TEST_INTEGRATION_CONTEXT); messageSource.afterPropertiesSet(); assertThat(messageSource.receive()).isNull(); } @@ -225,7 +225,7 @@ void validateSuccessfulQueryWithCustomConverter() { Expression queryExpression = new LiteralExpression("{'address.state' : 'PA'}"); MongoDbMessageSource messageSource = new MongoDbMessageSource(MONGO_DATABASE_FACTORY, queryExpression); MappingMongoConverter converter = new TestMongoConverter(MONGO_DATABASE_FACTORY, new MongoMappingContext()); - messageSource.setBeanFactory(TEST_INTEGRATION_CONTEXT); + messageSource.setApplicationContext(TEST_INTEGRATION_CONTEXT); converter.afterPropertiesSet(); converter = spy(converter); messageSource.setMongoConverter(converter); @@ -278,7 +278,7 @@ void validatePipelineInModifyOut() { Expression queryExpression = new LiteralExpression("{'name' : 'Manny'}"); MongoDbMessageSource messageSource = new MongoDbMessageSource(MONGO_DATABASE_FACTORY, queryExpression); messageSource.setExpectSingleResult(true); - messageSource.setBeanFactory(TEST_INTEGRATION_CONTEXT); + messageSource.setApplicationContext(TEST_INTEGRATION_CONTEXT); messageSource.afterPropertiesSet(); BasicDBObject result = (BasicDBObject) messageSource.receive().getPayload(); Object id = result.get("_id"); diff --git a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/inbound/ReactiveMongoDbMessageSourceTests.java b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/inbound/ReactiveMongoDbMessageSourceTests.java index 7bb9d551f1f..69044bfe013 100644 --- a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/inbound/ReactiveMongoDbMessageSourceTests.java +++ b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/inbound/ReactiveMongoDbMessageSourceTests.java @@ -107,7 +107,7 @@ void validateSuccessfulQueryWithSingleElementFluxOfDbObject() { Expression queryExpression = new LiteralExpression("{'name' : 'Oleg'}"); ReactiveMongoDbMessageSource messageSource = new ReactiveMongoDbMessageSource(REACTIVE_MONGO_DATABASE_FACTORY, queryExpression); - messageSource.setBeanFactory(TEST_INTEGRATION_CONTEXT); + messageSource.setApplicationContext(TEST_INTEGRATION_CONTEXT); messageSource.afterPropertiesSet(); StepVerifier.create((Flux) messageSource.receive().getPayload()) @@ -127,7 +127,7 @@ void validateSuccessfulQueryWithSingleElementFluxOfPerson() { Expression queryExpression = new LiteralExpression("{'name' : 'Oleg'}"); ReactiveMongoDbMessageSource messageSource = new ReactiveMongoDbMessageSource(REACTIVE_MONGO_DATABASE_FACTORY, queryExpression); - messageSource.setBeanFactory(TEST_INTEGRATION_CONTEXT); + messageSource.setApplicationContext(TEST_INTEGRATION_CONTEXT); messageSource.afterPropertiesSet(); messageSource.setEntityClass(Person.class); @@ -208,7 +208,7 @@ void validatePipelineInModifyOut() { ReactiveMongoDbMessageSource messageSource = new ReactiveMongoDbMessageSource(REACTIVE_MONGO_DATABASE_FACTORY, queryExpression); messageSource.setExpectSingleResult(true); - messageSource.setBeanFactory(TEST_INTEGRATION_CONTEXT); + messageSource.setApplicationContext(TEST_INTEGRATION_CONTEXT); messageSource.afterPropertiesSet(); BasicDBObject result = waitFor((Mono) messageSource.receive().getPayload()); Object id = result.get("_id"); @@ -236,7 +236,7 @@ private Flux queryMultipleElements(Expression queryExpression, Optional< messageSource.setBeanFactory(TEST_INTEGRATION_CONTEXT); messageSource.setEntityClass(Person.class); converter.ifPresent(messageSource::setMongoConverter); - messageSource.setBeanFactory(TEST_INTEGRATION_CONTEXT); + messageSource.setApplicationContext(TEST_INTEGRATION_CONTEXT); messageSource.afterPropertiesSet(); return (Flux) messageSource.receive().getPayload(); diff --git a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageGroupStoreTests.java b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageGroupStoreTests.java index 28819f7a1fd..f463974bf68 100644 --- a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageGroupStoreTests.java +++ b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageGroupStoreTests.java @@ -33,6 +33,7 @@ class MongoDbMessageGroupStoreTests extends AbstractMongoDbMessageGroupStoreTest protected MongoDbMessageStore getMessageGroupStore() { MongoDbMessageStore mongoDbMessageStore = new MongoDbMessageStore(MONGO_DATABASE_FACTORY); + mongoDbMessageStore.setApplicationContext(testApplicationContext); mongoDbMessageStore.afterPropertiesSet(); return mongoDbMessageStore; } diff --git a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageStoreClaimCheckIntegrationTests.java b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageStoreClaimCheckIntegrationTests.java index 7d41bace964..56e37331cbd 100644 --- a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageStoreClaimCheckIntegrationTests.java +++ b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageStoreClaimCheckIntegrationTests.java @@ -63,6 +63,7 @@ public void tearDown() { @Test void stringPayload() { MongoDbMessageStore messageStore = new MongoDbMessageStore(MONGO_DATABASE_FACTORY); + messageStore.setApplicationContext(testApplicationContext); messageStore.afterPropertiesSet(); ClaimCheckInTransformer checkin = new ClaimCheckInTransformer(messageStore); ClaimCheckOutTransformer checkout = new ClaimCheckOutTransformer(messageStore); @@ -78,6 +79,7 @@ void stringPayload() { @Test void objectPayload() { MongoDbMessageStore messageStore = new MongoDbMessageStore(MONGO_DATABASE_FACTORY); + messageStore.setApplicationContext(testApplicationContext); messageStore.afterPropertiesSet(); ClaimCheckInTransformer checkin = new ClaimCheckInTransformer(messageStore); ClaimCheckOutTransformer checkout = new ClaimCheckOutTransformer(messageStore); diff --git a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageStoreTests.java b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageStoreTests.java index e6a62fc5d96..90d203b2101 100644 --- a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageStoreTests.java +++ b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageStoreTests.java @@ -40,6 +40,7 @@ class MongoDbMessageStoreTests extends AbstractMongoDbMessageStoreTests { @Override protected MessageStore getMessageStore() { MongoDbMessageStore mongoDbMessageStore = new MongoDbMessageStore(MONGO_DATABASE_FACTORY); + mongoDbMessageStore.setApplicationContext(testApplicationContext); mongoDbMessageStore.afterPropertiesSet(); return mongoDbMessageStore; } @@ -49,6 +50,7 @@ void testCustomConverter() throws InterruptedException { MongoDbMessageStore mongoDbMessageStore = new MongoDbMessageStore(MONGO_DATABASE_FACTORY); FooToBytesConverter fooToBytesConverter = new FooToBytesConverter(); mongoDbMessageStore.setCustomConverters(fooToBytesConverter); + mongoDbMessageStore.setApplicationContext(testApplicationContext); mongoDbMessageStore.afterPropertiesSet(); mongoDbMessageStore.addMessage(new GenericMessage<>(new Foo("foo"))); From a2ef5a958c6de8853c3eb605eb874d0ea5b8a47a Mon Sep 17 00:00:00 2001 From: Jiandong Ma Date: Sun, 20 Jul 2025 10:19:44 +0800 Subject: [PATCH 2/2] Address PR Comments Signed-off-by: Jiandong Ma --- .../mongodb/outbound/MongoDbOutboundGateway.java | 4 ++-- .../ReactiveMongoDbStoringMessageHandler.java | 3 +-- .../AbstractConfigurableMongoDbMessageStore.java | 13 ++++++------- .../mongodb/store/MongoDbMessageStore.java | 16 +++++++--------- 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MongoDbOutboundGateway.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MongoDbOutboundGateway.java index 683ae5b7245..57ec0550c1c 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MongoDbOutboundGateway.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MongoDbOutboundGateway.java @@ -164,8 +164,8 @@ protected void doInit() { Assert.notNull(collectionName, "'collectionNameExpression' cannot evaluate to null"); Object result; - if (this.collectionCallback != null) { - var collectionCallbackToUse = this.collectionCallback; + var collectionCallbackToUse = this.collectionCallback; + if (collectionCallbackToUse != null) { result = this.mongoTemplate.execute(collectionName, collection -> collectionCallbackToUse.doInCollection(collection, requestMessage)); } diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/ReactiveMongoDbStoringMessageHandler.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/ReactiveMongoDbStoringMessageHandler.java index 5c8acf824ba..a6f1fbca1e5 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/ReactiveMongoDbStoringMessageHandler.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/ReactiveMongoDbStoringMessageHandler.java @@ -110,8 +110,7 @@ protected void onInit() { super.onInit(); this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory()); if (this.mongoTemplate == null) { - Objects.requireNonNull(this.mongoDbFactory); - ReactiveMongoTemplate template = new ReactiveMongoTemplate(this.mongoDbFactory, this.mongoConverter); + ReactiveMongoTemplate template = new ReactiveMongoTemplate(Objects.requireNonNull(this.mongoDbFactory), this.mongoConverter); template.setApplicationContext(getApplicationContext()); this.mongoTemplate = template; } diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/AbstractConfigurableMongoDbMessageStore.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/AbstractConfigurableMongoDbMessageStore.java index 99501a5f04e..73ad1e76012 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/AbstractConfigurableMongoDbMessageStore.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/AbstractConfigurableMongoDbMessageStore.java @@ -224,16 +224,15 @@ public int messageGroupSize(Object groupId) { * The {@link #SEQUENCE_NAME} document is created on demand. * @return the next sequence value. */ + @SuppressWarnings("NullAway") protected long getNextId() { Query query = Query.query(Criteria.where("_id").is(SEQUENCE_NAME)); query.fields().include(MessageDocumentFields.SEQUENCE); - Map result = this.mongoTemplate.findAndModify(query, - new Update().inc(MessageDocumentFields.SEQUENCE, 1L), - FindAndModifyOptions.options().returnNew(true).upsert(true), - Map.class, this.collectionName); - Objects.requireNonNull(result); - return ((Number) Objects.requireNonNull(result - .get(MessageDocumentFields.SEQUENCE))) + return ((Number) this.mongoTemplate.findAndModify(query, + new Update().inc(MessageDocumentFields.SEQUENCE, 1L), + FindAndModifyOptions.options().returnNew(true).upsert(true), + Map.class, this.collectionName) + .get(MessageDocumentFields.SEQUENCE)) .longValue(); } diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoDbMessageStore.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoDbMessageStore.java index 68e7faaf92e..1a47119ae71 100644 --- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoDbMessageStore.java +++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoDbMessageStore.java @@ -509,24 +509,22 @@ private void updateGroup(Object groupId, Update update) { this.template.findAndModify(query, update, FindAndModifyOptions.none(), Map.class, this.collectionName); } + @SuppressWarnings("NullAway") private long getNextId() { Query query = Query.query(Criteria.where("_id").is(SEQUENCE_NAME)); query.fields().include(SEQUENCE); - Map result = this.template.findAndModify(query, - new Update().inc(SEQUENCE, 1L), - FindAndModifyOptions.options().returnNew(true).upsert(true), - Map.class, this.collectionName); - Objects.requireNonNull(result); - return ((Number) Objects.requireNonNull(result - .get(SEQUENCE))) + return ((Number) this.template.findAndModify(query, + new Update().inc(SEQUENCE, 1L), + FindAndModifyOptions.options().returnNew(true).upsert(true), + Map.class, this.collectionName) + .get(SEQUENCE)) .longValue(); } - @SuppressWarnings(UNCHECKED) + @SuppressWarnings({UNCHECKED, "NullAway"}) private static void enhanceHeaders(MessageHeaders messageHeaders, Map headers) { Map innerMap = (Map) new DirectFieldAccessor(messageHeaders).getPropertyValue(HEADERS); - Objects.requireNonNull(innerMap); // using reflection to set ID and TIMESTAMP since they are immutable through MessageHeaders Object idHeader = headers.get(MessageHeaders.ID); if (idHeader != null) {