복붙노트

[SPRING] 배치에서 내 데이터 소스를 사용하지 않는 스프링 배치 프로젝트를 만들고 싶습니다.

SPRING

배치에서 내 데이터 소스를 사용하지 않는 스프링 배치 프로젝트를 만들고 싶습니다.

(a) dataSource가 정의되거나 (b) dataSource가 정의되지 않은 Spring Batch 프로젝트의 예제를 많이 보았습니다.

그러나, 내 프로젝트에서, 내 비즈니스 논리 데이터 원본에 액세스 할 수 싶습니다,하지만 스프링 일괄 데이터 원본을 사용하지 싶습니다. 이것이 가능한가?

이 사람도 비슷한 문제가 있습니다 : 스프링 부트 + 스프링 배치 (DataSource 제외)

해결법

  1. ==============================

    1.일반적으로 데이터베이스없이 스프링 배치를 사용하는 것은 좋지 않습니다. 사용자가 정의한 작업의 종류에 따라 동시성 문제가 발생할 수 있기 때문입니다. 따라서 최소한 생산적인 데이터베이스를 사용하는 것이 강력히 권장됩니다. 특히 프로덕션 환경에서이 작업을 사용하려는 경우 더욱 그렇습니다.

    일반적으로 데이터베이스없이 스프링 배치를 사용하는 것은 좋지 않습니다. 사용자가 정의한 작업의 종류에 따라 동시성 문제가 발생할 수 있기 때문입니다. 따라서 최소한 생산적인 데이터베이스를 사용하는 것이 강력히 권장됩니다. 특히 프로덕션 환경에서이 작업을 사용하려는 경우 더욱 그렇습니다.

    스프링 부트와 함께 스프링 배치를 사용하면 자신의 데이터 소스를 구성하지 않으면 메모리 데이터 소스를 초기화합니다.

    이 점을 고려하여 다음과 같이 질문을 다시 정의 해 보겠습니다. 비즈니스 로직이 springbatch가 BATCH 테이블을 업데이트하는 데 사용하는 다른 데이터 소스를 사용할 수 있습니까? 예, 그럴 수 있습니다. 사실, SpringBatch 작업 내에서 원하는만큼 많은 데이터 소스를 사용할 수 있습니다. 이름 별 자동 와이어 링을 사용하십시오.

    여기 내가 어떻게하는지 : 나는 항상 내 Jobs에서 사용해야하는 모든 데이터 소스를 정의하는 Configuration 클래스를 사용한다.

    Configuration
    public class DatasourceConfiguration {
    
        @Bean
        @ConditionalOnMissingBean(name = "dataSource")
        public DataSource dataSource() {
            // create datasource, that is used by springbatch
            // for instance, create an inmemory datasource using the 
            // EmbeddedDatabaseFactory
            return ...; 
        }
    
        @Bean
        @ConditionalOnMissingBean(name = "bl1datasource")
        public DataSource bl1datasource() {
            return ...; // your first datasource that is used in your businesslogic
        }
    
        @Bean
        @ConditionalOnMissingBean(name = "bl2datasource")
        public DataSource bl2datasource() {
            return ...; // your second datasource that is used in your businesslogic
        }
    }
    

    세 가지 유의 사항 :

    SpringBatch는 "dataSource"라는 이름의 데이터 소스를 찾고 있는데,이 EXACT (대문자 'S') 이름을 이름으로 제공하지 않으면 스프링 배치가 유형에 따라 자동 연결을 시도하고 둘 이상의 DataSource 인스턴스를 찾으면, 그것은 예외를 던질 것이다.

    데이터 소스 구성을 자체 클래스에 넣으십시오. 당신의 직업 정의와 같은 클래스에 그들을 넣지 마십시오. Spring은 컨텍스트를로드 할 때 "dataSource"라는 이름으로 SpringBean을 매우 일찍 인스턴스화 할 수 있어야합니다. Job과 Step Beans를 인스턴스화하기 전에. 데이터 소스 정의를 작업 / 단계 정의와 동일한 클래스에 넣으면 Spring은이를 올바르게 수행 할 수 없습니다.

    @ConditionalOnMissingBean을 사용하는 것은 필수는 아니지만 좋은 실전을 발견했습니다. 단위 / 통합 테스트의 데이터 소스를 쉽게 변경할 수 있습니다. 예를 들어 "bl1Datasource"를 inMemoryDataSource로 덮어 쓰는 유닛 / IT 테스트의 ContextConfiguration에 추가 테스트 구성을 제공하십시오.

    Configuration
    public class TestBL1DatasourceConfiguration {
    
        // overwritting bl1datasource with an inMemoryDatasource.
        @Bean
        public DataSource bl1datasource() {
            return new EmbeddedDatabaseFactory.getDatabase(); 
        }
    }
    

    비즈니스 로직 데이터 소스를 사용하려면 이름으로 주입을 사용하십시오.

    @Component
    public class PrepareRe1Re2BezStepCreatorComponent {
    
        @Autowired
        private StepBuilderFactory stepBuilderFactory;
    
        @Autowired
        private DataSource bl1datasource;
    
        @Autowired
        private DataSource bl2datasource;
    
        public Step createStep() throws Exception {
            SimpleStepBuilder<..., ...> builder =
                    stepBuilderFactory.get("astep") //
                    .<..., ...> chunk(100) //
                    .reader(createReader(bl1datasource)) //
                    .writer(createWriter(bl2datasource)); //
    
            return builder.build();
        }
    }
    

    또한 여러 데이터 소스로 작업하고 싶다면 XA-Datasources를 사용하는 것이 좋습니다.

    편집 됨 :

    기본적으로 데이터 소스를 사용하고 싶지 않으므로 자신의 BatchConfigurer (http://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/core/configuration)를 구현해야합니다. /annotation/BatchConfigurer.html) (Michael Minella - SpringBatch 프로젝트 리드 - 위에서 지적한 바와 같이).

    org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer 코드를 자신의 구현을위한 시작점으로 사용할 수 있습니다. 단순히 모든 datasource / transactionmanager 코드를 제거하고 initialize 메소드에서 if (datasource === null) 부분의 내용을 유지하면됩니다. 그러면 MapBasedJobRepository 및 MapBasedJobExplorer가 초기화됩니다. 그러나 이것은 threadsafe가 아니기 때문에 다시 생산적인 환경에서 사용 가능한 솔루션이 아닙니다.

    편집 됨 :

    구현 방법 :

    "businessDataSource"를 정의하는 구성 클래스 :

    @Configuration
    public class DataSourceConfigurationSimple {
        DataSource embeddedDataSource;
    
        @Bean
        public DataSource myBusinessDataSource() {
            if (embeddedDataSource == null) {
                EmbeddedDatabaseFactory factory = new EmbeddedDatabaseFactory();
                embeddedDataSource = factory.getDatabase();
            }
            return embeddedDataSource;
        }
    }
    

    특정 BatchConfigurer의 구현 : (물론, 메소드를 구현해야합니다 ...)

    public class MyBatchConfigurer implements BatchConfigurer {
        @Override
        public JobRepository getJobRepository() throws Exception {
            return null;
        }
    
        @Override
        public PlatformTransactionManager getTransactionManager() throws Exception {
            return null;
        }
    
        @Override
        public JobLauncher getJobLauncher() throws Exception {
            return null;
        }
    
        @Override
        public JobExplorer getJobExplorer() throws Exception {
            return null;
        }
    }
    

    그리고 마지막으로 주요 구성 및 시작 클래스 :

    @SpringBootApplication
    @Configuration
    @EnableBatchProcessing
    
    // Importing MyBatchConfigurer will install your BatchConfigurer instead of
    // SpringBatch default  configurer.
    @Import({DataSourceConfigurationSimple.class, MyBatchConfigurer.class})
    
    public class SimpleTestJob {
    
        @Autowired
        private JobBuilderFactory jobs;
    
        @Autowired
        private StepBuilderFactory steps;
    
        @Bean
        public Job job() throws Exception {
            SimpleJobBuilder standardJob = this.jobs.get(JOB_NAME)
                                                    .start(step1());
            return standardJob.build();
        }
    
        protected Step step1() throws Exception {
            TaskletStepBuilder standardStep1 = this.steps.get("SimpleTest_step1_Step")
                                                         .tasklet(tasklet());
            return standardStep1.build();
        }
    
        protected Tasklet tasklet() {
            return (contribution, context) -> {
                System.out.println("tasklet called");
                return RepeatStatus.FINISHED;
            };
        }
    
        public static void main(String[] args) throws Exception {
            SpringApplication.run(SimpleTestJob.class, args);
        }
    }
    
  2. from https://stackoverflow.com/questions/40553985/i-would-like-to-create-a-spring-batch-project-where-batch-does-not-use-my-dataso by cc-by-sa and MIT license