0
# Customization and Qualification
1
2
Spring Boot Batch Starter provides extensive customization capabilities through qualifier annotations, customization interfaces, and database initialization components for advanced configuration scenarios.
3
4
## Capabilities
5
6
### Qualifier Annotations
7
8
Qualifier annotations enable precise dependency injection when multiple beans of the same type exist, particularly useful in multi-tenant or complex enterprise environments.
9
10
#### @BatchDataSource
11
12
Qualifier annotation for specifying a dedicated DataSource for batch metadata storage, separate from the application's primary DataSource.
13
14
```java { .api }
15
/**
16
* Qualifier annotation for a DataSource to be injected into Batch auto-configuration.
17
* Can be used on a secondary data source, if there is another one marked as @Primary.
18
*/
19
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
20
@Retention(RetentionPolicy.RUNTIME)
21
@Documented
22
@Qualifier
23
public @interface BatchDataSource {
24
}
25
```
26
27
**Usage Examples:**
28
29
```java
30
@Configuration
31
public class MultiDataSourceConfiguration {
32
33
@Bean
34
@Primary
35
@ConfigurationProperties("app.datasource")
36
public DataSource applicationDataSource() {
37
return DataSourceBuilder.create().build();
38
}
39
40
@Bean
41
@BatchDataSource
42
@ConfigurationProperties("batch.datasource")
43
public DataSource batchDataSource() {
44
return DataSourceBuilder.create().build();
45
}
46
}
47
48
# application.yml
49
app:
50
datasource:
51
url: jdbc:postgresql://localhost/appdb
52
username: app_user
53
password: app_pass
54
55
batch:
56
datasource:
57
url: jdbc:postgresql://localhost/batchdb
58
username: batch_user
59
password: batch_pass
60
```
61
62
#### @BatchTransactionManager
63
64
Qualifier annotation for specifying a dedicated PlatformTransactionManager for batch operations.
65
66
```java { .api }
67
/**
68
* Qualifier annotation for a PlatformTransactionManager to be injected into Batch
69
* auto-configuration. Can be used on a secondary PlatformTransactionManager, if
70
* there is another one marked as @Primary.
71
*/
72
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
73
@Retention(RetentionPolicy.RUNTIME)
74
@Documented
75
@Qualifier
76
public @interface BatchTransactionManager {
77
}
78
```
79
80
**Usage Examples:**
81
82
```java
83
@Configuration
84
public class TransactionManagerConfiguration {
85
86
@Bean
87
@Primary
88
public PlatformTransactionManager applicationTransactionManager(
89
@Qualifier("applicationDataSource") DataSource dataSource) {
90
return new DataSourceTransactionManager(dataSource);
91
}
92
93
@Bean
94
@BatchTransactionManager
95
public PlatformTransactionManager batchTransactionManager(
96
@BatchDataSource DataSource batchDataSource) {
97
DataSourceTransactionManager tm = new DataSourceTransactionManager(batchDataSource);
98
tm.setDefaultTimeout(3600); // Longer timeout for batch operations
99
return tm;
100
}
101
}
102
```
103
104
#### @BatchTaskExecutor
105
106
Qualifier annotation for specifying a dedicated TaskExecutor for batch job processing, enabling custom thread pool configuration for batch operations.
107
108
```java { .api }
109
/**
110
* Qualifier annotation for a TaskExecutor to be injected into Batch
111
* auto-configuration. Can be used on a secondary task executor source, if there is
112
* another one marked as @Primary.
113
*/
114
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
115
@Retention(RetentionPolicy.RUNTIME)
116
@Documented
117
@Qualifier
118
public @interface BatchTaskExecutor {
119
}
120
```
121
122
**Usage Examples:**
123
124
```java
125
@Configuration
126
@EnableAsync
127
public class TaskExecutorConfiguration {
128
129
@Bean
130
@Primary
131
public TaskExecutor applicationTaskExecutor() {
132
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
133
executor.setCorePoolSize(2);
134
executor.setMaxPoolSize(5);
135
executor.setQueueCapacity(10);
136
executor.setThreadNamePrefix("app-");
137
executor.initialize();
138
return executor;
139
}
140
141
@Bean
142
@BatchTaskExecutor
143
public TaskExecutor batchTaskExecutor() {
144
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
145
executor.setCorePoolSize(10);
146
executor.setMaxPoolSize(50);
147
executor.setQueueCapacity(1000);
148
executor.setThreadNamePrefix("batch-");
149
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
150
executor.initialize();
151
return executor;
152
}
153
}
154
155
// Use in step configuration
156
@Bean
157
public Step parallelProcessingStep(JobRepository jobRepository,
158
@BatchTransactionManager PlatformTransactionManager transactionManager,
159
@BatchTaskExecutor TaskExecutor taskExecutor) {
160
return new StepBuilder("parallelStep", jobRepository)
161
.<String, String>chunk(100, transactionManager)
162
.reader(itemReader())
163
.processor(itemProcessor())
164
.writer(itemWriter())
165
.taskExecutor(taskExecutor)
166
.build();
167
}
168
```
169
170
### Customization Interfaces
171
172
#### BatchConversionServiceCustomizer
173
174
Functional interface for customizing the ConversionService used by Spring Batch for type conversions in job parameters and other batch operations.
175
176
```java { .api }
177
/**
178
* Callback interface that can be implemented by beans wishing to customize the
179
* ConfigurableConversionService that is provided by DefaultBatchConfiguration
180
* while retaining its default auto-configuration.
181
*/
182
@FunctionalInterface
183
public interface BatchConversionServiceCustomizer {
184
185
/**
186
* Customize the ConfigurableConversionService used by batch infrastructure
187
* @param configurableConversionService the ConfigurableConversionService to customize
188
*/
189
void customize(ConfigurableConversionService configurableConversionService);
190
}
191
```
192
193
**Usage Examples:**
194
195
```java
196
@Component
197
public class CustomBatchConversionServiceCustomizer implements BatchConversionServiceCustomizer {
198
199
@Override
200
public void customize(ConfigurableConversionService conversionService) {
201
// Add custom converters for specific types
202
conversionService.addConverter(new StringToLocalDateConverter());
203
conversionService.addConverter(new LocalDateToStringConverter());
204
conversionService.addConverter(new StringToEnumConverter());
205
206
// Add custom formatting for specific patterns
207
FormattingConversionService formattingService = (FormattingConversionService) conversionService;
208
formattingService.addFormatter(new CustomDateFormatter("yyyy-MM-dd"));
209
}
210
}
211
212
// Custom converter example
213
public class StringToLocalDateConverter implements Converter<String, LocalDate> {
214
215
@Override
216
public LocalDate convert(String source) {
217
try {
218
return LocalDate.parse(source, DateTimeFormatter.ISO_LOCAL_DATE);
219
} catch (DateTimeParseException e) {
220
throw new ConversionFailedException(
221
TypeDescriptor.valueOf(String.class),
222
TypeDescriptor.valueOf(LocalDate.class),
223
source, e);
224
}
225
}
226
}
227
228
// Usage in job parameters
229
java -jar app.jar --startDate=2024-01-15 --endDate=2024-01-31
230
// Automatically converted to LocalDate objects in job parameters
231
```
232
233
### Database Initialization Components
234
235
#### BatchDataSourceScriptDatabaseInitializer
236
237
Handles automatic initialization of batch database schema using SQL scripts with platform-specific support.
238
239
```java { .api }
240
/**
241
* Database initializer for Spring Batch schema using SQL scripts.
242
* Supports platform-specific scripts and custom schema locations.
243
*/
244
public class BatchDataSourceScriptDatabaseInitializer extends DataSourceScriptDatabaseInitializer {
245
246
/**
247
* Creates database initializer with specified DataSource and configuration
248
* @param dataSource DataSource to initialize (may be qualified with @BatchDataSource)
249
* @param properties JDBC configuration properties for initialization behavior
250
*/
251
public BatchDataSourceScriptDatabaseInitializer(
252
DataSource dataSource,
253
BatchProperties.Jdbc properties);
254
}
255
```
256
257
**Usage Examples:**
258
259
```java
260
@Configuration
261
public class CustomBatchDatabaseConfiguration {
262
263
@Bean
264
@ConditionalOnMissingBean
265
public BatchDataSourceScriptDatabaseInitializer customBatchInitializer(
266
@BatchDataSource DataSource batchDataSource,
267
BatchProperties batchProperties) {
268
269
BatchProperties.Jdbc jdbcProperties = batchProperties.getJdbc();
270
271
// Customize initialization behavior
272
jdbcProperties.setSchema("classpath:custom-batch-schema.sql");
273
jdbcProperties.setPlatform("postgresql");
274
jdbcProperties.setInitializeSchema(DatabaseInitializationMode.ALWAYS);
275
276
return new BatchDataSourceScriptDatabaseInitializer(batchDataSource, jdbcProperties);
277
}
278
}
279
280
# Custom schema file: custom-batch-schema.sql
281
CREATE TABLE IF NOT EXISTS CUSTOM_BATCH_JOB_INSTANCE (
282
JOB_INSTANCE_ID BIGINT PRIMARY KEY,
283
VERSION BIGINT,
284
JOB_NAME VARCHAR(100) NOT NULL,
285
JOB_KEY VARCHAR(32) NOT NULL,
286
constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
287
);
288
-- Additional custom tables...
289
```
290
291
#### JobRepositoryDependsOnDatabaseInitializationDetector
292
293
Ensures proper initialization order between database schema creation and job repository configuration.
294
295
```java { .api }
296
/**
297
* Detector that ensures JobRepository beans depend on database initialization completion.
298
* Part of Spring Boot's database initialization dependency management system.
299
*/
300
public class JobRepositoryDependsOnDatabaseInitializationDetector
301
implements DependsOnDatabaseInitializationDetector {
302
303
/**
304
* Returns bean names that should depend on database initialization
305
* @return Set of bean names that require database initialization to complete first
306
*/
307
public Set<String> getDependsOnDatabaseInitializationBeanNames();
308
}
309
```
310
311
## Advanced Customization Patterns
312
313
### Multi-Tenant Batch Configuration
314
315
Configure separate batch infrastructure for different tenants:
316
317
```java
318
@Configuration
319
public class MultiTenantBatchConfiguration {
320
321
@Bean("tenant1BatchConfig")
322
@ConfigurationProperties("tenant1.batch")
323
public BatchProperties tenant1BatchProperties() {
324
return new BatchProperties();
325
}
326
327
@Bean("tenant2BatchConfig")
328
@ConfigurationProperties("tenant2.batch")
329
public BatchProperties tenant2BatchProperties() {
330
return new BatchProperties();
331
}
332
333
@Bean
334
@BatchDataSource
335
@Qualifier("tenant1DataSource")
336
public DataSource tenant1DataSource() {
337
return DataSourceBuilder.create()
338
.url("jdbc:postgresql://localhost/tenant1_batch")
339
.build();
340
}
341
342
@Bean
343
@Qualifier("tenant2DataSource")
344
public DataSource tenant2DataSource() {
345
return DataSourceBuilder.create()
346
.url("jdbc:postgresql://localhost/tenant2_batch")
347
.build();
348
}
349
}
350
```
351
352
### Custom Error Handling and Monitoring
353
354
Integrate custom monitoring and error handling:
355
356
```java
357
@Component
358
public class BatchMonitoringCustomizer implements BatchConversionServiceCustomizer {
359
360
@Autowired
361
private MeterRegistry meterRegistry;
362
363
@Override
364
public void customize(ConfigurableConversionService conversionService) {
365
// Add monitoring capabilities to conversion service
366
conversionService.addConverter(new MonitoredStringToDateConverter(meterRegistry));
367
}
368
369
@EventListener
370
public void handleJobExecution(JobExecutionEvent event) {
371
JobExecution execution = event.getJobExecution();
372
373
// Custom metrics
374
Timer.Sample sample = Timer.start(meterRegistry);
375
sample.stop(Timer.builder("batch.job.duration")
376
.tag("job.name", execution.getJobInstance().getJobName())
377
.tag("status", execution.getStatus().toString())
378
.register(meterRegistry));
379
380
// Custom alerting
381
if (execution.getStatus() == BatchStatus.FAILED) {
382
sendAlert(execution);
383
}
384
}
385
386
private void sendAlert(JobExecution execution) {
387
// Integration with alerting systems
388
}
389
}
390
```
391
392
### Dynamic Job Parameter Resolution
393
394
Create dynamic job parameter resolution based on environment:
395
396
```java
397
@Component
398
public class EnvironmentAwareBatchConversionServiceCustomizer
399
implements BatchConversionServiceCustomizer {
400
401
@Autowired
402
private Environment environment;
403
404
@Override
405
public void customize(ConfigurableConversionService conversionService) {
406
conversionService.addConverter(new EnvironmentAwareConverter(environment));
407
}
408
}
409
410
public class EnvironmentAwareConverter implements Converter<String, String> {
411
412
private final Environment environment;
413
414
public EnvironmentAwareConverter(Environment environment) {
415
this.environment = environment;
416
}
417
418
@Override
419
public String convert(String source) {
420
// Resolve environment-specific placeholders
421
if (source.startsWith("${") && source.endsWith("}")) {
422
String property = source.substring(2, source.length() - 1);
423
return environment.getProperty(property, source);
424
}
425
return source;
426
}
427
}
428
```
429
430
## Integration Best Practices
431
432
### Resource Management
433
434
```java
435
@Configuration
436
public class BatchResourceConfiguration {
437
438
@Bean
439
@BatchTaskExecutor
440
public TaskExecutor batchTaskExecutor() {
441
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
442
executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
443
executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 2);
444
executor.setQueueCapacity(1000);
445
executor.setThreadNamePrefix("batch-worker-");
446
executor.setWaitForTasksToCompleteOnShutdown(true);
447
executor.setAwaitTerminationSeconds(60);
448
executor.initialize();
449
return executor;
450
}
451
}
452
```
453
454
### Security Integration
455
456
```java
457
@Configuration
458
@EnableBatchProcessing
459
public class SecureBatchConfiguration {
460
461
@Bean
462
@BatchDataSource
463
public DataSource secureDataSource() {
464
HikariConfig config = new HikariConfig();
465
config.setJdbcUrl("jdbc:postgresql://localhost/secure_batch");
466
config.setUsername("batch_service");
467
// Use encrypted password or credential management
468
config.setPassword(passwordDecoder.decode(encryptedPassword));
469
config.setMaximumPoolSize(20);
470
return new HikariDataSource(config);
471
}
472
}