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

  • LineTokenizer in FlatFileItemReader

    It looks like the LineTokenizer was removed from the FlatFileItemReader in 2.0, based on the updated documentation (http://static.springframework.org/sp...temReader.html ), but the User Guide and samples still seem to say that's how I tokenize lines in 2.0 (ref http://static.springframework.org/sp...s.html#d0e4219 and http://static.springframework.org/sp....html#football ). When I try to use it as the user guide and samples show, I get the following exception:

    Code:
     org.springframework.beans.NotWritablePropertyException: Invalid property 'lineTokenizer' of bean class [org.springframework.batch.item.file.FlatFileItemReader]: Bean property 'lineTokenizer' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
    Here's the reader I'm creating:

    Code:
    <bean id="pubFinIdItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
    	<property name="resource" value="file:/#{jobParameters[srcDir]}/#{jobParameters[fileName]}" />
    	<property name="lineTokenizer">
    		<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
    			<property name="delimiter" value="|"/>
    			<property name="names" value="publ_id,fin_id" />
    		</bean>
    	</property>
    	<property name="fieldSetMapper">
    		<bean class="com.me.batch.mapping.PubFinIdDataMapping" >
    			<property name="invalidFinDataWriter" ref="invalidFinDataWriter" />
    		</bean>
    	</property>
    </bean>
    I've looked all over, and can only find this as the method of doing what I want to do - grab the lines from the file and tokenize them. How do I do this now in 2.0? What am I missing?

    Thanks!

  • #2
    We have inserted another layer. In 1.x, you set the tokenizer and fieldSetMapper directly onto the FlatFileItemReader. In 2.0, there is a lineMapper property instead. The easiest way to make the transition to 2.0 is to use the DefaultLineMapper on your FFIR. The DefaultLineMapper holds both a tokenizer and a fieldSetMapper and uses them to perform the same behavior as in 1.x.

    See: http://static.springframework.org/sp...ineMapper.html

    Comment


    • #3
      That worked. Thank you for your help!

      I'm having another problem with something that seems to have changed from v1 to 2.0. We've got some old config files that have something like this:

      Code:
      <bean id="invalidFinDataWriter" class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
      	<property name="resource" ref="file:/#{jobParameters[invalidDir]}/#{jobParameters[invalidFileName]}" />
      	<property name="fieldSetCreator">
      		<bean class="org.springframework.batch.item.file.mapping.PassThroughFieldSetMapper"/>
      	</property>
      </bean>
      
      <bean id="pubFinIdItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
      	<property name="resource" value="file:/#{jobParameters[srcDir]}/#{jobParameters[fileName]}" />
      	<property name="lineMapper">
      		<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
      			<property name="lineTokenizer">
      				<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
      					<property name="delimiter" value="|"/>
      					<property name="names" value="publ_id,fin_id" />
      				</bean>
      			</property>
      			<property name="fieldSetMapper">
      				<bean class="com.me.batch.mapping.PubFinIdDataMapping" >
      					<property name="invalidFinDataWriter" ref="invalidFinDataWriter" />
      				</bean>
      			</property>
      		</bean>
      	</property>
      </bean>
      The part I'm having trouble with is passing invalidFinDataWriter into my class PubFinIdDataMapping. That class contains:

      Code:
      public void setInvalidFinDataWriter (FlatFileItemWriter invalidFinDataWriter){
      	this.invalidFinDataWriter = invalidFinDataWriter;
      }
      When I do this, I get the exception:

      Code:
       java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy16 implementing org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,org.springframework.beans.factory.InitializingBean,org.springframework.aop.scope.ScopedObject,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,java.io.Serializable] to required type [org.springframework.batch.item.file.FlatFileItemWriter]: no matching editors or conversion strategy found
      I cribbed this code from an existing set we have in production running on spring batch 1.1, so I'm fairly certain this should work. Any ideas?

      Comment


      • #4
        I think the problem is that the late-binding code automatically proxies the class on which the binding occurs. In this case, that would be invalidFinDataWriter. The proxy is actually wrapping the object, so it is technically not a FlatFileItemWriter any more, which means that it can't cast to a FlatFileItemWriter when the setter is called.

        However, setting the writer as a property of the reader is a bit strange. What was the reason for doing this? And would it be better to separate them completely?

        Comment


        • #5
          We're doing that to write lines that aren't parseable to a file so we can determine why they didn't parse - the mapper is returning a pojo based on the publ_id. If the publ_id isn't found, we want to write that line to the invalid file. If that's not possible this way, we'll figure out another way to do it.

          Thanks!

          Comment


          • #6
            It's perfectly possible. Why do you need to inject FlatFileItemWriter though (wouldn't ItemWriter be sufficient)?

            Comment


            • #7
              Originally posted by Dave Syer View Post
              It's perfectly possible. Why do you need to inject FlatFileItemWriter though (wouldn't ItemWriter be sufficient)?
              Concur, you should be injecting an ItemWriter not a FFIW. This also would allow you to plugin in a different ItemWriter down the road that writes to a db or somewhere else without having to modify your reader.

              Comment


              • #8
                I'm not really sure what you mean. I get that I should change the setter to take in an ItemWriter rather than a FlatFileItemWriter, but what else do I need to change to do that?

                Comment


                • #9
                  I think all chudak is trying to say is that you shouldn't tie yourself a FlatFileItemWriter when an ItemWriter is all you need. If you reference the implementation instead of the interface, then you will limit your flexibility, for instance, if you decided later that you wanted to write invalid lines to the database instead of a flat file.

                  Comment


                  • #10
                    How do i give a Line Tokenizer for a flatfileItemReader in Springbatch 2.0.

                    How do i give a Line Tokenizer for a flatfileItemReader in Springbatch 2.0.
                    Unable to give LineTokenizer.Please help



                    <bean id="itemReader" class="org.springframework.batch.item.file.FlatFil eItemReader">
                    <property name="resource" value="file:./hello.txt" />
                    <property name="lineMapper" ref="lineMapper" />
                    </bean>
                    <bean id="lineMapper"
                    class="org.springframework.batch.item.file.mapping .DefaultLineMapper">
                    <property name="tokenizer" ref="tokenizer" />
                    <property name="fieldSetMapper" ref="fieldSetMapper" />
                    </bean>
                    <bean id="tokenizer"
                    class="org.springframework.batch.item.file.transfo rm.DelimitedLineTokenizer">
                    <property name="delimiter" value="H"/>
                    </bean>
                    <bean id="fieldSetMapper"
                    class="org.springframework.batch.item.file.mapping .PassThroughFieldSetMapper" />

                    Comment

                    Working...
                    X