mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-17 12:09:16 +00:00
Add support for Spring Batch MongoDB
This commit adds support for running Spring Batch jobs with a MongoDB store. It aligns as much as possible to the JDBC counterpart, with spring-boot-starter-batch-data-mongodb and spring-boot-starter-batch-data-mongodb-test. As we do not have a way to initialize a MongoDB store at the moment, this commit adds a conservative approach of executing commands defined by the standard Spring Batch schema script. Closes gh-43236
This commit is contained in:
+1
@@ -117,6 +117,7 @@ apiref-openjdk=https://docs.oracle.com/en/java/javase/17/docs/api
|
||||
|
||||
code-spring-boot=https://github.com/{github-repo}/tree/{github-ref}
|
||||
code-spring-boot-autoconfigure-src={code-spring-boot}/core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure
|
||||
code-spring-boot-batch-data-mongodb-src={code-spring-boot}/module/spring-boot-batch-data-mongodb/src/main/java/org/springframework/boot/batch/mongodb
|
||||
code-spring-boot-batch-jdbc-src={code-spring-boot}/module/spring-boot-batch-jdbc/src/main/java/org/springframework/boot/batch/jdbc
|
||||
code-spring-boot-batch-src={code-spring-boot}/module/spring-boot-batch/src/main/java/org/springframework/boot/batch
|
||||
code-spring-boot-freemarker-src={code-spring-boot}/module/spring-boot-freemarker/src/main/java/org/springframework/boot/freemarker
|
||||
|
||||
@@ -235,6 +235,7 @@ dependencies {
|
||||
javadocMacros(project(":module:spring-boot-activemq"))
|
||||
javadocMacros(project(":module:spring-boot-artemis"))
|
||||
javadocMacros(project(":module:spring-boot-batch"))
|
||||
javadocMacros(project(":module:spring-boot-batch-data-mongodb"))
|
||||
javadocMacros(project(":module:spring-boot-batch-jdbc"))
|
||||
javadocMacros(project(":module:spring-boot-cache-test"))
|
||||
javadocMacros(project(":module:spring-boot-data-r2dbc-test"))
|
||||
|
||||
+15
-2
@@ -7,6 +7,7 @@ When building a batch application, the following stores can be auto-configured:
|
||||
|
||||
* In-memory
|
||||
* JDBC
|
||||
* MongoDB
|
||||
|
||||
Each store has specific additional settings.
|
||||
For instance, it is possible to customize the tables prefix for the JDBC store, as shown in the following example:
|
||||
@@ -19,8 +20,20 @@ spring:
|
||||
table-prefix: "CUSTOM_"
|
||||
----
|
||||
|
||||
When using the MongoDB store, you can enable initialization of the Spring Batch job repository schema (collections and indexes):
|
||||
|
||||
[configprops,yaml]
|
||||
----
|
||||
spring:
|
||||
batch:
|
||||
data:
|
||||
mongodb:
|
||||
schema:
|
||||
initialize: true
|
||||
----
|
||||
|
||||
To disable Spring Boot's auto-configuration and take complete control of Spring Batch's configuration, add javadoc:org.springframework.batch.core.configuration.annotation.EnableBatchProcessing[format=annotation] to one of your javadoc:org.springframework.context.annotation.Configuration[format=annotation] classes or extend javadoc:org.springframework.batch.core.configuration.support.DefaultBatchConfiguration[].
|
||||
This will cause the auto-configuration to back off, including initialization of Spring Batch's database schema if you're using the JDBC-based store.
|
||||
This will cause the auto-configuration to back off, including initialization of Spring Batch's database schema (JDBC or MongoDB).
|
||||
Spring Batch can then be configured using the `@Enable*JobRepository` annotation's attributes rather than the previously described configuration properties.
|
||||
|
||||
To learn more about manually configuring Spring Batch, see the API documentation of:
|
||||
@@ -50,4 +63,4 @@ spring:
|
||||
enabled: false
|
||||
----
|
||||
|
||||
See {code-spring-boot-batch-src}/autoconfigure/BatchAutoConfiguration.java[`BatchAutoConfiguration`] and {code-spring-boot-batch-jdbc-src}/autoconfigure/BatchJdbcAutoConfiguration.java[`BatchJdbcAutoConfiguration`] for more details.
|
||||
See {code-spring-boot-batch-src}/autoconfigure/BatchAutoConfiguration.java[`BatchAutoConfiguration`], {code-spring-boot-batch-jdbc-src}/autoconfigure/BatchJdbcAutoConfiguration.java[`BatchJdbcAutoConfiguration`], and {code-spring-boot-batch-data-mongodb-src}/autoconfigure/BatchDataMongoAutoConfiguration.java[`BatchDataMongoAutoConfiguration`] for more details.
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License);
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id "java-library"
|
||||
id "org.springframework.boot.auto-configuration"
|
||||
id "org.springframework.boot.configuration-properties"
|
||||
id "org.springframework.boot.deployed"
|
||||
id "org.springframework.boot.docker-test"
|
||||
id "org.springframework.boot.optional-dependencies"
|
||||
}
|
||||
|
||||
description = "Spring Boot Batch Data MongoDB"
|
||||
|
||||
dependencies {
|
||||
api(project(":module:spring-boot-batch"))
|
||||
api(project(":module:spring-boot-data-mongodb"))
|
||||
|
||||
optional(project(":core:spring-boot-autoconfigure"))
|
||||
optional("org.mongodb:mongodb-driver-sync")
|
||||
|
||||
dockerTestImplementation(project(":core:spring-boot-test"))
|
||||
dockerTestImplementation(project(":test-support:spring-boot-docker-test-support"))
|
||||
dockerTestImplementation("org.mongodb:mongodb-driver-sync")
|
||||
dockerTestImplementation("org.testcontainers:testcontainers-junit-jupiter")
|
||||
dockerTestImplementation("org.testcontainers:testcontainers-mongodb")
|
||||
|
||||
testImplementation(project(":core:spring-boot-test"))
|
||||
testImplementation(project(":test-support:spring-boot-test-support"))
|
||||
|
||||
testRuntimeOnly("ch.qos.logback:logback-classic")
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.batch.mongodb.autoconfigure;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.testcontainers.mongodb.MongoDBContainer;
|
||||
|
||||
import org.springframework.batch.core.job.Job;
|
||||
import org.springframework.batch.core.job.JobExecution;
|
||||
import org.springframework.batch.core.job.builder.JobBuilder;
|
||||
import org.springframework.batch.core.job.parameters.JobParameters;
|
||||
import org.springframework.batch.core.job.parameters.JobParametersBuilder;
|
||||
import org.springframework.batch.core.launch.JobOperator;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.step.builder.StepBuilder;
|
||||
import org.springframework.batch.infrastructure.repeat.RepeatStatus;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.data.mongodb.autoconfigure.DataMongoAutoConfiguration;
|
||||
import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link BatchDataMongoAutoConfiguration}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class BatchDataMongoAutoConfigurationIntegrationTests {
|
||||
|
||||
@Container
|
||||
static final MongoDBContainer mongoDb = TestImage.container(MongoDBContainer.class).withReplicaSet();
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withUserConfiguration(JobConfiguration.class)
|
||||
.withPropertyValues("spring.batch.data.mongodb.schema.initialize=true",
|
||||
"spring.mongodb.uri=" + mongoDb.getReplicaSetUrl())
|
||||
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, DataMongoAutoConfiguration.class,
|
||||
BatchDataMongoAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runJob() {
|
||||
this.contextRunner.withUserConfiguration(JobConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(JobOperator.class)
|
||||
.hasSingleBean(JobRepository.class)
|
||||
.hasSingleBean(Job.class);
|
||||
|
||||
JobParameters jobParameters = new JobParametersBuilder().addString("name", "foo")
|
||||
.addLocalDateTime("runtime", LocalDateTime.now())
|
||||
.toJobParameters();
|
||||
JobExecution jobExecution = context.getBean(JobOperator.class)
|
||||
.start(context.getBean(Job.class), jobParameters);
|
||||
|
||||
assertThat(jobExecution).isNotNull();
|
||||
assertThat(context.getBean(JobRepository.class).getLastJobExecution("job", jobParameters)).isNotNull();
|
||||
assertThat(context.getBean(MongoOperations.class).getCollection("BATCH_JOB_EXECUTION").countDocuments())
|
||||
.isPositive();
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class JobConfiguration {
|
||||
|
||||
@Bean
|
||||
Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
.start(new StepBuilder("step1", jobRepository)
|
||||
.tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED)
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.batch.mongodb.autoconfigure;
|
||||
|
||||
import com.mongodb.client.MongoClient;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
|
||||
import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration;
|
||||
import org.springframework.batch.core.configuration.support.MongoDefaultBatchConfiguration;
|
||||
import org.springframework.batch.core.launch.JobOperator;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.batch.autoconfigure.BatchAutoConfiguration;
|
||||
import org.springframework.boot.batch.autoconfigure.BatchJobLauncherAutoConfiguration;
|
||||
import org.springframework.boot.batch.autoconfigure.BatchTaskExecutor;
|
||||
import org.springframework.boot.batch.autoconfigure.BatchTransactionManager;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
|
||||
import org.springframework.boot.data.mongodb.autoconfigure.DataMongoAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.data.mongodb.MongoDatabaseFactory;
|
||||
import org.springframework.data.mongodb.MongoTransactionManager;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Batch using Data MongoDB.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.1.0
|
||||
*/
|
||||
@AutoConfiguration(before = { BatchAutoConfiguration.class, BatchJobLauncherAutoConfiguration.class },
|
||||
after = DataMongoAutoConfiguration.class)
|
||||
@ConditionalOnClass({ JobOperator.class, MongoClient.class, MongoOperations.class })
|
||||
@ConditionalOnBean(MongoDatabaseFactory.class)
|
||||
@ConditionalOnMissingBean(value = DefaultBatchConfiguration.class, annotation = EnableBatchProcessing.class)
|
||||
@EnableConfigurationProperties(BatchDataMongoProperties.class)
|
||||
public final class BatchDataMongoAutoConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty("spring.batch.data.mongodb.schema.initialize")
|
||||
@ConditionalOnBean(MongoOperations.class)
|
||||
@Import(JobRepositoryDependsOnSchemaInitializationDetector.class)
|
||||
static class BatchMongoDatabaseInitializerConfiguration {
|
||||
|
||||
@Bean(name = JobRepositoryDependsOnSchemaInitializationDetector.SCHEMA_INITIALIZATION_BEAN_NAME)
|
||||
InitializingBean batchMongoDataInitializingBean(MongoOperations mongoOperations,
|
||||
BatchDataMongoProperties properties) {
|
||||
return () -> {
|
||||
BatchMongoSchemaInitializer initializer = new BatchMongoSchemaInitializer(mongoOperations);
|
||||
String schemaLocation = properties.getSchema().getLocation();
|
||||
Resource resource = new ClassPathResource(schemaLocation);
|
||||
if (!resource.exists()) {
|
||||
throw new InvalidConfigurationPropertyValueException("spring.batch.data.mongodb.schema.location",
|
||||
schemaLocation, "resource does not exist");
|
||||
}
|
||||
initializer.initialize(resource);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class SpringBootBatchMongoConfiguration extends MongoDefaultBatchConfiguration {
|
||||
|
||||
private final MongoOperations mongoOperations;
|
||||
|
||||
private final MongoTransactionManager transactionManager;
|
||||
|
||||
private final @Nullable TaskExecutor taskExecutor;
|
||||
|
||||
private final BatchDataMongoProperties properties;
|
||||
|
||||
SpringBootBatchMongoConfiguration(MongoDatabaseFactory mongoDatabaseFactory,
|
||||
ObjectProvider<MongoTransactionManager> transactionManager,
|
||||
@BatchTransactionManager ObjectProvider<MongoTransactionManager> batchTransactionManager,
|
||||
@BatchTaskExecutor ObjectProvider<TaskExecutor> batchTaskExecutor,
|
||||
BatchDataMongoProperties properties) {
|
||||
this.mongoOperations = createMongoOperations(mongoDatabaseFactory);
|
||||
this.transactionManager = batchTransactionManager.getIfAvailable(
|
||||
() -> transactionManager.getIfAvailable(() -> new MongoTransactionManager(mongoDatabaseFactory)));
|
||||
this.taskExecutor = batchTaskExecutor.getIfAvailable();
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
private static MongoTemplate createMongoOperations(MongoDatabaseFactory mongoDatabaseFactory) {
|
||||
MongoTemplate template = new MongoTemplate(mongoDatabaseFactory);
|
||||
MappingMongoConverter converter = (MappingMongoConverter) template.getConverter();
|
||||
converter.setMapKeyDotReplacement(".");
|
||||
return template;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MongoOperations getMongoOperations() {
|
||||
return this.mongoOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MongoTransactionManager getTransactionManager() {
|
||||
return this.transactionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getValidateTransactionState() {
|
||||
return this.properties.isValidateTransactionState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Isolation getIsolationLevelForCreate() {
|
||||
Isolation isolation = this.properties.getIsolationLevelForCreate();
|
||||
return (isolation != null) ? isolation : super.getIsolationLevelForCreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TaskExecutor getTaskExecutor() {
|
||||
return (this.taskExecutor != null) ? this.taskExecutor : super.getTaskExecutor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.batch.mongodb.autoconfigure;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
|
||||
/**
|
||||
* Configuration properties for Spring Batch using Data MongoDB.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.1.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.batch.data.mongodb")
|
||||
public class BatchDataMongoProperties {
|
||||
|
||||
/**
|
||||
* Whether to validate the transaction state.
|
||||
*/
|
||||
private boolean validateTransactionState = true;
|
||||
|
||||
/**
|
||||
* Transaction isolation level to use when creating job metadata for new jobs.
|
||||
*/
|
||||
private @Nullable Isolation isolationLevelForCreate;
|
||||
|
||||
private final Schema schema = new Schema();
|
||||
|
||||
public boolean isValidateTransactionState() {
|
||||
return this.validateTransactionState;
|
||||
}
|
||||
|
||||
public void setValidateTransactionState(boolean validateTransactionState) {
|
||||
this.validateTransactionState = validateTransactionState;
|
||||
}
|
||||
|
||||
public @Nullable Isolation getIsolationLevelForCreate() {
|
||||
return this.isolationLevelForCreate;
|
||||
}
|
||||
|
||||
public void setIsolationLevelForCreate(@Nullable Isolation isolationLevelForCreate) {
|
||||
this.isolationLevelForCreate = isolationLevelForCreate;
|
||||
}
|
||||
|
||||
public Schema getSchema() {
|
||||
return this.schema;
|
||||
}
|
||||
|
||||
public static class Schema {
|
||||
|
||||
/**
|
||||
* Path to the newline-delimited JSON script used to create the Spring Batch job
|
||||
* repository collections and indexes in MongoDB.
|
||||
*/
|
||||
private String location = "org/springframework/batch/core/schema-mongodb.jsonl";
|
||||
|
||||
/**
|
||||
* Whether to initialize the Spring Batch job repository schema in MongoDB.
|
||||
*/
|
||||
private boolean initialize;
|
||||
|
||||
public String getLocation() {
|
||||
return this.location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public boolean isInitialize() {
|
||||
return this.initialize;
|
||||
}
|
||||
|
||||
public void setInitialize(boolean initialize) {
|
||||
this.initialize = initialize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.batch.mongodb.autoconfigure;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
/**
|
||||
* Thrown when the Spring Batch repository schema cannot be initialized.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public class BatchMongoSchemaInitializationException extends DataAccessException {
|
||||
|
||||
public BatchMongoSchemaInitializationException(String msg, @Nullable Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.batch.mongodb.autoconfigure;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
/**
|
||||
* Initializes the Spring Batch job repository schema (collections and indexes) in MongoDB
|
||||
* by executing commands from a newline-delimited JSON script.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class BatchMongoSchemaInitializer {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(BatchMongoSchemaInitializer.class);
|
||||
|
||||
private final MongoOperations mongoOperations;
|
||||
|
||||
BatchMongoSchemaInitializer(MongoOperations mongoOperations) {
|
||||
this.mongoOperations = mongoOperations;
|
||||
}
|
||||
|
||||
void initialize(Resource schema) throws IOException {
|
||||
StreamUtils.copyToString(schema.getInputStream(), StandardCharsets.UTF_8)
|
||||
.lines()
|
||||
.filter((line) -> !line.isBlank())
|
||||
.forEach((command) -> {
|
||||
try {
|
||||
executeCommand(command);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new BatchMongoSchemaInitializationException(
|
||||
"Failed to initialize Batch repository schema using '%s', command failed: %s"
|
||||
.formatted(schema, command),
|
||||
ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void executeCommand(String command) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Executing command: " + command);
|
||||
}
|
||||
this.mongoOperations.executeCommand(command);
|
||||
}
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.batch.mongodb.autoconfigure;
|
||||
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor;
|
||||
|
||||
/**
|
||||
* {@link AbstractDependsOnBeanFactoryPostProcessor} implementation that makes sure Spring
|
||||
* Batch's {@link JobRepository} depends on schema initialization.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class JobRepositoryDependsOnSchemaInitializationDetector extends AbstractDependsOnBeanFactoryPostProcessor {
|
||||
|
||||
/**
|
||||
* Bean name responsible for schema initialization.
|
||||
*/
|
||||
static final String SCHEMA_INITIALIZATION_BEAN_NAME = "batchMongoDataInitializingBean";
|
||||
|
||||
JobRepositoryDependsOnSchemaInitializationDetector() {
|
||||
super(JobRepository.class, SCHEMA_INITIALIZATION_BEAN_NAME);
|
||||
}
|
||||
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Auto-configuration for Spring Batch with Data MongoDB.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.batch.mongodb.autoconfigure;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
+1
@@ -0,0 +1 @@
|
||||
org.springframework.boot.batch.mongodb.autoconfigure.BatchDataMongoAutoConfiguration
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.batch.mongodb.autoconfigure;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
|
||||
import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration;
|
||||
import org.springframework.batch.core.launch.JobOperator;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.batch.autoconfigure.BatchTransactionManager;
|
||||
import org.springframework.boot.batch.mongodb.autoconfigure.BatchDataMongoAutoConfiguration.SpringBootBatchMongoConfiguration;
|
||||
import org.springframework.boot.data.mongodb.autoconfigure.DataMongoAutoConfiguration;
|
||||
import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.mongodb.MongoDatabaseFactory;
|
||||
import org.springframework.data.mongodb.MongoTransactionManager;
|
||||
import org.springframework.data.mongodb.core.MongoExceptionTranslator;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
||||
/**
|
||||
* Tests for {@link BatchDataMongoAutoConfiguration}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class BatchDataMongoAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(BatchDataMongoAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void autoConfigurationWithSpringDataMongoDb() {
|
||||
this.contextRunner
|
||||
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, DataMongoAutoConfiguration.class))
|
||||
.run((context) -> assertThat(context).hasSingleBean(JobRepository.class).hasSingleBean(JobOperator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfigurationOnlyRequiresMongoDatabaseFactory() {
|
||||
this.contextRunner.withBean(MongoDatabaseFactory.class, this::mockMongoDatabaseFactory)
|
||||
.run((context) -> assertThat(context).hasSingleBean(JobRepository.class).hasSingleBean(JobOperator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void autConfigurationUsesMainTransactionManager() {
|
||||
MongoTransactionManager transactionManager = mock(MongoTransactionManager.class);
|
||||
this.contextRunner.withBean(MongoDatabaseFactory.class, this::mockMongoDatabaseFactory)
|
||||
.withBean(MongoTransactionManager.class, () -> transactionManager)
|
||||
.run((context) -> assertThat(
|
||||
context.getBean(SpringBootBatchMongoConfiguration.class).getTransactionManager())
|
||||
.isSameAs(transactionManager));
|
||||
}
|
||||
|
||||
@Test
|
||||
void autConfigurationFavorsBatchTransactionManager() {
|
||||
MongoTransactionManager transactionManager = mock(MongoTransactionManager.class);
|
||||
this.contextRunner.withBean(MongoDatabaseFactory.class, this::mockMongoDatabaseFactory)
|
||||
.withBean(MongoTransactionManager.class, () -> transactionManager)
|
||||
.withUserConfiguration(BatchTransactionManagerConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context.getBeansOfType(MongoTransactionManager.class)).hasSize(2);
|
||||
assertThat(context.getBean(SpringBootBatchMongoConfiguration.class).getTransactionManager())
|
||||
.isSameAs(context.getBean("customTransactionManager"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void autConfigurationCreatesBatchTransactionManagerIfNecessary() {
|
||||
MongoDatabaseFactory mongoDatabaseFactory = mockMongoDatabaseFactory();
|
||||
this.contextRunner.withBean(MongoDatabaseFactory.class, () -> mongoDatabaseFactory).run((context) -> {
|
||||
assertThat(context).doesNotHaveBean(MongoTransactionManager.class);
|
||||
assertThat(context.getBean(SpringBootBatchMongoConfiguration.class).getTransactionManager())
|
||||
.satisfies((mongoTransactionManager) -> assertThat(mongoTransactionManager.getDatabaseFactory())
|
||||
.isSameAs(mongoDatabaseFactory));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoconfigurationBacksOffEntirelyIfSpringMongoDbAbsent() {
|
||||
this.contextRunner
|
||||
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, DataMongoAutoConfiguration.class))
|
||||
.withClassLoader(new FilteredClassLoader(MongoOperations.class))
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(JobRepository.class)
|
||||
.doesNotHaveBean(JobOperator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfigurationBacksOfEntirelyIfSpringMongoDbIsNotConfigured() {
|
||||
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(JobRepository.class)
|
||||
.doesNotHaveBean(JobOperator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfigurationBacksOffWhenUserEnablesBatchProcessing() {
|
||||
this.contextRunner.withBean(MongoDatabaseFactory.class, this::mockMongoDatabaseFactory)
|
||||
.withUserConfiguration(EnableBatchProcessingConfiguration.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(SpringBootBatchMongoConfiguration.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfigurationBacksOffWhenUserProvidesBatchConfiguration() {
|
||||
this.contextRunner.withBean(MongoDatabaseFactory.class, this::mockMongoDatabaseFactory)
|
||||
.withUserConfiguration(CustomBatchConfiguration.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(SpringBootBatchMongoConfiguration.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void schemaInitializerBeanNotCreatedByDefault() {
|
||||
this.contextRunner.withBean(MongoDatabaseFactory.class, this::mockMongoDatabaseFactory)
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(JobRepositoryDependsOnSchemaInitializationDetector.SCHEMA_INITIALIZATION_BEAN_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
void schemaInitializerBeanCreatedWhenSchemaInitializeEnabled() {
|
||||
MongoOperations mongoOperations = mock(MongoOperations.class);
|
||||
this.contextRunner.withBean(MongoDatabaseFactory.class, this::mockMongoDatabaseFactory)
|
||||
.withBean(MongoOperations.class, () -> mongoOperations)
|
||||
.withPropertyValues("spring.batch.data.mongodb.schema.initialize=true")
|
||||
.run((context) -> {
|
||||
assertThat(context)
|
||||
.hasBean(JobRepositoryDependsOnSchemaInitializationDetector.SCHEMA_INITIALIZATION_BEAN_NAME);
|
||||
// see org/springframework/batch/core/schema-mongodb.jsonl
|
||||
then(mongoOperations).should(times(7)).executeCommand(anyString());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void jobRepositoryDependsOnSchemaInitializerWhenSchemaInitializationEnabled() {
|
||||
this.contextRunner.withBean(MongoDatabaseFactory.class, this::mockMongoDatabaseFactory)
|
||||
.withBean(MongoOperations.class, Mockito::mock)
|
||||
.withPropertyValues("spring.batch.data.mongodb.schema.initialize=true")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(JobRepository.class);
|
||||
BeanDefinition jobRepositoryDefinition = context.getBeanFactory().getBeanDefinition("jobRepository");
|
||||
assertThat(jobRepositoryDefinition.getDependsOn())
|
||||
.contains(JobRepositoryDependsOnSchemaInitializationDetector.SCHEMA_INITIALIZATION_BEAN_NAME);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void schemaInitializationFailsWhenSchemaLocationDoesNotExist() {
|
||||
this.contextRunner.withBean(MongoDatabaseFactory.class, this::mockMongoDatabaseFactory)
|
||||
.withBean(MongoOperations.class, Mockito::mock)
|
||||
.withPropertyValues("spring.batch.data.mongodb.schema.initialize=true",
|
||||
"spring.batch.data.mongodb.schema.location=classpath:does/not/exist.jsonl")
|
||||
.run((context) -> assertThat(context).getFailure()
|
||||
.hasRootCauseInstanceOf(
|
||||
org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException.class)
|
||||
.rootCause()
|
||||
.hasMessageContaining("spring.batch.data.mongodb.schema.location")
|
||||
.hasMessageContaining("resource does not exist"));
|
||||
}
|
||||
|
||||
private MongoDatabaseFactory mockMongoDatabaseFactory() {
|
||||
MongoDatabaseFactory factory = mock(MongoDatabaseFactory.class);
|
||||
given(factory.getExceptionTranslator()).willReturn(MongoExceptionTranslator.DEFAULT_EXCEPTION_TRANSLATOR);
|
||||
return factory;
|
||||
}
|
||||
|
||||
@EnableBatchProcessing
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class EnableBatchProcessingConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomBatchConfiguration extends DefaultBatchConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class BatchTransactionManagerConfiguration {
|
||||
|
||||
@Bean
|
||||
@BatchTransactionManager
|
||||
MongoTransactionManager customTransactionManager() {
|
||||
return mock(MongoTransactionManager.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.batch.mongodb.autoconfigure;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link BatchMongoSchemaInitializer}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class BatchMongoSchemaInitializerTests {
|
||||
|
||||
@Test
|
||||
void initializeExecutesEachNonBlankLine() throws IOException {
|
||||
MongoOperations mongoOperations = mock(MongoOperations.class);
|
||||
BatchMongoSchemaInitializer initializer = new BatchMongoSchemaInitializer(mongoOperations);
|
||||
Resource schema = resource("{\"create\": \"batch_job_instance\"}\n{\"create\": \"batch_job_execution\"}");
|
||||
|
||||
initializer.initialize(schema);
|
||||
|
||||
then(mongoOperations).should().executeCommand("{\"create\": \"batch_job_instance\"}");
|
||||
then(mongoOperations).should().executeCommand("{\"create\": \"batch_job_execution\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
void initializeSkipsBlankLines() throws IOException {
|
||||
MongoOperations mongoOperations = mock(MongoOperations.class);
|
||||
BatchMongoSchemaInitializer initializer = new BatchMongoSchemaInitializer(mongoOperations);
|
||||
Resource schema = resource("{\"create\": \"col1\"}\n\n \n{\"create\": \"col2\"}");
|
||||
|
||||
initializer.initialize(schema);
|
||||
|
||||
then(mongoOperations).should().executeCommand("{\"create\": \"col1\"}");
|
||||
then(mongoOperations).should().executeCommand("{\"create\": \"col2\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
void initializeThrowsWhenCommandFails() {
|
||||
MongoOperations mongoOperations = mock(MongoOperations.class);
|
||||
given(mongoOperations.executeCommand(anyString())).willThrow(new RuntimeException("Command failed"));
|
||||
BatchMongoSchemaInitializer initializer = new BatchMongoSchemaInitializer(mongoOperations);
|
||||
Resource schema = resource("{\"create\": \"batch_job_instance\"}");
|
||||
|
||||
assertThatExceptionOfType(BatchMongoSchemaInitializationException.class)
|
||||
.isThrownBy(() -> initializer.initialize(schema))
|
||||
.withMessageContaining("Failed to initialize Batch repository schema")
|
||||
.withMessageContaining("{\"create\": \"batch_job_instance\"}")
|
||||
.withCauseInstanceOf(RuntimeException.class);
|
||||
}
|
||||
|
||||
private static Resource resource(String content) {
|
||||
return new InputStreamResource(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -85,6 +85,7 @@ include "module:spring-boot-artemis"
|
||||
include "module:spring-boot-autoconfigure-classic"
|
||||
include "module:spring-boot-autoconfigure-classic-modules"
|
||||
include "module:spring-boot-batch"
|
||||
include "module:spring-boot-batch-data-mongodb"
|
||||
include "module:spring-boot-batch-jdbc"
|
||||
include "module:spring-boot-cache"
|
||||
include "module:spring-boot-cache-test"
|
||||
@@ -214,6 +215,8 @@ include "starter:spring-boot-starter-artemis-test"
|
||||
include "starter:spring-boot-starter-aspectj"
|
||||
include "starter:spring-boot-starter-aspectj-test"
|
||||
include "starter:spring-boot-starter-batch"
|
||||
include "starter:spring-boot-starter-batch-data-mongodb"
|
||||
include "starter:spring-boot-starter-batch-data-mongodb-test"
|
||||
include "starter:spring-boot-starter-batch-jdbc"
|
||||
include "starter:spring-boot-starter-batch-jdbc-test"
|
||||
include "starter:spring-boot-starter-batch-test"
|
||||
@@ -396,6 +399,7 @@ include ":smoke-test:spring-boot-smoke-test-artemis"
|
||||
include ":smoke-test:spring-boot-smoke-test-aspectj"
|
||||
include ":smoke-test:spring-boot-smoke-test-autoconfigure-classic"
|
||||
include ":smoke-test:spring-boot-smoke-test-batch"
|
||||
include ":smoke-test:spring-boot-smoke-test-batch-data-mongodb"
|
||||
include ":smoke-test:spring-boot-smoke-test-batch-jdbc"
|
||||
include ":smoke-test:spring-boot-smoke-test-bootstrap-registry"
|
||||
include ":smoke-test:spring-boot-smoke-test-cache"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License);
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id "java"
|
||||
}
|
||||
|
||||
description = "Spring Boot Batch with Data MongoDB smoke test"
|
||||
|
||||
dependencies {
|
||||
implementation(project(":starter:spring-boot-starter-batch-data-mongodb"))
|
||||
|
||||
testImplementation(project(":starter:spring-boot-starter-batch-data-mongodb-test"))
|
||||
testImplementation(project(":test-support:spring-boot-docker-test-support"))
|
||||
testImplementation("org.testcontainers:testcontainers-junit-jupiter")
|
||||
testImplementation("org.testcontainers:testcontainers-mongodb")
|
||||
}
|
||||
|
||||
tasks.named("compileTestJava") {
|
||||
options.nullability.checking = "tests"
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package smoketest.batch;
|
||||
|
||||
import org.springframework.batch.core.job.Job;
|
||||
import org.springframework.batch.core.job.builder.JobBuilder;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.step.builder.StepBuilder;
|
||||
import org.springframework.batch.infrastructure.repeat.RepeatStatus;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SampleBatchApplication {
|
||||
|
||||
@Bean
|
||||
Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
.start(new StepBuilder("step1", jobRepository)
|
||||
.tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED)
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// System.exit is common for Batch applications since the exit code can be used to
|
||||
// drive a workflow
|
||||
System.exit(SpringApplication.exit(SpringApplication.run(SampleBatchApplication.class, args)));
|
||||
}
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@NullMarked
|
||||
package smoketest.batch;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package smoketest.batch;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.testcontainers.mongodb.MongoDBContainer;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.test.system.CapturedOutput;
|
||||
import org.springframework.boot.test.system.OutputCaptureExtension;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Smoke tests for Spring Batch with MongoDB.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ExtendWith(OutputCaptureExtension.class)
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class SampleBatchApplicationTests {
|
||||
|
||||
@Container
|
||||
static final MongoDBContainer mongoDb = TestImage.container(MongoDBContainer.class).withReplicaSet();
|
||||
|
||||
@Test
|
||||
void testDefaultSettings(CapturedOutput output) {
|
||||
int exitCode = SpringApplication.exit(SpringApplication.run(SampleBatchApplication.class,
|
||||
"--spring.mongodb.uri=" + mongoDb.getReplicaSetUrl(),
|
||||
"--spring.batch.data.mongodb.schema.initialize=true"));
|
||||
assertThat(exitCode).isZero();
|
||||
assertThat(output).contains("completed with the following parameters");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id "org.springframework.boot.starter"
|
||||
}
|
||||
|
||||
description = "Starter for testing using Spring Batch with Data MongoDB"
|
||||
|
||||
dependencies {
|
||||
api(project(":starter:spring-boot-starter-batch-test"))
|
||||
api(project(":starter:spring-boot-starter-data-mongodb-test"))
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id "org.springframework.boot.starter"
|
||||
}
|
||||
|
||||
description = "Starter for using Spring Batch with Data MongoDB"
|
||||
|
||||
dependencies {
|
||||
api(project(":starter:spring-boot-starter-batch"))
|
||||
api(project(":starter:spring-boot-starter-data-mongodb"))
|
||||
|
||||
api(project(":module:spring-boot-batch-data-mongodb"))
|
||||
}
|
||||
Reference in New Issue
Block a user