Вопрос или проблема
Я оценю вашу помощь в поиске причины исключения, указанного ниже, которое возникает при попытке расширить DefaultBatchConfiguration. Сервис Spring Batch, показанный ниже, работает нормально, когда не расширяет «Default Batch Configuration». Я новичок в сервисе Spring Batch, я обучаюсь, следуя учебнику Spring по этой ссылке «https://spring.io/guides/gs/batch-processing#header» для создания Batch Service. Будет большой помощью, если кто-то из сообщества StakeOverflow объяснит, как настроить сервис Spring Batch, когда он расширяет DefaultBatchConfiguration, цель – устранить проблему и создать прочное понимание того, как расширить Default Batch Configuration.
Детали реализации:
- Использует SpringBootApplication для запуска задания
- Использует две базы данных
- MySQL в качестве репозитория заданий
- PostgreSQL в качестве данных
- Проект Maven
- IDE Eclipse
Используемые библиотеки и версии:
- Java JDK версия 22
- Spring Batch версия 5.1.2
- Spring Boot версия 5.1.2
- PostgreSQL версия 42.7.2
- MySQL Connector версия 8.0.33
Лог отладки:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.2.10)
2024-11-05T14:30:17.788-05:00 INFO 2912 --- [ main] c.e.b.BatchProcessingApplication : Запуск BatchProcessingApplication с использованием Java 22 с PID 2912 (D:\User\Gilmar\git-repo\spring-batch-mastery\spring-batch-initial\target\classes, запущенный Gilmar в D:\User\Gilmar\git-repo\spring-batch-mastery\spring-batch-initial)
2024-11-05T14:30:17.790-05:00 INFO 2912 --- [ main] c.e.b.BatchProcessingApplication : Профиль не установлен, используется 1 профиль по умолчанию: "default"
2024-11-05T14:30:18.464-05:00 WARN 2912 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'batchConfiguration' типа [com.example.batchprocessing.BatchConfiguration$$SpringCGLIB$$0] не может быть обработан всеми BeanPostProcessors (например, не подходит для автоматического проксирования). В настоящее время созданный BeanPostProcessor [jobRegistryBeanPostProcessor] объявляется через нестатический фабричный метод в этом классе; рассмотрите возможность объявления его как статического.
2024-11-05T14:30:18.488-05:00 WARN 2912 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'jobRegistry' типа [org.springframework.batch.core.configuration.support.MapJobRegistry] не может быть обработан всеми BeanPostProcessors (например, не подходит для автоматического проксирования). Этот bean внедряется с ожиданием в текущий создаваемый BeanPostProcessor [jobRegistryBeanPostProcessor]? Проверьте соответствующее объявление BeanPostProcessor и его зависимости.
2024-11-05T14:30:18.562-05:00 INFO 2912 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Запуск...
2024-11-05T14:30:19.026-05:00 INFO 2912 --- [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Добавлено соединение com.mysql.cj.jdbc.ConnectionImpl@6778aea6
2024-11-05T14:30:19.028-05:00 INFO 2912 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Запуск завершен.
2024-11-05T14:30:19.061-05:00 INFO 2912 --- [ main] c.e.batchprocessing.BatchConfiguration : ******jobTemplate запущен******
2024-11-05T14:30:19.078-05:00 INFO 2912 --- [ main] c.e.batchprocessing.BatchConfiguration : ******FlatFileItemReader******
2024-11-05T14:30:19.095-05:00 INFO 2912 --- [ main] c.e.batchprocessing.BatchConfiguration : ******PersonItemProcessor******
2024-11-05T14:30:19.096-05:00 INFO 2912 --- [ main] c.e.batchprocessing.BatchConfiguration : ******JdbcBatchItemWriter******
2024-11-05T14:30:19.118-05:00 INFO 2912 --- [ main] o.s.b.c.r.s.JobRepositoryFactoryBean : Тип базы данных не установлен, используются метаданные, указывающие: MYSQL
2024-11-05T14:30:19.145-05:00 WARN 2912 --- [ main] s.c.a.AnnotationConfigApplicationContext : Исключение, возникшее во время инициализации контекста - отмена попытки обновления: org.springframework.beans.factory.UnsatisfiedDependencyException: Ошибка при создании bean с именем 'importUserJob', определенной в классе по пути [com/example/batchprocessing/BatchConfiguration.class]: Неудовлетворенная зависимость, выраженная через метод 'importUserJob', параметр 1: Ошибка при создании bean с именем 'step1', определенной в классе по пути [com/example/batchprocessing/BatchConfiguration.class]: Неудовлетворенная зависимость, выраженная через метод 'step1', параметр 0: Ошибка при создании bean с именем 'jobRepository', определенной в классе по пути [com/example/batchprocessing/BatchConfiguration.class]: Не удалось создать экземпляр [org.springframework.batch.core.repository.JobRepository]: Фабричный метод 'jobRepository' выдал исключение с сообщением: Невозможно настроить репозиторий заданий по умолчанию
2024-11-05T14:30:19.147-05:00 INFO 2912 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Инициализирована остановка...
2024-11-05T14:30:19.196-05:00 INFO 2912 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Остановка завершена.
2024-11-05T14:30:19.220-05:00 INFO 2912 --- [ main] .s.b.a.l.ConditionEvaluationReportLogger :
Ошибка при запуске ApplicationContext. Чтобы отобразить отчет об оценке условий, перезапустите приложение с включенной отладкой.
2024-11-05T14:30:19.249-05:00 ERROR 2912 --- [ main] o.s.boot.SpringApplication : Не удалось запустить приложение
org.springframework.beans.factory.UnsatisfiedDependencyException: Ошибка при создании bean с именем 'importUserJob', определенной в классе по пути [com/example/batchprocessing/BatchConfiguration.class]: Неудовлетворенная зависимость, выраженная через метод 'importUserJob', параметр 1: Ошибка при создании bean с именем 'step1', определенной в классе по пути [com/example/batchprocessing/BatchConfiguration.class]: Неудовлетворенная зависимость, выраженная через метод 'step1', параметр 0: Ошибка при создании bean с именем 'jobRepository', определенной в классе по пути [com/example/batchprocessing/BatchConfiguration.class]: Не удалось создать экземпляр [org.springframework.batch.core.repository.JobRepository]: Фабричный метод 'jobRepository' выдал исключение с сообщением: Невозможно настроить репозиторий заданий по умолчанию
по адресу org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:795) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:542) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.10.jar:3.2.10]
по адресу org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.10.jar:3.2.10]
по адресу org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.2.10.jar:3.2.10]
по адресу org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.2.10.jar:3.2.10]
по адресу org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.2.10.jar:3.2.10]
по адресу com.example.batchprocessing.BatchProcessingApplication.main(BatchProcessingApplication.java:11) ~[classes/:na]
Причина: org.springframework.beans.factory.UnsatisfiedDependencyException: Ошибка при создании bean с именем 'step1', определенной в классе по пути [com/example/batchprocessing/BatchConfiguration.class]: Неудовлетворенная зависимость, выраженная через метод 'step1', параметр 0: Ошибка при создании bean с именем 'jobRepository', определенной в классе по пути [com/example/batchprocessing/BatchConfiguration.class]: Не удалось создать экземпляр [org.springframework.batch.core.repository.JobRepository]: Фабричный метод 'jobRepository' выдал исключение с сообщением: Невозможно настроить репозиторий заданий по умолчанию
по адресу org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:795) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:542) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.10.jar:3.2.10]
по адресу org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.10.jar:3.2.10]
по адресу org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.2.10.jar:3.2.10]
по адресу org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.2.10.jar:3.2.10]
по адресу org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.2.10.jar:3.2.10]
по адресу com.example.batchprocessing.BatchProcessingApplication.main(BatchProcessingApplication.java:11) ~[classes/:na]
Причина: org.springframework.beans.factory.BeanCreationException: Ошибка при создании bean с именем 'jobRepository', определенной в классе по пути [com/example/batchprocessing/BatchConfiguration.class]: Не удалось создать экземпляр [org.springframework.batch.core.repository.JobRepository]: Фабричный метод 'jobRepository' выдал исключение с сообщением: Невозможно настроить репозиторий заданий по умолчанию
по адресу org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:648) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:485) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:904) ~[spring-beans-6.1.13.jar:6.1.13]
по адресу org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:782) ~[spring-beans-6.1.13.jar:6.1.13]
... 18 общих фреймов
Причина: org.springframework.batch.core.configuration.BatchConfigurationException: Невозможно настроить репозиторий заданий по умолчанию
по адресу org.springframework.batch.core.configuration.support.DefaultBatchConfiguration.jobRepository(DefaultBatchConfiguration.java:151) ~[spring-batch-core-5.1.2.jar:5.1.2]
по адресу com.example.batchprocessing.BatchConfiguration$$SpringCGLIB$$0.CGLIB$jobRepository$29(<генерируется>) ~[classes/:na]
по адресу com.example.batchprocessing.BatchConfiguration$$SpringCGLIB$$FastClass$$1.invoke(<генерируется>) ~[classes/:na]
по адресу org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258) ~[spring-core-6.1.13.jar:6.1.13]
по адресу org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:348) ~[spring-context-6.1.13.jar:6.1.13]
по адресу com.example.batchprocessing.BatchConfiguration$$SpringCGLIB$$0.jobRepository(<генерируется>) ~[classes/:na]
по адресу java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
по адресу java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
по адресу org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:146) ~[spring-beans-6.1.13.jar:6.1.13]
... 47 общих фреймов
Причина: org.springframework.batch.core.configuration.BatchConfigurationException: Для использования конфигурации по умолчанию должен быть определен bean источника данных с именем 'dataSource' в контексте приложения, но он не был найден. Переопределите getDataSource(), чтобы предоставить источник данных, который нужно использовать для метаданных Batch.
по адресу org.springframework.batch.core.configuration.support.DefaultBatchConfiguration.getDataSource(DefaultBatchConfiguration.java:250) ~[spring-batch-core-5.1.2.jar:5.1.2]
по адресу org.springframework.batch.core.configuration.support.DefaultBatchConfiguration.jobRepository(DefaultBatchConfiguration.java:132) ~[spring-batch-core-5.1.2.jar:5.1.2]
... 55 общих фреймов
——Код——
@SpringBootApplication
public class BatchProcessingApplication {
public static void main(String[] args) {
System.exit(SpringApplication.exit(SpringApplication.run(BatchProcessingApplication.class, args)));
}
}
@Configuration
public class BatchConfiguration extends DefaultBatchConfiguration {
//public class BatchConfiguration {
private static final Logger log = LoggerFactory.getLogger(BatchConfiguration.class);
@Bean("jdbcTemplate")
public JdbcTemplate jdbcTemplate( @Qualifier("pgDataSource")DataSource dataSource) {
log.info("******jobTemplate запущен******");
return new JdbcTemplate(dataSource);
}
@Bean("reader")
public FlatFileItemReader<Person> reader() {
log.info("******FlatFileItemReader******");
return new FlatFileItemReaderBuilder<Person>()
.name("personItemReader")
.resource(new ClassPathResource("sample-data.csv"))
.delimited()
.delimiter(",")
.names("firstName", "lastName")
.targetType(Person.class)
.build();
}
@Bean("processor")
public PersonItemProcessor processor() {
log.info("******PersonItemProcessor******");
return new PersonItemProcessor();
}
@Bean("writer")
public JdbcBatchItemWriter<Person> writer( @Qualifier("pgDataSource") DataSource dataRepository) {
log.info("******JdbcBatchItemWriter******");
return new JdbcBatchItemWriterBuilder<Person>()
.sql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)")
.dataSource(dataRepository)
.beanMapped()
.build();
}
@Bean("importUserJob")
public Job importUserJob(@Qualifier(
"mySQLJobRepository")JobRepository jobRepository,
Step step1,
JobCompletionNotificationListener listener) {
log.info("******importUserJob******");
return new JobBuilder("importUserJob", jobRepository)
.listener(listener)
.start(step1)
.build();
}
@Bean("step1")
public Step step1(JobRepository jobRepository,
DataSourceTransactionManager transactionManager,
@Qualifier("reader")FlatFileItemReader<Person> reader,
@Qualifier("processor")PersonItemProcessor processor,
@Qualifier("writer")JdbcBatchItemWriter<Person> writer) {
log.info("******step1******");
return new StepBuilder("step1", jobRepository)
.<Person, Person> chunk(3, transactionManager)
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
/***** Источники данных Spring Batch и репозиторий заданий*****/
/**
* Этот метод создает репозиторий заданий
* @param mySQLDataSource содержит объект dataSource для создания репозитория заданий
* @return
* @throws Exception
*/
@Bean("mySQLJobRepository")
public JobRepository jobRepository(DataSource mySQLDataSource) throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(mySQLDataSource);
factory.setTransactionManager(new DataSourceTransactionManager(mySQLDataSource));
factory.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE");
factory.setMaxVarCharLength(255);
factory.afterPropertiesSet();
return factory.getObject();
}
/**
* Этот метод создает источник данных на основе настроек свойств в "application.properties" для управления базой данных MySQL, используемой в качестве репозитория заданий.
*
* @return объект источника данных
*
* Примечание:
* Аннотации @ConfigurationProperty @Value избыточны для учебных целей, одной достаточно.
*/
@Primary
@Bean("mySQLDataSource")
@ConfigurationProperties(prefix = "db.job.repo")
public DataSource mySQLDataSource(
@Value("${db.job.repo.driverClassName}") String className,
@Value("${db.job.repo.jdbc-url}") String url,
@Value("${db.job.repo.username}") String userName,
@Value("${db.job.repo.schema}") String password) {
return DataSourceBuilder
.create()
.driverClassName(className)
.url(url)
.username(userName)
.password(password)
.build();
}
/**
* Этот метод создает источник данных на основе настроек свойств в "application.properties" для управления базой данных PostgreSQL, используемой в качестве репозитория данных.
* @return созданный объект dataSource
*
* Примечание:
* Аннотации @ConfigurationProperty @Value избыточны для учебных целей, одной достаточно.
*/
@Bean("pgDataSource")
@ConfigurationProperties(prefix = "db.src")
public DataSource pgDataRepository(
@Value("${db.src.driverClassName}") String className,
@Value("${db.src.jdbc-url}") String url,
@Value("${db.src.username}") String userName,
@Value("${db.src.password}") String password) {
return DataSourceBuilder
.create()
.driverClassName(className)
.url(url).username(userName)
.password(password)
.build();
}
}
@Component
public class JobCompletionNotificationListener implements JobExecutionListener {
private static final Logger log = LoggerFactory.getLogger(JobCompletionNotificationListener.class);
private final JdbcTemplate jdbcTemplate;
/**
* Конструктор - Позволяет создать объект/экземпляр JdbcTemplate, потому что spring data jdbc на пути JAVA библиотеки
* @param jdbcTemplate
*/
public JobCompletionNotificationListener(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void beforeJob(JobExecution jobExecution) {
JobExecutionListener.super.beforeJob(jobExecution);
log.info("Работа {} начата", jobExecution.getJobInstance().getJobName());
}
@Override
public void afterJob(JobExecution jobExecution) {
JobExecutionListener.super.afterJob(jobExecution);
log.info("Работа {} завершена", jobExecution.getJobInstance().getJobName());
if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
log.info("!!! РАБОТА ЗАВЕРШЕНА! Время проверить результаты");
jdbcTemplate.query("SELECT first_name, last_name FROM people", new DataClassRowMapper<>(Person.class))
.forEach(person -> log.info("Найдено - имя, фамилия ( {},{}) в базе данных.", person.firstName(),person.lastName() ));
}
}
}
public record Person(String firstName, String lastName) {}
public class PersonItemProcessor implements ItemProcessor<Person, Person> {
private static final Logger log = LoggerFactory.getLogger(PersonItemProcessor.class);
@Override
public Person process(final Person person) {
final String firstName = person.firstName().toUpperCase();
final String lastName = person.lastName().toUpperCase();
final Person transformedPerson = new Person(firstName, lastName);
log.info("Преобразуем (" + person + ") в (" + transformedPerson + ")");
return transformedPerson;
}
}
src/main/resource
***application.properties***
db.job.repo.driverClassName=com.mysql.cj.jdbc.Driver
db.job.repo.jdbc-url=jdbc:mysql://localhost:3306/batch-initial?currentSchema=batch-initial
db.job.repo.username=****
db.job.repo.password=*****
db.job.repo.schema=batch-initial
# Нужно ли заполнять схему для Spring Batch в случае, если она отсутствует
#batch.db.initialize-schema=ALWAYS
db.job.repo.initialize-schema=ALWAYS
db.src.jdbc-url=jdbc:postgresql://127.0.0.1:5432/SPRINGBATCH?currentSchema=batch-initial
db.src.username=******
db.src.password=******
db.src.driverClassName=org.postgresql.Driver
***data.sql***
DROP TABLE people IF EXISTS;
CREATE TABLE people (
-- id BIGINT AUTO_INCREMENT PRIMARY KEY,
person_id BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY,
first_name VARCHAR(20),
last_name VARCHAR(20)
);
***sample-data.txt***
Jill,Doe
Joe,Doe
Justin,Doe
Jane,Doe
John,Doe
Файл pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.10</version>
<relativePath/> <!-- искать родителя в репозитории -->
</parent>
<groupId>com.example</groupId>
<artifactId>batchprocessing</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Демо проект для Batch Service</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>22</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Я ожидал расширить DefauldBatchConfiguration
при настройке сервиса Spring Batch
Ответ или решение
Обзор ошибки UnsatisfiedDependencyException при расширении DefaultBatchConfiguration в Spring Batch
При разработке приложения на основе Spring Batch часто возникает необходимость настройки и расширения конфигураций. Однако, когда вы пытаетесь расширить DefaultBatchConfiguration
, это может привести к ошибке UnsatisfiedDependencyException
, как указывает ваш лог. Давайте глубже изучим эту проблему и предложим решение.
Суть проблемы
Ошибка UnsatisfiedDependencyException
возникает, когда Spring не может создать необходимый для компонента объект. В вашем случае возникает проблема с созданием JobRepository
, который используется для управления метаданными заданий в Spring Batch. Конкретное сообщение об ошибке:
Unable to configure the default job repository
указывает на то, что Spring не может найти необходимый бин DataSource
для конфигурации JobRepository
.
Причины
-
Отсутствие бина DataSource: Сообщение об ошибке явно указывает на то, что Spring не смог найти бин
DataSource
, который требуется для конфигурацииJobRepository
. -
Проблемы с конфигурацией: Если вы расширяете
DefaultBatchConfiguration
, не забудьте предоставить необходимые бины для работы.DefaultBatchConfiguration
ожидает, что в контексте будет доступенDataSource
, именуемыйdataSource
.
Решение
Чтобы устранить это предупреждение и ошибку, выполните следующие шаги:
-
Обеспечьте наличие бина DataSource:
Убедитесь, что у вас есть
DataSource
, названныйdataSource
, в вашем контексте Spring. Вы можете изменить вашу конфигурацию следующим образом:@Bean(name = "dataSource") @Primary @ConfigurationProperties(prefix = "spring.datasource") public DataSource dataSource() { return DataSourceBuilder.create().build(); }
В этом методе вы объявляете основной
DataSource
, который будет использоваться дляJobRepository
. -
Обновление метода JobRepository:
Убедитесь, что ваш метод для создания
JobRepository
использует правильный бинdataSource
. Вы можете настроить его следующим образом:@Bean @Override public JobRepository jobRepository() throws Exception { JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setDataSource(dataSource()); // Здесь используем бин dataSource factory.setTransactionManager(new DataSourceTransactionManager(dataSource())); factory.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE"); factory.afterPropertiesSet(); return factory.getObject(); }
-
Проверка файла application.properties:
Убедитесь, что ваш файл
application.properties
настроен правильно и содержит все необходимые данные для подключения к MySQL.spring.datasource.url=jdbc:mysql://localhost:3306/batch-initial spring.datasource.username=ваш_пользователь spring.datasource.password=ваш_пароль spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
Заключение
Настройка Spring Batch с использованием DefaultBatchConfiguration
требует внимательного подхода к обеспечению наличия необходимых бинов для работы вашего приложения. Обеспечив наличие корректного DataSource
и соответствующих методов, вы сможете избежать возникновения ошибок, таких как UnsatisfiedDependencyException
.
Если все сделано правильно, ваше приложение должно начать работать без ошибок. Это поможет вам углубить понимание работы Spring Batch и его конфигураций, а также успешного расширения стандартного функционала. Если у вас появятся дополнительные вопросы, не стесняйтесь обращаться за помощью к сообществу Spring или использовать ресурсы официальной документации.