Spring Batch с модульным = true не работает для нескольких заданий - PullRequest
3 голосов
/ 22 апреля 2020

Я пытаюсь настроить два задания с @EnableBatchProcessing(modular = true). Это нужно для предотвращения присвоения имени cla sh, насколько я понимаю.

Вот моя конфигурация работы:

@Configuration
public class Dummy1 {

    @Autowired
    JobBuilderFactory jobBuilderFactory;
    @Autowired
    StepBuilderFactory stepBuilderFactory;

    @Bean
    public Step step() {
        // < build step. Omitted for code clarity > 
    }

    @Bean
    public Job getJob() {
        return jobBuilderFactory.get("dummy-job-1")
                .start(step())
                .build();
    }
}

У меня есть аналогичный класс с именем Dummy2.

Я также определил следующую конфигурацию:

@Configuration
@EnableAutoConfiguration
@EnableBatchProcessing(modular = true)
public class BatchConfig {

    @Bean
    public ApplicationContextFactory getDummy1() {
        return new GenericApplicationContextFactory(Dummy1.class);
    }

    @Bean
    public ApplicationContextFactory getDummy2() {
        return new GenericApplicationContextFactory(Dummy2.class);
    }
}

При запуске приложения я получаю:

Bean-компонент 'step', определенный в ресурсе пути к классу [~ PATH ~ /Dumm2.class], не может быть зарегистрирован. Компонент с таким именем уже определен в ресурсе пути к классу [~ PATH ~ / Dumm1.class], и переопределение отключено.

Но я подумал, что это все, что является модульным = true. То есть обрабатывать имена конфликтами.

С другой стороны, если я разрешу переопределение бина, у меня останется вторая работа, переопределяющая первую.

т.е. @Autowired List<Job> имеет только одно задание (из Dummy2.class)

Как правильно настроить эти задания?

1 Ответ

1 голос
/ 25 апреля 2020

@EnableBatchProcessing - аннотация Spring Batch, предшествующая Spring Boot. Таким образом, вы должны рассмотреть, как это работает в контексте Spring Boot. Я взглянул на ваш пример приложения. Позвольте мне сначала объяснить, что происходит, а затем я объясню, как это исправить.

Проблема

Когда вы настраиваете @EnableBatchProcessing(modular=true), в соответствии с javado c, у вас не должно быть @Bean определений в текущем контексте, которые вы не хотите загружать. Вместо этого вы предоставляете ApplicationContextFactory реализации как @Bean, каждая из которых определяет дочерний контекст для задания.

Однако в вашем приложении есть ловушка. Как уже отмечалось, @EnableBatchProcessing предшествует Spring Boot, и вам необходимо подумать о том, как он работает в контексте Spring Boot. В вашем случае пример приложения содержит все классы в одном пакете. По умолчанию Spring Boot выполняет сканирование пути к классам для @Configuration аннотированных классов в пакете, для которого вы определяете класс, отмеченный @SpringBootApplication и «ниже». Итак, в вашем примере приложения Spring Boot автоматически вводит Dummy1 и Dummy2 в то, что должно быть родительским контекстом, вызывающим вашу ошибку.

Решение

Чтобы устранить эту проблему, необходимо запретить загрузке Spring Boot конфигурации вашего дочернего контекста с проверкой пути к классам. Чтобы доказать это, я протестировал ваше примерное приложение, переместив Dummy1 и Dummy2 в пакет com.example (на один уровень выше класса, помеченного @SpringBootApplication). Это предотвратило загрузку Spring Boot при сканировании пути к классам и позволило приложению правильно запускаться ... с двумя другими незначительными изменениями:

  1. Хотя имена бинов могут дублироваться в модульной конфигурации, фактические названия работы не могут. В Dummy1 и Dummy2 оба имени задания были настроены на dummy-job-1. Измените его на dummy-job-2, и это решает эту проблему.
  2. Для Spring Boot требуется источник данных для пакетных приложений. Я добавил HSQLDB в POM, чтобы проверить мое исправление, и оно сработало.

С этими изменениями вы сможете создать приложение и запустить его с помощью команды: java -jar target/demo-0.0.1-SNAPSHOT.jar --spring.batch.job.names=dummy-job-1 для запуска задания 1 или java -jar target/demo-0.0.1-SNAPSHOT.jar --spring.batch.job.names=dummy-job-2 для запуска задания 2.

Есть много других способов перемещать классы, чтобы предотвратить сканирование пути к классам Spring Boot, чтобы поднять их, и пока Spring Boot не берет Dummy1 и Dummy2, приложение должно работать так, как вы ожидаете. Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...