title: How to use BeanWrapperFieldSetMapper to map a subset of fields?
body: <p>I have a Spring batch application where <code>BeanWrapperFieldSetMapper</code> is used to map fields using a prototype object. However, the CSV file that is being read (via a <code>FlatFileItemReader</code>) contains one (indicator) field that determines the mapping of another field. If the indicator field has a value of Y, then the value of the another field should be mapped to property <code>foo</code> otherwise it should be mapped to property <code>bar</code>.</p>
  
  <p>I know that I can use a custom <code>FieldSetMapper</code> to do this, but then I have to code the mapping all of the other fields (of which there are a quite a few). Alternatively, I could do this post reading via an <code>ItemProcessor</code> but then my domain (prototype) object must have a property representing the indicator field (which I prefer not to do since it is not really part of the business domain).</p>
  
  <p>Is it possible to perhaps use a custom <code>FieldSetMapper</code> to only map these custom fields and delegate the other mappings to <code>BeanWrapperFieldSetMapper</code>? Or is there some other better way to solve for this?</p>
  
  <p>Here is my current attempt to use a custom <code>FieldSetMapper</code> and delegate to <code>BeanWrapperFieldSetMapper</code>:</p>
  
  <pre><code>public class DelegatedFieldSetMapper extends BeanWrapperFieldSetMapper&lt;MyProtoClass&gt; {
  
      @Override
      public MyProtoClass mapFieldSet(FieldSet fieldSet) throws BindException {       
          String indicator = fieldSet.readString("indicator");
          Properties fieldProperties = fieldSet.getProperties();
  
          if (indicator.equalsIgnoreCase("y")) {
              fieldProperties.put("test.foo", fieldSet.readString("value");
          } else {
              fieldProperties.put("test.bar", fieldSet.readString("value");
          }
  
          fieldProperties.remove("indicator");
          Set&lt;Object&gt; keys = fieldProperties.keySet();
          List&lt;String&gt; names = new ArrayList&lt;String&gt;();
          List&lt;String&gt; values = new ArrayList&lt;String&gt;();      
          for (Object key : keys) {
              names.add((String) key);
              values.add((String) fieldProperties.getProperty((String) key));
          }
          DefaultFieldSet domainObjectFieldSet = new DefaultFieldSet(names.toArray(new String[names.size()]), values.toArray(new String[values.size()]));     
          return super.mapFieldSet(domainObjectFieldSet);
      }
  
  }
  </code></pre>
  
  <p>However, a FlatFileParseException is thrown. The relevant parts of the batch config class are as follows:</p>
  
  <pre><code>@Configuration
  @EnableBatchProcessing
  public class BatchConfiguration { 
  
      @Value("${file}")
      private File file;
  
      @Bean
      @Scope("prototype")
      public MyProtoClass () {
          return new MyProtoClass();
      }
  
      @Bean
      public ItemReader&lt;MyProtoClass&gt; reader(LineMapper&lt;MyProtoClass&gt; lineMapper) {
          FlatFileItemReader&lt;MyProtoClass&gt; flatFileItemReader = new FlatFileItemReader&lt;MyProtoClass&gt;();
          flatFileItemReader.setResource(new FileSystemResource(file));
          final int NUMBER_OF_HEADER_LINES = 1;
          flatFileItemReader.setLinesToSkip(NUMBER_OF_HEADER_LINES);
          flatFileItemReader.setLineMapper(lineMapper);
          return flatFileItemReader;
      }
  
      @Bean 
      public LineMapper&lt;MyProtoClass&gt; lineMapper(LineTokenizer lineTokenizer, FieldSetMapper&lt;MyProtoClass&gt; fieldSetMapper) {
          DefaultLineMapper&lt;MyProtoClass&gt; lineMapper = new DefaultLineMapper&lt;MyProtoClass&gt;();
          lineMapper.setLineTokenizer(lineTokenizer);
          lineMapper.setFieldSetMapper(fieldSetMapper);
          return lineMapper;
      }
  
      @Bean
      public LineTokenizer lineTokenizer() {
          DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();        
          lineTokenizer.setNames(new String[] {"value", "test.bar", "test.foo", "indicator"});
          return lineTokenizer;
      }
  
      @Bean
      public FieldSetMapper&lt;MyProtoClass&gt; fieldSetMapper(PropertyEditor emptyStringToNullPropertyEditor) {
          BeanWrapperFieldSetMapper&lt;MyProtoClass&gt; fieldSetMapper = new DelegatedFieldSetMapper();
          fieldSetMapper.setPrototypeBeanName("myProtoClass");
          Map&lt;Class&lt;String&gt;, PropertyEditor&gt; customEditors = new HashMap&lt;Class&lt;String&gt;, PropertyEditor&gt;();
          customEditors.put(String.class, emptyStringToNullPropertyEditor);
          fieldSetMapper.setCustomEditors(customEditors);
          return fieldSetMapper;
  
      }
  </code></pre>
  
  <p>Finally, the CSV flat file look like this:</p>
  
  <pre><code>value,bar,foo,indicator
  abc,,,y
  xyz,,,n
  </code></pre>