diff --git a/consumer/spring-jdbc-consumer/README.adoc b/consumer/spring-jdbc-consumer/README.adoc index 14a3decf..ea972c42 100644 --- a/consumer/spring-jdbc-consumer/README.adoc +++ b/consumer/spring-jdbc-consumer/README.adoc @@ -5,7 +5,7 @@ The consumer uses the `JdbcMessageHandler` from Spring Integration. ## Beans for injection -You can import `JdbcConsumerConfiguration` in the application and then inject the following bean. +The `JdbcConsumerConfiguration` auto-configuration provides the following bean: `Consumer> jdbcConsumer` diff --git a/consumer/spring-jdbc-consumer/src/main/java/org/springframework/cloud/fn/consumer/jdbc/JdbcConsumerConfiguration.java b/consumer/spring-jdbc-consumer/src/main/java/org/springframework/cloud/fn/consumer/jdbc/JdbcConsumerConfiguration.java index 3befc0ca..57fc3b0e 100644 --- a/consumer/spring-jdbc-consumer/src/main/java/org/springframework/cloud/fn/consumer/jdbc/JdbcConsumerConfiguration.java +++ b/consumer/spring-jdbc-consumer/src/main/java/org/springframework/cloud/fn/consumer/jdbc/JdbcConsumerConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 the original author or authors. + * Copyright 2020-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,30 +29,28 @@ import javax.sql.DataSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ResourceLoader; import org.springframework.expression.EvaluationContext; import org.springframework.expression.EvaluationException; import org.springframework.expression.Expression; import org.springframework.expression.spel.SpelParseException; import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.integration.aggregator.DefaultAggregatingMessageGroupProcessor; import org.springframework.integration.aggregator.MessageCountReleaseStrategy; +import org.springframework.integration.annotation.MessagingGateway; import org.springframework.integration.config.AggregatorFactoryBean; +import org.springframework.integration.context.IntegrationContextUtils; import org.springframework.integration.dsl.IntegrationFlow; -import org.springframework.integration.dsl.IntegrationFlowBuilder; -import org.springframework.integration.expression.ExpressionUtils; import org.springframework.integration.expression.ValueExpression; import org.springframework.integration.jdbc.JdbcMessageHandler; import org.springframework.integration.jdbc.SqlParameterSourceFactory; -import org.springframework.integration.json.JsonPropertyAccessor; import org.springframework.integration.store.MessageGroupStore; import org.springframework.integration.store.SimpleMessageStore; import org.springframework.integration.support.MutableMessage; @@ -68,6 +66,8 @@ import org.springframework.util.MimeTypeUtils; import org.springframework.util.MultiValueMap; /** + * Auto-configuration for JDBC consumer. + * * @author Eric Bottard * @author Thomas Risberg * @author Robert St. John @@ -76,25 +76,20 @@ import org.springframework.util.MultiValueMap; * @author Soby Chacko * @author Szabolcs Stremler */ -@Configuration +@AutoConfiguration(after = DataSourceAutoConfiguration.class) @EnableConfigurationProperties(JdbcConsumerProperties.class) public class JdbcConsumerConfiguration { - private static final Log logger = LogFactory.getLog(JdbcConsumerConfiguration.class); + private static final Log LOGGER = LogFactory.getLog(JdbcConsumerConfiguration.class); private static final Object NOT_SET = new Object(); + private static final SpelExpressionParser EXPRESSION_PARSER = new SpelExpressionParser(); + private final JdbcConsumerProperties properties; - private SpelExpressionParser spelExpressionParser = new SpelExpressionParser(); - - private EvaluationContext evaluationContext; - - public JdbcConsumerConfiguration(JdbcConsumerProperties properties, BeanFactory beanFactory) { + public JdbcConsumerConfiguration(JdbcConsumerProperties properties) { this.properties = properties; - this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(beanFactory); - StandardEvaluationContext standardEvaluationContext = (StandardEvaluationContext) this.evaluationContext; - standardEvaluationContext.addPropertyAccessor(new JsonPropertyAccessor()); } @Bean @@ -128,18 +123,18 @@ public class JdbcConsumerConfiguration { IntegrationFlow jdbcConsumerFlow(@Qualifier("aggregator") MessageHandler aggregator, JdbcMessageHandler jdbcMessageHandler) { - final IntegrationFlowBuilder builder = IntegrationFlow.from(Consumer.class, - gateway -> gateway.beanName("jdbcConsumer")); - if (properties.getBatchSize() > 1 || properties.getIdleTimeout() > 0) { - builder.handle(aggregator); - } - return builder.handle(jdbcMessageHandler).get(); + return (flow) -> { + if (this.properties.getBatchSize() > 1 || this.properties.getIdleTimeout() > 0) { + flow.handle(aggregator); + } + flow.handle(jdbcMessageHandler); + }; } @Bean FactoryBean aggregator(MessageGroupStore messageGroupStore) { AggregatorFactoryBean aggregatorFactoryBean = new AggregatorFactoryBean(); - aggregatorFactoryBean.setCorrelationStrategy(message -> message.getPayload().getClass().getName()); + aggregatorFactoryBean.setCorrelationStrategy((message) -> message.getPayload().getClass().getName()); aggregatorFactoryBean.setReleaseStrategy(new MessageCountReleaseStrategy(this.properties.getBatchSize())); if (this.properties.getIdleTimeout() >= 0) { aggregatorFactoryBean.setGroupTimeoutExpression(new ValueExpression<>(this.properties.getIdleTimeout())); @@ -160,19 +155,20 @@ public class JdbcConsumerConfiguration { } @Bean - public JdbcMessageHandler jdbcMessageHandler(DataSource dataSource) { + public JdbcMessageHandler jdbcMessageHandler(DataSource dataSource, + @Qualifier(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME) EvaluationContext evaluationContext) { + final MultiValueMap columnExpressionVariations = new LinkedMultiValueMap<>(); for (Map.Entry entry : this.properties.getColumnsMap().entrySet()) { String value = entry.getValue(); - columnExpressionVariations.add(entry.getKey(), this.spelExpressionParser.parseExpression(value)); + columnExpressionVariations.add(entry.getKey(), EXPRESSION_PARSER.parseExpression(value)); if (!value.startsWith("payload")) { String qualified = "payload." + value; try { - columnExpressionVariations.add(entry.getKey(), - this.spelExpressionParser.parseExpression(qualified)); + columnExpressionVariations.add(entry.getKey(), EXPRESSION_PARSER.parseExpression(qualified)); } - catch (SpelParseException e) { - logger.info("failed to parse qualified fallback expression " + qualified + catch (SpelParseException ex) { + LOGGER.info("failed to parse qualified fallback expression " + qualified + "; be sure your expression uses the 'payload.' prefix where necessary"); } } @@ -191,10 +187,9 @@ public class JdbcConsumerConfiguration { if (message.getPayload() instanceof Iterable) { Stream messageStream = StreamSupport .stream(((Iterable) message.getPayload()).spliterator(), false) - .map(payload -> { - if (payload instanceof byte[]) { - return convertibleContentType(contentType) ? new String(((byte[]) payload)) - : payload; + .map((payload) -> { + if (payload instanceof byte[] bytes) { + return (convertibleContentType(contentType)) ? new String(bytes) : bytes; } else { return payload; @@ -205,7 +200,7 @@ public class JdbcConsumerConfiguration { } else { if (convertibleContentType(contentType)) { - convertedMessage = new MutableMessage<>(new String(((byte[]) message.getPayload())), + convertedMessage = new MutableMessage<>(new String((byte[]) message.getPayload()), message.getHeaders()); } } @@ -214,7 +209,7 @@ public class JdbcConsumerConfiguration { } }; SqlParameterSourceFactory parameterSourceFactory = new ParameterFactory(columnExpressionVariations, - this.evaluationContext); + evaluationContext); jdbcMessageHandler.setSqlParameterSourceFactory(parameterSourceFactory); return jdbcMessageHandler; } @@ -227,7 +222,7 @@ public class JdbcConsumerConfiguration { ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); databasePopulator.setIgnoreFailedDrops(true); dataSourceInitializer.setDatabasePopulator(databasePopulator); - if ("true".equals(properties.getInitialize())) { + if ("true".equals(this.properties.getInitialize())) { databasePopulator.addScript(new DefaultInitializationScriptResource(this.properties.getTableName(), this.properties.getColumnsMap().keySet())); } @@ -237,23 +232,19 @@ public class JdbcConsumerConfiguration { return dataSourceInitializer; } - private static final class ParameterFactory implements SqlParameterSourceFactory { + @MessagingGateway(name = "jdbcConsumer", defaultRequestChannel = "jdbcConsumerFlow.input") + public interface MessageConsumer extends Consumer> { - private final MultiValueMap columnExpressions; + } - private final EvaluationContext context; - - ParameterFactory(MultiValueMap columnExpressions, EvaluationContext context) { - this.columnExpressions = columnExpressions; - this.context = context; - } + private record ParameterFactory(MultiValueMap columnExpressions, + EvaluationContext context) implements SqlParameterSourceFactory { @Override public SqlParameterSource createParameterSource(Object o) { - if (!(o instanceof Message)) { + if (!(o instanceof Message message)) { throw new IllegalArgumentException("Unable to handle type " + o.getClass().getName()); } - Message message = (Message) o; MapSqlParameterSource parameterSource = new MapSqlParameterSource(); for (Map.Entry> entry : this.columnExpressions.entrySet()) { String key = entry.getKey(); @@ -262,16 +253,16 @@ public class JdbcConsumerConfiguration { EvaluationException lastException = null; for (Expression spel : spels) { try { - value = spel.getValue(context, message); + value = spel.getValue(this.context, message); break; } - catch (EvaluationException e) { - lastException = e; + catch (EvaluationException ex) { + lastException = ex; } } if (value == NOT_SET) { if (lastException != null) { - logger.info("Could not find value for column '" + key + "': " + lastException.getMessage()); + LOGGER.info("Could not find value for column '" + key + "': " + lastException.getMessage()); } parameterSource.addValue(key, null); } diff --git a/consumer/spring-jdbc-consumer/src/main/java/org/springframework/cloud/fn/consumer/jdbc/JdbcConsumerProperties.java b/consumer/spring-jdbc-consumer/src/main/java/org/springframework/cloud/fn/consumer/jdbc/JdbcConsumerProperties.java index 23c4b747..b429e5fa 100644 --- a/consumer/spring-jdbc-consumer/src/main/java/org/springframework/cloud/fn/consumer/jdbc/JdbcConsumerProperties.java +++ b/consumer/spring-jdbc-consumer/src/main/java/org/springframework/cloud/fn/consumer/jdbc/JdbcConsumerProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2020 the original author or authors. + * Copyright 2020-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; /** + * The configuration properties for JDBC consumer. + * * @author Eric Bottard * @author Artem Bilan * @author Oliver Flasch diff --git a/consumer/spring-jdbc-consumer/src/main/java/org/springframework/cloud/fn/consumer/jdbc/ShorthandMapConverter.java b/consumer/spring-jdbc-consumer/src/main/java/org/springframework/cloud/fn/consumer/jdbc/ShorthandMapConverter.java index 7bb966c0..59cf82a6 100644 --- a/consumer/spring-jdbc-consumer/src/main/java/org/springframework/cloud/fn/consumer/jdbc/ShorthandMapConverter.java +++ b/consumer/spring-jdbc-consumer/src/main/java/org/springframework/cloud/fn/consumer/jdbc/ShorthandMapConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2020 the original author or authors. + * Copyright 2020-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,7 +46,7 @@ public class ShorthandMapConverter implements Converter jdbcOperations.queryForObject("select count(*) from messages", Integer.class), - value -> value == numberOfInserts); + (value) -> value == numberOfInserts); } } diff --git a/consumer/spring-jdbc-consumer/src/test/java/org/springframework/cloud/fn/consumer/jdbc/JdbcConsumerApplicationTests.java b/consumer/spring-jdbc-consumer/src/test/java/org/springframework/cloud/fn/consumer/jdbc/JdbcConsumerApplicationTests.java index 259be577..30b1b335 100644 --- a/consumer/spring-jdbc-consumer/src/test/java/org/springframework/cloud/fn/consumer/jdbc/JdbcConsumerApplicationTests.java +++ b/consumer/spring-jdbc-consumer/src/test/java/org/springframework/cloud/fn/consumer/jdbc/JdbcConsumerApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2020 the original author or authors. + * Copyright 2020-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,7 +49,7 @@ public class JdbcConsumerApplicationTests { jdbcOperations.execute("DROP TABLE MESSAGES IF EXISTS"); } - static class Payload { + public static class Payload { private String a; diff --git a/consumer/spring-mongodb-consumer/README.adoc b/consumer/spring-mongodb-consumer/README.adoc index 236cf009..a7b61099 100644 --- a/consumer/spring-mongodb-consumer/README.adoc +++ b/consumer/spring-mongodb-consumer/README.adoc @@ -4,7 +4,7 @@ A consumer that allows you to insert records into MongoDB. ## Beans for injection -You can import `MongoDbConsumerConfiguration` in the application and then inject one of the following beans. +The `MongoDbConsumerConfiguration` auto-configuration provides the following beans: `Function, Mono> mongodbConsumerFunction` - Allows you to subscribe. @@ -18,13 +18,13 @@ The return value from the function can be ignored as this is used as a consumer All configuration properties are prefixed with `mongodb.consumer`. -For more information on the various options available, please see link:src/main/java/org/springframework/cloud/fn/consumer/mongo/MongoDBConsumerProperties.java[MongoDBConsumerProperties]. +For more information on the various options available, please see link:src/main/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerProperties.java[MongoDBConsumerProperties]. A `ComponentCustomizer` bean can be added in the target project to provide any custom options for the `ReactiveMongoDbStoringMessageHandler` configuration used by the `mongodbConsumer`. ## Examples -See this link:src/test/java/org/springframework/cloud/fn/consumer/mongo/MongoDBConsumerApplicationTests.java[test suite] for the various ways, this consumer is used. +See this link:src/test/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerApplicationTests.java[test suite] for the various ways, this consumer is used. ## Other usage diff --git a/consumer/spring-mongodb-consumer/src/main/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerConfiguration.java b/consumer/spring-mongodb-consumer/src/main/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerConfiguration.java index e50d3528..12aafdb2 100644 --- a/consumer/spring-mongodb-consumer/src/main/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerConfiguration.java +++ b/consumer/spring-mongodb-consumer/src/main/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 the original author or authors. + * Copyright 2017-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,10 +21,11 @@ import java.util.function.Function; import reactor.core.publisher.Mono; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.fn.common.config.ComponentCustomizer; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.expression.Expression; import org.springframework.expression.common.LiteralExpression; @@ -41,8 +42,8 @@ import org.springframework.messaging.ReactiveMessageHandler; * @author David Turanski * */ -@Configuration(proxyBeanMethods = false) -@EnableConfigurationProperties({ MongoDbConsumerProperties.class }) +@AutoConfiguration(after = MongoReactiveAutoConfiguration.class) +@EnableConfigurationProperties(MongoDbConsumerProperties.class) public class MongoDbConsumerConfiguration { private final MongoDbConsumerProperties properties; @@ -56,7 +57,7 @@ public class MongoDbConsumerConfiguration { @Bean public Consumer> mongodbConsumer(Function, Mono> mongodbConsumerFunction) { - return message -> mongodbConsumerFunction.apply(message).subscribe(); + return (message) -> mongodbConsumerFunction.apply(message).subscribe(); } @Bean diff --git a/consumer/spring-mongodb-consumer/src/main/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerProperties.java b/consumer/spring-mongodb-consumer/src/main/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerProperties.java index 26a99243..baa95a14 100644 --- a/consumer/spring-mongodb-consumer/src/main/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerProperties.java +++ b/consumer/spring-mongodb-consumer/src/main/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,8 @@ import org.springframework.util.StringUtils; import org.springframework.validation.annotation.Validated; /** + * The configuration properties for MongoDB consumer. + * * @author Artem Bilan * @author David Turanski * @@ -55,7 +57,7 @@ public class MongoDbConsumerProperties { } public Expression getCollectionExpression() { - return collectionExpression; + return this.collectionExpression; } @AssertTrue(message = "One of 'collection' or 'collectionExpression' is required") diff --git a/consumer/spring-mongodb-consumer/src/main/java/org/springframework/cloud/fn/consumer/mongo/package-info.java b/consumer/spring-mongodb-consumer/src/main/java/org/springframework/cloud/fn/consumer/mongo/package-info.java new file mode 100644 index 00000000..ee5d067e --- /dev/null +++ b/consumer/spring-mongodb-consumer/src/main/java/org/springframework/cloud/fn/consumer/mongo/package-info.java @@ -0,0 +1,4 @@ +/** + * The MongoDB consumer auto-configuration support. + */ +package org.springframework.cloud.fn.consumer.mongo; diff --git a/consumer/spring-mongodb-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/consumer/spring-mongodb-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..8d981d98 --- /dev/null +++ b/consumer/spring-mongodb-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.springframework.cloud.fn.consumer.mongo.MongoDbConsumerConfiguration diff --git a/consumer/spring-mongodb-consumer/src/test/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerApplicationTests.java b/consumer/spring-mongodb-consumer/src/test/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerApplicationTests.java index b5c8b581..cd269c3d 100644 --- a/consumer/spring-mongodb-consumer/src/test/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerApplicationTests.java +++ b/consumer/spring-mongodb-consumer/src/test/java/org/springframework/cloud/fn/consumer/mongo/MongoDbConsumerApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 the original author or authors. + * Copyright 2019-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,8 +33,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.messaging.Message; import org.springframework.messaging.support.GenericMessage; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.annotation.DirtiesContext; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; @@ -43,15 +42,10 @@ import static org.awaitility.Awaitility.await; * @author David Turanski * @author Chris Bono */ -@SpringBootTest(properties = { "mongodb.consumer.collection=testing" }) +@SpringBootTest(properties = "mongodb.consumer.collection=testing") +@DirtiesContext class MongoDbConsumerApplicationTests implements MongoDbTestContainerSupport { - @DynamicPropertySource - static void mongoDbProperties(DynamicPropertyRegistry registry) { - registry.add("spring.data.mongodb.port", MONGO_CONTAINER::getFirstMappedPort); - registry.add("spring.data.mongodb.database", () -> "test"); - } - @Autowired private MongoDbConsumerProperties properties; @@ -73,28 +67,26 @@ class MongoDbConsumerApplicationTests implements MongoDbTestContainerSupport { Flux> messages = Flux.just(new GenericMessage<>(data1), new GenericMessage<>(data2), new GenericMessage<>("{\"my_data\": \"THE DATA\"}")); - messages.map(message -> { + messages.map((message) -> { mongodbConsumer.accept(message); return message; }).subscribe(); await().timeout(Duration.ofSeconds(10)) - .until(() -> mongoTemplate.findAll(Document.class, properties.getCollection()).count().block() == 3L); + .untilAsserted( + () -> assertThat(mongoTemplate.findAll(Document.class, properties.getCollection()).count().block()) + .isEqualTo(3L)); StepVerifier .create(this.mongoTemplate.findAll(Document.class, properties.getCollection()) - .sort(Comparator.comparing(d -> d.get("_id").toString()))) - .assertNext(document -> { - assertThat(document.get("foo")).isEqualTo("bar"); - }) - .assertNext(document -> { + .sort(Comparator.comparing((d) -> d.get("_id").toString()))) + .assertNext((document) -> assertThat(document.get("foo")).isEqualTo("bar")) + .assertNext((document) -> { assertThat(document.get("firstName")).isEqualTo("Foo"); assertThat(document.get("lastName")).isEqualTo("Bar"); }) - .assertNext(document -> { - assertThat(document.get("my_data")).isEqualTo("THE DATA"); - }) + .assertNext((document) -> assertThat(document.get("my_data")).isEqualTo("THE DATA")) .verifyComplete(); } diff --git a/consumer/spring-mongodb-consumer/src/test/java/org/springframework/cloud/fn/consumer/mongo/MongoDbTestContainerSupport.java b/consumer/spring-mongodb-consumer/src/test/java/org/springframework/cloud/fn/consumer/mongo/MongoDbTestContainerSupport.java index 47396062..50adf3ee 100644 --- a/consumer/spring-mongodb-consumer/src/test/java/org/springframework/cloud/fn/consumer/mongo/MongoDbTestContainerSupport.java +++ b/consumer/spring-mongodb-consumer/src/test/java/org/springframework/cloud/fn/consumer/mongo/MongoDbTestContainerSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2022-2022 the original author or authors. + * Copyright 2022-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,13 @@ package org.springframework.cloud.fn.consumer.mongo; -import java.time.Duration; - import org.junit.jupiter.api.BeforeAll; import org.testcontainers.containers.MongoDBContainer; import org.testcontainers.junit.jupiter.Testcontainers; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; + /** * Provides a static {@link MongoDBContainer} that can be shared across test classes. * @@ -30,14 +31,19 @@ import org.testcontainers.junit.jupiter.Testcontainers; @Testcontainers(disabledWithoutDocker = true) public interface MongoDbTestContainerSupport { - MongoDBContainer MONGO_CONTAINER = new MongoDBContainer("mongo:6.0.6").withStartupTimeout(Duration.ofSeconds(120)) - .withStartupAttempts(3); + MongoDBContainer MONGO_CONTAINER = new MongoDBContainer("mongo"); @BeforeAll static void startContainer() { MONGO_CONTAINER.start(); } + @DynamicPropertySource + static void mongoDbProperties(DynamicPropertyRegistry registry) { + registry.add("spring.data.mongodb.port", MONGO_CONTAINER::getFirstMappedPort); + registry.add("spring.data.mongodb.database", () -> "test"); + } + static String mongoDbUri() { return "mongodb://localhost:" + MONGO_CONTAINER.getFirstMappedPort(); } diff --git a/function/spring-splitter-function/README.adoc b/function/spring-splitter-function/README.adoc index 7c28989d..7a093687 100644 --- a/function/spring-splitter-function/README.adoc +++ b/function/spring-splitter-function/README.adoc @@ -4,7 +4,7 @@ This module provides a header enricher function that can be reused and composed ## Beans for injection -You can import the `SpliiterFunctionConfiguration` in a Spring Boot application and then inject the following bean. +The `SpliiterFunctionConfiguration` auto-configuration provides the following bean: `splitterFunction` diff --git a/function/spring-splitter-function/src/main/java/org/springframework/cloud/fn/splitter/SplitterFunctionConfiguration.java b/function/spring-splitter-function/src/main/java/org/springframework/cloud/fn/splitter/SplitterFunctionConfiguration.java index da1f82cf..2faf4829 100644 --- a/function/spring-splitter-function/src/main/java/org/springframework/cloud/fn/splitter/SplitterFunctionConfiguration.java +++ b/function/spring-splitter-function/src/main/java/org/springframework/cloud/fn/splitter/SplitterFunctionConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,14 +23,13 @@ import java.util.function.Function; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; -import org.springframework.context.annotation.Configuration; -import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.integration.channel.ReactiveStreamsSubscribableChannel; import org.springframework.integration.file.splitter.FileSplitter; import org.springframework.integration.splitter.AbstractMessageSplitter; @@ -39,7 +38,13 @@ import org.springframework.integration.splitter.ExpressionEvaluatingSplitter; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; -@Configuration +/** + * Auto-configuration for Splitter function. + * + * @author Artem Bilan + * @author Soby Chacko + */ +@AutoConfiguration @EnableConfigurationProperties(SplitterFunctionProperties.class) public class SplitterFunctionConfiguration { @@ -50,7 +55,7 @@ public class SplitterFunctionConfiguration { messageSplitter.setApplySequence(splitterFunctionProperties.isApplySequence()); ThreadLocalFluxSinkMessageChannel outputChannel = new ThreadLocalFluxSinkMessageChannel(); messageSplitter.setOutputChannel(outputChannel); - return message -> { + return (message) -> { messageSplitter.handleMessage(message); return outputChannel.publisherThreadLocal.get(); }; @@ -59,8 +64,7 @@ public class SplitterFunctionConfiguration { @Bean @ConditionalOnProperty(prefix = "splitter", name = "expression") public AbstractMessageSplitter expressionSplitter(SplitterFunctionProperties splitterFunctionProperties) { - return new ExpressionEvaluatingSplitter( - new SpelExpressionParser().parseExpression(splitterFunctionProperties.getExpression())); + return new ExpressionEvaluatingSplitter(splitterFunctionProperties.getExpression()); } @Bean diff --git a/function/spring-splitter-function/src/main/java/org/springframework/cloud/fn/splitter/SplitterFunctionProperties.java b/function/spring-splitter-function/src/main/java/org/springframework/cloud/fn/splitter/SplitterFunctionProperties.java index 088eac1b..88768290 100644 --- a/function/spring-splitter-function/src/main/java/org/springframework/cloud/fn/splitter/SplitterFunctionProperties.java +++ b/function/spring-splitter-function/src/main/java/org/springframework/cloud/fn/splitter/SplitterFunctionProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,10 +19,11 @@ package org.springframework.cloud.fn.splitter; import jakarta.validation.constraints.AssertTrue; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.expression.Expression; import org.springframework.validation.annotation.Validated; /** - * Configuration properties for the Splitter Processor app. + * Configuration properties for the Splitter function. * * @author Gary Russell * @author Artem Bilan @@ -34,7 +35,7 @@ public class SplitterFunctionProperties { /** * A SpEL expression for splitting payloads. */ - private String expression; + private Expression expression; /** * When expression is null, delimiters to use when tokenizing {@link String} payloads. @@ -63,11 +64,11 @@ public class SplitterFunctionProperties { */ private boolean applySequence = true; - public String getExpression() { + public Expression getExpression() { return this.expression; } - public void setExpression(String expression) { + public void setExpression(Expression expression) { this.expression = expression; } diff --git a/function/spring-splitter-function/src/main/java/org/springframework/cloud/fn/splitter/package-info.java b/function/spring-splitter-function/src/main/java/org/springframework/cloud/fn/splitter/package-info.java new file mode 100644 index 00000000..59f57f23 --- /dev/null +++ b/function/spring-splitter-function/src/main/java/org/springframework/cloud/fn/splitter/package-info.java @@ -0,0 +1,4 @@ +/** + * The Splitter function auto-configuration support. + */ +package org.springframework.cloud.fn.splitter; diff --git a/function/spring-splitter-function/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/function/spring-splitter-function/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..b51f3ee8 --- /dev/null +++ b/function/spring-splitter-function/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.springframework.cloud.fn.splitter.SplitterFunctionConfiguration diff --git a/function/spring-splitter-function/src/test/java/org/springframework/cloud/fn/splitter/SplitterFunctionApplicationTests.java b/function/spring-splitter-function/src/test/java/org/springframework/cloud/fn/splitter/SplitterFunctionApplicationTests.java index e90878a4..910b1645 100644 --- a/function/spring-splitter-function/src/test/java/org/springframework/cloud/fn/splitter/SplitterFunctionApplicationTests.java +++ b/function/spring-splitter-function/src/test/java/org/springframework/cloud/fn/splitter/SplitterFunctionApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,7 +40,7 @@ public class SplitterFunctionApplicationTests { @Test public void testExpressionSplitter() { List> messageList = this.splitter.apply(new GenericMessage<>("hello,world")); - assertThat(messageList).extracting(m -> m.getPayload().toString()).contains("hello", "world"); + assertThat(messageList).extracting((m) -> m.getPayload().toString()).contains("hello", "world"); } @SpringBootApplication diff --git a/supplier/spring-jdbc-supplier/README.adoc b/supplier/spring-jdbc-supplier/README.adoc index beba5d73..76bbbdec 100644 --- a/supplier/spring-jdbc-supplier/README.adoc +++ b/supplier/spring-jdbc-supplier/README.adoc @@ -7,7 +7,7 @@ When you have use-cases such as periodical execution of a Database query, based ## Beans for injection -You can import the `JdbcSupplierConfiguration` in the application and then inject the following bean. +The `JdbcSupplierConfiguration` auto-configuration provides the following bean: `jdbcSupplier` diff --git a/supplier/spring-jdbc-supplier/src/main/java/org/springframework/cloud/fn/supplier/jdbc/JdbcSupplierConfiguration.java b/supplier/spring-jdbc-supplier/src/main/java/org/springframework/cloud/fn/supplier/jdbc/JdbcSupplierConfiguration.java index d4b40631..3f157e10 100644 --- a/supplier/spring-jdbc-supplier/src/main/java/org/springframework/cloud/fn/supplier/jdbc/JdbcSupplierConfiguration.java +++ b/supplier/spring-jdbc-supplier/src/main/java/org/springframework/cloud/fn/supplier/jdbc/JdbcSupplierConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 the original author or authors. + * Copyright 2019-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,26 +24,27 @@ import javax.sql.DataSource; import reactor.core.publisher.Flux; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.fn.common.config.ComponentCustomizer; import org.springframework.cloud.fn.splitter.SplitterFunctionConfiguration; import org.springframework.cloud.function.context.PollableBean; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.integration.core.MessageSource; import org.springframework.integration.jdbc.JdbcPollingChannelAdapter; import org.springframework.lang.Nullable; import org.springframework.messaging.Message; /** + * JDBC supplier auto-configuration. + * * @author Soby Chacko * @author Artem Bilan */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration(after = { DataSourceAutoConfiguration.class, SplitterFunctionConfiguration.class }) @EnableConfigurationProperties(JdbcSupplierProperties.class) -@Import(SplitterFunctionConfiguration.class) public class JdbcSupplierConfiguration { private final JdbcSupplierProperties properties; @@ -74,12 +75,12 @@ public class JdbcSupplierConfiguration { @ConditionalOnProperty(prefix = "jdbc.supplier", name = "split", matchIfMissing = true) public Supplier>> splittedSupplier(MessageSource jdbcMessageSource, Function, List>> splitterFunction) { + return () -> { Message received = jdbcMessageSource.receive(); if (received != null) { - return Flux.fromIterable(splitterFunction.apply(received)); // multiple - // Message> + // multiple Message> + return Flux.fromIterable(splitterFunction.apply(received)); } else { return Flux.empty(); diff --git a/supplier/spring-jdbc-supplier/src/main/java/org/springframework/cloud/fn/supplier/jdbc/JdbcSupplierProperties.java b/supplier/spring-jdbc-supplier/src/main/java/org/springframework/cloud/fn/supplier/jdbc/JdbcSupplierProperties.java index 45d0ed8f..fa983697 100644 --- a/supplier/spring-jdbc-supplier/src/main/java/org/springframework/cloud/fn/supplier/jdbc/JdbcSupplierProperties.java +++ b/supplier/spring-jdbc-supplier/src/main/java/org/springframework/cloud/fn/supplier/jdbc/JdbcSupplierProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.validation.annotation.Validated; /** + * JDBC supplier configuration properties. + * * @author Soby Chacko * @author Artem Bilan */ @@ -51,7 +53,7 @@ public class JdbcSupplierProperties { @NotNull public String getQuery() { - return query; + return this.query; } public void setQuery(String query) { @@ -59,7 +61,7 @@ public class JdbcSupplierProperties { } public String getUpdate() { - return update; + return this.update; } public void setUpdate(String update) { @@ -67,7 +69,7 @@ public class JdbcSupplierProperties { } public boolean isSplit() { - return split; + return this.split; } public void setSplit(boolean split) { @@ -75,7 +77,7 @@ public class JdbcSupplierProperties { } public int getMaxRows() { - return maxRows; + return this.maxRows; } public void setMaxRows(int maxRows) { diff --git a/supplier/spring-jdbc-supplier/src/main/java/org/springframework/cloud/fn/supplier/jdbc/package-info.java b/supplier/spring-jdbc-supplier/src/main/java/org/springframework/cloud/fn/supplier/jdbc/package-info.java new file mode 100644 index 00000000..dac436de --- /dev/null +++ b/supplier/spring-jdbc-supplier/src/main/java/org/springframework/cloud/fn/supplier/jdbc/package-info.java @@ -0,0 +1,4 @@ +/** + * The JDBC supplier auto-configuration support. + */ +package org.springframework.cloud.fn.supplier.jdbc; diff --git a/supplier/spring-jdbc-supplier/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/supplier/spring-jdbc-supplier/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..4574494f --- /dev/null +++ b/supplier/spring-jdbc-supplier/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.springframework.cloud.fn.supplier.jdbc.JdbcSupplierConfiguration diff --git a/supplier/spring-jdbc-supplier/src/main/resources/application.properties b/supplier/spring-jdbc-supplier/src/main/resources/application.properties deleted file mode 100644 index 532da3b2..00000000 --- a/supplier/spring-jdbc-supplier/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.integration.jdbc.initialize-schema=NEVER diff --git a/supplier/spring-jdbc-supplier/src/test/java/org/springframework/cloud/fn/supplier/jdbc/DefaultJdbcSupplierTests.java b/supplier/spring-jdbc-supplier/src/test/java/org/springframework/cloud/fn/supplier/jdbc/DefaultJdbcSupplierTests.java index d56c0ccc..87b29f1b 100644 --- a/supplier/spring-jdbc-supplier/src/test/java/org/springframework/cloud/fn/supplier/jdbc/DefaultJdbcSupplierTests.java +++ b/supplier/spring-jdbc-supplier/src/test/java/org/springframework/cloud/fn/supplier/jdbc/DefaultJdbcSupplierTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 the original author or authors. + * Copyright 2020-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,16 +26,13 @@ import reactor.test.StepVerifier; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.messaging.Message; import org.springframework.test.annotation.DirtiesContext; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, - properties = "jdbc.supplier.query=select id, name from test order by id") +@SpringBootTest(properties = "jdbc.supplier.query=select id, name from test order by id") @DirtiesContext public class DefaultJdbcSupplierTests { @@ -46,22 +43,22 @@ public class DefaultJdbcSupplierTests { JdbcTemplate jdbcTemplate; @Test - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings("rawtypes") void testExtraction() { final Flux> messageFlux = jdbcSupplier.get(); StepVerifier stepVerifier = StepVerifier.create(messageFlux) .assertNext((message) -> assertThat(message) - .satisfies((msg) -> assertThat(msg).extracting(Message::getPayload).matches(o -> { + .satisfies((msg) -> assertThat(msg).extracting(Message::getPayload).matches((o) -> { Map map = (Map) o; return map.get("ID").equals(1L) && map.get("NAME").equals("Bob"); }))) .assertNext((message) -> assertThat(message) - .satisfies((msg) -> assertThat(msg).extracting(Message::getPayload).matches(o -> { + .satisfies((msg) -> assertThat(msg).extracting(Message::getPayload).matches((o) -> { Map map = (Map) o; return map.get("ID").equals(2L) && map.get("NAME").equals("Jane"); }))) .assertNext((message) -> assertThat(message) - .satisfies((msg) -> assertThat(msg).extracting(Message::getPayload).matches(o -> { + .satisfies((msg) -> assertThat(msg).extracting(Message::getPayload).matches((o) -> { Map map = (Map) o; return map.get("ID").equals(3L) && map.get("NAME").equals("John"); }))) @@ -70,20 +67,6 @@ public class DefaultJdbcSupplierTests { stepVerifier.verify(); } - /* - * The test to verify that DB is not initialized with Spring Integration DDL - * (spring.integration.jdbc.initialize-schema=NEVER) what happens by default via - * IntegrationAutoConfiguration.IntegrationJdbcConfiguration. This is not a - * functionality of this JDBC Supplier. - */ - @Test - void verifyNoIntMessageGroupTable() { - assertThatExceptionOfType(BadSqlGrammarException.class) - .isThrownBy(() -> this.jdbcTemplate.queryForList("SELECT * FROM INT_MESSAGE_GROUP")) - .havingCause() - .withMessageContaining("Table \"INT_MESSAGE_GROUP\" not found;"); - } - @SpringBootApplication static class JdbcSupplierTestApplication { diff --git a/supplier/spring-jdbc-supplier/src/test/java/org/springframework/cloud/fn/supplier/jdbc/NonSplitJdbcSupplierTests.java b/supplier/spring-jdbc-supplier/src/test/java/org/springframework/cloud/fn/supplier/jdbc/NonSplitJdbcSupplierTests.java index 9ed42f97..c9a12e31 100644 --- a/supplier/spring-jdbc-supplier/src/test/java/org/springframework/cloud/fn/supplier/jdbc/NonSplitJdbcSupplierTests.java +++ b/supplier/spring-jdbc-supplier/src/test/java/org/springframework/cloud/fn/supplier/jdbc/NonSplitJdbcSupplierTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2020 the original author or authors. + * Copyright 2020-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,7 +34,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Soby Chacko * @author Artem Bilan */ -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, +@SpringBootTest( properties = { "jdbc.supplier.query=select id, name from test order by id", "jdbc.supplier.split=false" }) @DirtiesContext public class NonSplitJdbcSupplierTests { diff --git a/supplier/spring-mongodb-supplier/README.adoc b/supplier/spring-mongodb-supplier/README.adoc index 79fc60fc..fb9c24ad 100644 --- a/supplier/spring-mongodb-supplier/README.adoc +++ b/supplier/spring-mongodb-supplier/README.adoc @@ -7,7 +7,7 @@ When you have use-cases such as periodical execution of querying MongoDB, based ## Beans for injection -You can import the `MongoDBSupplierConfiguration` in the application and then inject the following bean. +The `MongoDBSupplierConfiguration` auto-configuration provides the following bean: `mongoDBSupplier` diff --git a/supplier/spring-mongodb-supplier/src/main/java/org/springframework/cloud/fn/supplier/mongo/MongodbSupplierConfiguration.java b/supplier/spring-mongodb-supplier/src/main/java/org/springframework/cloud/fn/supplier/mongo/MongodbSupplierConfiguration.java index 77bbadef..693a461b 100644 --- a/supplier/spring-mongodb-supplier/src/main/java/org/springframework/cloud/fn/supplier/mongo/MongodbSupplierConfiguration.java +++ b/supplier/spring-mongodb-supplier/src/main/java/org/springframework/cloud/fn/supplier/mongo/MongodbSupplierConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 the original author or authors. + * Copyright 2019-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,14 +22,14 @@ import java.util.function.Supplier; import reactor.core.publisher.Flux; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.fn.common.config.ComponentCustomizer; import org.springframework.cloud.fn.splitter.SplitterFunctionConfiguration; import org.springframework.cloud.function.context.PollableBean; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.expression.Expression; import org.springframework.expression.common.LiteralExpression; @@ -38,17 +38,15 @@ import org.springframework.lang.Nullable; import org.springframework.messaging.Message; /** - * A configuration for MongoDB Source applications. Produces {@link MongoDbMessageSource} - * which polls collection with the query after startup according to the polling - * properties. + * Auto-configuration for MongoDB supplier. Produces {@link MongoDbMessageSource} which + * polls collection with the query after startup according to the polling properties. * * @author Adam Zwickey * @author Artem Bilan * @author David Turanski */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration(after = { MongoAutoConfiguration.class, SplitterFunctionConfiguration.class }) @EnableConfigurationProperties({ MongodbSupplierProperties.class }) -@Import(SplitterFunctionConfiguration.class) public class MongodbSupplierConfiguration { private final MongodbSupplierProperties properties; @@ -69,9 +67,8 @@ public class MongodbSupplierConfiguration { return () -> { Message received = mongoDbSource.receive(); if (received != null) { - return Flux.fromIterable(splitterFunction.apply(received)); // multiple - // Message> + // multiple Message> + return Flux.fromIterable(splitterFunction.apply(received)); } else { return Flux.empty(); @@ -89,8 +86,8 @@ public class MongodbSupplierConfiguration { public MongoDbMessageSource mongoDbSource( @Nullable ComponentCustomizer mongoDbMessageSourceCustomizer) { - Expression queryExpression = (this.properties.getQueryExpression() != null - ? this.properties.getQueryExpression() : new LiteralExpression(this.properties.getQuery())); + Expression queryExpression = (this.properties.getQueryExpression() != null) + ? this.properties.getQueryExpression() : new LiteralExpression(this.properties.getQuery()); MongoDbMessageSource mongoDbMessageSource = new MongoDbMessageSource(this.mongoTemplate, queryExpression); mongoDbMessageSource.setCollectionNameExpression(new LiteralExpression(this.properties.getCollection())); mongoDbMessageSource.setEntityClass(String.class); diff --git a/supplier/spring-mongodb-supplier/src/main/java/org/springframework/cloud/fn/supplier/mongo/MongodbSupplierProperties.java b/supplier/spring-mongodb-supplier/src/main/java/org/springframework/cloud/fn/supplier/mongo/MongodbSupplierProperties.java index 67fd31c1..35383158 100644 --- a/supplier/spring-mongodb-supplier/src/main/java/org/springframework/cloud/fn/supplier/mongo/MongodbSupplierProperties.java +++ b/supplier/spring-mongodb-supplier/src/main/java/org/springframework/cloud/fn/supplier/mongo/MongodbSupplierProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 the original author or authors. + * Copyright 2016-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,8 @@ import org.springframework.expression.Expression; import org.springframework.validation.annotation.Validated; /** + * The MongoDB supplier configuration properties. + * * @author Adam Zwickey * @author Artem Bilan * @author Chris Schaefer @@ -60,7 +62,7 @@ public class MongodbSupplierProperties { @NotEmpty(message = "Query is required") public String getQuery() { - return query; + return this.query; } public void setQuery(String query) { @@ -68,7 +70,7 @@ public class MongodbSupplierProperties { } public Expression getQueryExpression() { - return queryExpression; + return this.queryExpression; } public void setQueryExpression(Expression queryExpression) { @@ -77,7 +79,7 @@ public class MongodbSupplierProperties { @NotBlank(message = "Collection name is required") public String getCollection() { - return collection; + return this.collection; } public void setCollection(String collection) { @@ -85,7 +87,7 @@ public class MongodbSupplierProperties { } public boolean isSplit() { - return split; + return this.split; } public void setSplit(boolean split) { diff --git a/supplier/spring-mongodb-supplier/src/main/java/org/springframework/cloud/fn/supplier/mongo/package-info.java b/supplier/spring-mongodb-supplier/src/main/java/org/springframework/cloud/fn/supplier/mongo/package-info.java new file mode 100644 index 00000000..f809a3b4 --- /dev/null +++ b/supplier/spring-mongodb-supplier/src/main/java/org/springframework/cloud/fn/supplier/mongo/package-info.java @@ -0,0 +1,4 @@ +/** + * The MongoDB supplier auto-configuration support. + */ +package org.springframework.cloud.fn.supplier.mongo; diff --git a/supplier/spring-mongodb-supplier/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/supplier/spring-mongodb-supplier/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..9aaaa884 --- /dev/null +++ b/supplier/spring-mongodb-supplier/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.springframework.cloud.fn.supplier.mongo.MongodbSupplierConfiguration diff --git a/supplier/spring-mongodb-supplier/src/main/resources/application.properties b/supplier/spring-mongodb-supplier/src/main/resources/application.properties deleted file mode 100644 index 8b137891..00000000 --- a/supplier/spring-mongodb-supplier/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/supplier/spring-mongodb-supplier/src/test/java/org/springframework/cloud/fn/supplier/mongo/MongodbSupplierApplicationTests.java b/supplier/spring-mongodb-supplier/src/test/java/org/springframework/cloud/fn/supplier/mongo/MongodbSupplierApplicationTests.java index e66fd152..efc98c56 100644 --- a/supplier/spring-mongodb-supplier/src/test/java/org/springframework/cloud/fn/supplier/mongo/MongodbSupplierApplicationTests.java +++ b/supplier/spring-mongodb-supplier/src/test/java/org/springframework/cloud/fn/supplier/mongo/MongodbSupplierApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 the original author or authors. + * Copyright 2019-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,8 +34,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.fn.consumer.mongo.MongoDbTestContainerSupport; import org.springframework.messaging.Message; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; @@ -43,14 +43,9 @@ import static org.assertj.core.api.Assertions.entry; @SpringBootTest( properties = { "mongodb.supplier.collection=testing", "mongodb.supplier.query={ name: { $exists: true }}", "mongodb.supplier.update-expression='{ $unset: { name: 0 } }'" }) +@DirtiesContext class MongodbSupplierApplicationTests implements MongoDbTestContainerSupport { - @DynamicPropertySource - static void mongoDbProperties(DynamicPropertyRegistry registry) { - registry.add("spring.data.mongodb.port", MONGO_CONTAINER::getFirstMappedPort); - registry.add("spring.data.mongodb.database", () -> "test"); - } - private final ObjectMapper objectMapper = new ObjectMapper(); @Autowired @@ -60,7 +55,7 @@ class MongodbSupplierApplicationTests implements MongoDbTestContainerSupport { private MongoClient mongo; @BeforeEach - public void setUp() { + void setUp() { MongoDatabase database = this.mongo.getDatabase("test"); database.createCollection("testing"); MongoCollection collection = database.getCollection("testing"); @@ -91,8 +86,8 @@ class MongodbSupplierApplicationTests implements MongoDbTestContainerSupport { try { map = objectMapper.readValue(message.getPayload().toString(), Map.class); } - catch (Exception e) { - e.printStackTrace(); + catch (Exception ex) { + ReflectionUtils.rethrowRuntimeException(ex); } return map; }