2016-03-08 100 views
0

根據Spring批處理documentationJobScope作爲Spring批處理3.0的一部分引入。但是,它看起來像JobScope註釋在Spring批處理3.0罐中不可用。我指定我pom.xmlspring-batch-core依賴如下:Spring批處理:JobScope在Spring 3.0.0中不可用

<properties> 
    <jdk.version>1.6</jdk.version> 
    <spring.version>4.2.4.RELEASE</spring.version> 
    <spring.batch.version>3.0.0.RELEASE</spring.batch.version> 
</properties> 

<dependencies> 

    <!-- Spring Batch dependencies --> 
    <dependency> 
     <groupId>org.springframework.batch</groupId> 
     <artifactId>spring-batch-core</artifactId> 
     <version>${spring.batch.version}</version> 
    </dependency> 

當我改變spring-batch-version3.0.6,如預期的那樣JobScope註解中找到。我的理解是JobScope是作爲Spring批處理3.0的一部分引入的,因此應該可以在任何從3.0.0開始的彈簧批處理罐中使用。

是否有任何具體原因爲什麼JobScope註釋在版本3.0.0中不可用或者我是否需要手動添加包含此註釋的其他jar?我相信spring-batch-core依賴關係應該拉出所有額外的spring批處理依賴關係,我不需要明確指定它們。

我正在使用基於註釋的配置來編寫批處理作業。我需要JobScope註釋來將作業參數的後期綁定到我的bean。有沒有辦法做到這一點,而不使用JobScope

編輯

我的工作配置文件如下:

@Configuration 
@EnableBatchProcessing 
public class FileLoaderConfigurationNoAbstractLoader { 

    @Autowired 
    private ResourcePatternResolver resourcePatternResolver; 

    @Bean 
    public Job job(JobBuilderFactory jobs, Step s1) { 
     return jobs.get("FileLoader").incrementer(new RunIdIncrementer()).start(s1).build(); 
    } 

    @Bean 
    @StepScope 
    @SuppressWarnings("rawtypes") 
    public FlatFileItemReader reader(@Value("#{stepExecutionContext['fileName']}") String filePath, 
      @Value("#{jobParameters['fieldSetMapperClass']}") String fieldSetMapperClass, 
      @Value("#{jobParameters['processType']}") String processType, @Value("#{jobParameters['dataType']}") String dataType, 
      FileLoaderCreator loader) { 
     String path = filePath.substring(filePath.indexOf(":") + 1, filePath.length()); 
     return loader.getReader(path, fieldSetMapperClass, processType, dataType); 
    } 

    @Bean 
    @Scope(value = "job", proxyMode = ScopedProxyMode.TARGET_CLASS) 
    @SuppressWarnings("rawtypes") 
    public ItemWriter writer(@Value("#{jobParameters['dataType']}") String dataType) { 
     return new CollectionItemWriter(dataType); 
    } 

    @Bean 
    @Scope(value = "job", proxyMode = ScopedProxyMode.TARGET_CLASS) 
    @SuppressWarnings("rawtypes") 
    public ItemProcessor processor(FileLoaderCreator loader, @Value("#{jobParameters['itemProcessorClass']}") String itemProcessorClass) { 
     return loader.getItemProcessor(itemProcessorClass); 
    } 

    @Bean 
    @Scope(value = "job", proxyMode = ScopedProxyMode.TARGET_CLASS) 
    @SuppressWarnings("all") 
    public Step readStep(StepBuilderFactory stepBuilderFactory, ItemReader reader, ItemWriter writer, ItemProcessor processor, 
      TaskExecutor taskExecutor, FileLoaderCreator fileLoader, @Value("#{jobParameters['dataType']}") String dataType, 
      @Value("#{jobParameters['processType']}") String processType) { 

     final Step readerStep = stepBuilderFactory.get(dataType + " ReadStep:slave") 
       .chunk(fileLoader.getCommitInterval(processType, dataType)).reader(reader).processor(processor).writer(writer) 
       .taskExecutor(taskExecutor).throttleLimit(fileLoader.getThrottleLimit(processType, dataType)).build(); 

     final Step partitionedStep = stepBuilderFactory.get(dataType + " ReadStep:master").partitioner(readerStep) 
       .partitioner(dataType + " ReadStep:slave", partitioner(fileLoader, null, null)).taskExecutor(taskExecutor).build(); 

     return partitionedStep; 

    } 

    @Bean 
    @Scope(value = "job", proxyMode = ScopedProxyMode.TARGET_CLASS) 
    public Partitioner partitioner(FileLoaderCreator fileLoader, @Value("#{jobParameters['processType']}") String processType, 
      @Value("#{jobParameters['dataType']}") String dataType) { 
     MultiResourcePartitioner partitioner = new MultiResourcePartitioner(); 
     Resource[] resources; 
     try { 
      resources = resourcePatternResolver.getResources("file:" + fileLoader.getPath(processType, dataType) 
        + fileLoader.getFilePattern(processType, dataType)); 
     } catch (IOException e) { 
      throw new RuntimeException("I/O problems when resolving the input file pattern.", e); 
     } 
     partitioner.setResources(resources); 
     return partitioner; 
    } 

    /* 
    * Use this if you want the writer to have job scope (JIRA BATCH-2269). 
    * Might also change the return type of writer to ListItemWriter for this to 
    * work. 
    */ 
    @SuppressWarnings("serial") 
    @Bean 
    public TaskExecutor taskExecutor() { 
     return new SimpleAsyncTaskExecutor() { 
      @Override 
      protected void doExecute(final Runnable task) { 
       // gets the jobExecution of the configuration thread 
       final JobExecution jobExecution = JobSynchronizationManager.getContext().getJobExecution(); 
       super.doExecute(new Runnable() { 
        public void run() { 
         JobSynchronizationManager.register(jobExecution); 

         try { 
          task.run(); 
         } finally { 
          JobSynchronizationManager.close(); 
         } 
        } 
       }); 
      } 
     }; 
    } 

    @Bean 
    public FileLoaderCreator loader() { 
     System.out.println("Creating loader only once "); 
     return new FileLoaderCreator(); 
    } 

    @Bean 
    public JobResults jobResults() { 
     return new JobResults(); 
    } 
} 

M.Deinum's建議,我用@Scope(value = "job", proxyMode = ScopedProxyMode.TARGET_CLASS)代替JobScope註解,但是遇到了以下異常:

java.lang.IllegalStateException: No Scope registered for scope name 'job'' exception

我試圖通過添加以下豆上述配置固定這樣的:

@Bean 
    public JobScope jobScope() { 
     JobScope scope = new JobScope(); 
     scope.setAutoProxy(false); 
     return scope; 
    } 

這讓我在我的Java配置以下行異常:

resources = resourcePatternResolver.getResources("file:" + fileLoader.getPath(processType, dataType) 
       + fileLoader.getFilePattern(processType, dataType)); 

注意這與完美的罰款JobScope和spring批處理3.0.1。

+0

它被添加到3.0.1中。但使用'@ JobScope'與使用'@Scope(value =「job」,proxyMode = ScopedProxyMode.TARGET_CLASS)''相同。但爲什麼不簡單地使用3.0.6這是最新的3.0版本,爲什麼堅持使用舊版本? –

+0

@ M.Deinum True。包含這個註釋的最低版本似乎是3.0.1。這是否意味着如果我必須使用基於註釋的作業配置,我不得不使用3.0.1或更高版本?我們公司有一個框架審批流程,目前批准的spring批處理版本是3.0.0。 – CKing

+0

查看我編輯的評論... –

回答

1

我正在使用基於註釋的配置來編寫批處理作業。我需要 JobScope註釋將作業參數的後期綁定到我的 bean。有沒有辦法做到這一點,而不使用JobScope?

它應該沒有Jobscope,通過使用Stepscope可以訪問jobparameters,看到https://docs.spring.io/spring-batch/reference/html/configureStep.html#step-scope

,如果你需要的所有豆可用的信息,你可以實現一個簡單的Spring bean(類型併發的HashMap)持有的信息

,如果你需要的信息持續了每批來看,你可以實現一個JobExecutionListener這使/拉*的信息在JobExecutionContext和填充(上述)簡單的bean

*)如果您需要重新啓動

+0

謝謝。我對「StepScope」的理解是,每次執行該步驟都會創建一個新的bean。由於我正在使用分區,我相信每個分區都會執行一個新的「Step」。因此,每次執行「Step」時都會有一個標記爲「StepScope」的每個bean的新實例。這種理解是否正確?如果是,我會創建一個項目編寫器和項目處理器的太多實例(每個分區一個),即使每個作業執行一個實例是我真正想要的。另外,建議在工作環境中存儲大量數據? – CKing

+0

現在我真的不能想象一個無狀態的讀者爲x分區(特別是不用於文件資源),處理/編寫它是很有可能的,除了文件資源,在你的例子中,它依賴於「dataType」只有你可以提供上述備用解決方案 –

+0

這是正確的。我不指望讀者是無國籍的。我對擁有'StepScope'的讀者沒問題。但是,我沒有看到作者或處理器應該具有「StepScope」的原因。如果我理解正確,如果我想堅持使用Spring 3.0.0版,您會發現這是我唯一的選擇嗎? – CKing