Spring Boot starter that provides comprehensive batch processing capabilities for enterprise Java applications with auto-configuration, job management, and database integration.
—
Spring Boot Batch Starter provides extensive customization capabilities through qualifier annotations, customization interfaces, and database initialization components for advanced configuration scenarios.
Qualifier annotations enable precise dependency injection when multiple beans of the same type exist, particularly useful in multi-tenant or complex enterprise environments.
Qualifier annotation for specifying a dedicated DataSource for batch metadata storage, separate from the application's primary DataSource.
/**
* Qualifier annotation for a DataSource to be injected into Batch auto-configuration.
* Can be used on a secondary data source, if there is another one marked as @Primary.
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier
public @interface BatchDataSource {
}Usage Examples:
@Configuration
public class MultiDataSourceConfiguration {
@Bean
@Primary
@ConfigurationProperties("app.datasource")
public DataSource applicationDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@BatchDataSource
@ConfigurationProperties("batch.datasource")
public DataSource batchDataSource() {
return DataSourceBuilder.create().build();
}
}
# application.yml
app:
datasource:
url: jdbc:postgresql://localhost/appdb
username: app_user
password: app_pass
batch:
datasource:
url: jdbc:postgresql://localhost/batchdb
username: batch_user
password: batch_passQualifier annotation for specifying a dedicated PlatformTransactionManager for batch operations.
/**
* Qualifier annotation for a PlatformTransactionManager to be injected into Batch
* auto-configuration. Can be used on a secondary PlatformTransactionManager, if
* there is another one marked as @Primary.
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier
public @interface BatchTransactionManager {
}Usage Examples:
@Configuration
public class TransactionManagerConfiguration {
@Bean
@Primary
public PlatformTransactionManager applicationTransactionManager(
@Qualifier("applicationDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
@BatchTransactionManager
public PlatformTransactionManager batchTransactionManager(
@BatchDataSource DataSource batchDataSource) {
DataSourceTransactionManager tm = new DataSourceTransactionManager(batchDataSource);
tm.setDefaultTimeout(3600); // Longer timeout for batch operations
return tm;
}
}Qualifier annotation for specifying a dedicated TaskExecutor for batch job processing, enabling custom thread pool configuration for batch operations.
/**
* Qualifier annotation for a TaskExecutor to be injected into Batch
* auto-configuration. Can be used on a secondary task executor source, if there is
* another one marked as @Primary.
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier
public @interface BatchTaskExecutor {
}Usage Examples:
@Configuration
@EnableAsync
public class TaskExecutorConfiguration {
@Bean
@Primary
public TaskExecutor applicationTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(5);
executor.setQueueCapacity(10);
executor.setThreadNamePrefix("app-");
executor.initialize();
return executor;
}
@Bean
@BatchTaskExecutor
public TaskExecutor batchTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(1000);
executor.setThreadNamePrefix("batch-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
// Use in step configuration
@Bean
public Step parallelProcessingStep(JobRepository jobRepository,
@BatchTransactionManager PlatformTransactionManager transactionManager,
@BatchTaskExecutor TaskExecutor taskExecutor) {
return new StepBuilder("parallelStep", jobRepository)
.<String, String>chunk(100, transactionManager)
.reader(itemReader())
.processor(itemProcessor())
.writer(itemWriter())
.taskExecutor(taskExecutor)
.build();
}Functional interface for customizing the ConversionService used by Spring Batch for type conversions in job parameters and other batch operations.
/**
* Callback interface that can be implemented by beans wishing to customize the
* ConfigurableConversionService that is provided by DefaultBatchConfiguration
* while retaining its default auto-configuration.
*/
@FunctionalInterface
public interface BatchConversionServiceCustomizer {
/**
* Customize the ConfigurableConversionService used by batch infrastructure
* @param configurableConversionService the ConfigurableConversionService to customize
*/
void customize(ConfigurableConversionService configurableConversionService);
}Usage Examples:
@Component
public class CustomBatchConversionServiceCustomizer implements BatchConversionServiceCustomizer {
@Override
public void customize(ConfigurableConversionService conversionService) {
// Add custom converters for specific types
conversionService.addConverter(new StringToLocalDateConverter());
conversionService.addConverter(new LocalDateToStringConverter());
conversionService.addConverter(new StringToEnumConverter());
// Add custom formatting for specific patterns
FormattingConversionService formattingService = (FormattingConversionService) conversionService;
formattingService.addFormatter(new CustomDateFormatter("yyyy-MM-dd"));
}
}
// Custom converter example
public class StringToLocalDateConverter implements Converter<String, LocalDate> {
@Override
public LocalDate convert(String source) {
try {
return LocalDate.parse(source, DateTimeFormatter.ISO_LOCAL_DATE);
} catch (DateTimeParseException e) {
throw new ConversionFailedException(
TypeDescriptor.valueOf(String.class),
TypeDescriptor.valueOf(LocalDate.class),
source, e);
}
}
}
// Usage in job parameters
java -jar app.jar --startDate=2024-01-15 --endDate=2024-01-31
// Automatically converted to LocalDate objects in job parametersHandles automatic initialization of batch database schema using SQL scripts with platform-specific support.
/**
* Database initializer for Spring Batch schema using SQL scripts.
* Supports platform-specific scripts and custom schema locations.
*/
public class BatchDataSourceScriptDatabaseInitializer extends DataSourceScriptDatabaseInitializer {
/**
* Creates database initializer with specified DataSource and configuration
* @param dataSource DataSource to initialize (may be qualified with @BatchDataSource)
* @param properties JDBC configuration properties for initialization behavior
*/
public BatchDataSourceScriptDatabaseInitializer(
DataSource dataSource,
BatchProperties.Jdbc properties);
}Usage Examples:
@Configuration
public class CustomBatchDatabaseConfiguration {
@Bean
@ConditionalOnMissingBean
public BatchDataSourceScriptDatabaseInitializer customBatchInitializer(
@BatchDataSource DataSource batchDataSource,
BatchProperties batchProperties) {
BatchProperties.Jdbc jdbcProperties = batchProperties.getJdbc();
// Customize initialization behavior
jdbcProperties.setSchema("classpath:custom-batch-schema.sql");
jdbcProperties.setPlatform("postgresql");
jdbcProperties.setInitializeSchema(DatabaseInitializationMode.ALWAYS);
return new BatchDataSourceScriptDatabaseInitializer(batchDataSource, jdbcProperties);
}
}
# Custom schema file: custom-batch-schema.sql
CREATE TABLE IF NOT EXISTS CUSTOM_BATCH_JOB_INSTANCE (
JOB_INSTANCE_ID BIGINT PRIMARY KEY,
VERSION BIGINT,
JOB_NAME VARCHAR(100) NOT NULL,
JOB_KEY VARCHAR(32) NOT NULL,
constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
);
-- Additional custom tables...Ensures proper initialization order between database schema creation and job repository configuration.
/**
* Detector that ensures JobRepository beans depend on database initialization completion.
* Part of Spring Boot's database initialization dependency management system.
*/
public class JobRepositoryDependsOnDatabaseInitializationDetector
implements DependsOnDatabaseInitializationDetector {
/**
* Returns bean names that should depend on database initialization
* @return Set of bean names that require database initialization to complete first
*/
public Set<String> getDependsOnDatabaseInitializationBeanNames();
}Configure separate batch infrastructure for different tenants:
@Configuration
public class MultiTenantBatchConfiguration {
@Bean("tenant1BatchConfig")
@ConfigurationProperties("tenant1.batch")
public BatchProperties tenant1BatchProperties() {
return new BatchProperties();
}
@Bean("tenant2BatchConfig")
@ConfigurationProperties("tenant2.batch")
public BatchProperties tenant2BatchProperties() {
return new BatchProperties();
}
@Bean
@BatchDataSource
@Qualifier("tenant1DataSource")
public DataSource tenant1DataSource() {
return DataSourceBuilder.create()
.url("jdbc:postgresql://localhost/tenant1_batch")
.build();
}
@Bean
@Qualifier("tenant2DataSource")
public DataSource tenant2DataSource() {
return DataSourceBuilder.create()
.url("jdbc:postgresql://localhost/tenant2_batch")
.build();
}
}Integrate custom monitoring and error handling:
@Component
public class BatchMonitoringCustomizer implements BatchConversionServiceCustomizer {
@Autowired
private MeterRegistry meterRegistry;
@Override
public void customize(ConfigurableConversionService conversionService) {
// Add monitoring capabilities to conversion service
conversionService.addConverter(new MonitoredStringToDateConverter(meterRegistry));
}
@EventListener
public void handleJobExecution(JobExecutionEvent event) {
JobExecution execution = event.getJobExecution();
// Custom metrics
Timer.Sample sample = Timer.start(meterRegistry);
sample.stop(Timer.builder("batch.job.duration")
.tag("job.name", execution.getJobInstance().getJobName())
.tag("status", execution.getStatus().toString())
.register(meterRegistry));
// Custom alerting
if (execution.getStatus() == BatchStatus.FAILED) {
sendAlert(execution);
}
}
private void sendAlert(JobExecution execution) {
// Integration with alerting systems
}
}Create dynamic job parameter resolution based on environment:
@Component
public class EnvironmentAwareBatchConversionServiceCustomizer
implements BatchConversionServiceCustomizer {
@Autowired
private Environment environment;
@Override
public void customize(ConfigurableConversionService conversionService) {
conversionService.addConverter(new EnvironmentAwareConverter(environment));
}
}
public class EnvironmentAwareConverter implements Converter<String, String> {
private final Environment environment;
public EnvironmentAwareConverter(Environment environment) {
this.environment = environment;
}
@Override
public String convert(String source) {
// Resolve environment-specific placeholders
if (source.startsWith("${") && source.endsWith("}")) {
String property = source.substring(2, source.length() - 1);
return environment.getProperty(property, source);
}
return source;
}
}@Configuration
public class BatchResourceConfiguration {
@Bean
@BatchTaskExecutor
public TaskExecutor batchTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 2);
executor.setQueueCapacity(1000);
executor.setThreadNamePrefix("batch-worker-");
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
executor.initialize();
return executor;
}
}@Configuration
@EnableBatchProcessing
public class SecureBatchConfiguration {
@Bean
@BatchDataSource
public DataSource secureDataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:postgresql://localhost/secure_batch");
config.setUsername("batch_service");
// Use encrypted password or credential management
config.setPassword(passwordDecoder.decode(encryptedPassword));
config.setMaximumPoolSize(20);
return new HikariDataSource(config);
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter-batch