Announcement Announcement Module
Collapse
No announcement yet.
Dynamically setting FlatFileItemReader.resource Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dynamically setting FlatFileItemReader.resource

    Hi everyone, I have pretty much solved my external mapping issue however have one additional problem to solve for.

    I would like to be able to modify the resource property of FlatFileItemReader at runtime with a value sourced earlier in the job.

    I have the current job:

    Code:
    <job id="processTrades">
    	<step id="step1" next="step2">
    		<tasklet ref="mappingLoaderTasklet" />
    	</step>
    	<step id="step2">
    		<tasklet>
    			<chunk reader="tradeReader" processor="tradeProcessor" writer="tradeWriter" commit-interval="1" />
    		</tasklet>
    	</step>
    </job>
    mappingLoaderTasklet is used to load a static class with some mapping details from an external configuration file that can be used throughout the job.

    Code:
    package com.windebank.projects.tradeloader;
    
    import org.apache.log4j.Logger;
    import org.springframework.batch.core.StepContribution;
    import org.springframework.batch.core.scope.context.ChunkContext;
    import org.springframework.batch.core.step.tasklet.Tasklet;
    import org.springframework.batch.repeat.RepeatStatus;
    
    public class MappingLoaderTasklet implements Tasklet {
    
    	final Logger logger = Logger.getLogger(MappingLoaderTasklet.class);
    	
    	private String inputFile;
    
    	public String getInputFile() {
    		return inputFile;
    	}
    
    	public void setInputFile(String inputFile) {
    		this.inputFile = inputFile;
    	}
    
    	public RepeatStatus execute(StepContribution contribution,
    			ChunkContext chunkContext) throws Exception {
    
    		TradeMapping.inputFile = inputFile;
    		TradeMapping.read();
    		
    		logger.info("MappingLoaderTasklet: " + inputFile);
    
    		return null;
    	}
    }
    One of these mapping fields is the input file location that I want used by the ItemReader. I would like to be able to effectively do the following:

    Code:
    FlatFileItemReader.resource = TradeMapping.fileName
    I just don't know how this can work when interacting with the beans. I know I can use late binding from the JobParameters as follows:

    Code:
    <beans:bean name="tradeReader"
    	class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
    	<beans:property name="lineMapper" ref="tradeLineMapper" />
    	<beans:property name="resource" value="#{jobParameters['inputFile']}" />
    </beans:bean>
    However this still isn't late enough binding for what I want.

    Anyone got any ideas please?

  • #2
    If you don't expose the inputFile as job parameter it will not be available. You only set it inside your tasklet and not as a job parameter, hence your binding isn't working. You can store the attribute/add it to the execution context and retrieve it from there. If my memory serves me well there is either a sample doing that or it is written out in the Spring Batch Reference Guide.

    Also storing attributes in a class with static members isn't a very good idea IMHO (what happens if you have 2 instances of the job running, what about restartability ?!). But that is just IMHO ofcourse .

    Comment


    • #3
      Thanks Marten. I am only using the static members for now to solve the problem of not being able to pass objects around, however the execution context appears to solve this. Thank you!

      I have one additional question I'm hoping someone can help with please. If I look at how to implement functionality to save an object to the execution context, it requires me to modify the ItemReader. Eg:

      Code:
      public class SavingItemWriter implements ItemWriter<Object> {
          private StepExecution stepExecution;
      
          public void write(List<? extends Object> items) throws Exception {
              // ...
      
              ExecutionContext stepContext = this.stepExecution.getExecutionContext();
              stepContext.put("someKey", someObject);
          }
      
          @BeforeStep
          public void saveStepExecution(StepExecution stepExecution) {
              this.stepExecution = stepExecution;
          }
      }
      This looks fine except my program is using the built in FlatFileItemReader and so I have nowhere to add the code as required. I am trying to get my head around this and it looks like I might need a delegate, or to extend the FlatFileItemReader. Am I on the right path here please? If so, can anyone provide any tips or references for me as the Spring Batch Reference is a little light on info around these.

      Thanks again.

      Comment

      Working...
      X