Announcement Announcement Module
Collapse
No announcement yet.
Resource on MultiResourceItemReader Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Resource on MultiResourceItemReader

    I am a Spring batch newbie. Please help. I have a simple FlatFileReader wrapped in a multiresource item reader. I then write the details in a record in the database. I need to write the filename on every record. Please help me find the simplest way to do this. I found something about getResource?? But how am I suppose to wire this in?

    I have a mapper and a dto for the records that I read. The dto allready has a field for the filename.
    Extracts of my code:

    Code:
        <beans:bean id="MultiResourceItemReader.ImportDataJob" scope="step"
                    class="org.springframework.batch.item.file.MultiResourceItemReader">
            <beans:property name="resources" value="file:${data.extract.file.path}/${data.extract.file.thefile}*.txt"/>
            <beans:property name="delegate" ref="ItemReader.IstoreImportDataJob">
            </beans:property>
        </beans:bean>
    
        <beans:bean id="ItemReader.ImportDataJob"
                    class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
            <beans:property name="linesToSkip" value="1"/>
            <beans:property name="comments" value="001,999"/>
            <beans:property name="lineMapper">
                <beans:bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
                    <beans:property name="lineTokenizer">
                        <beans:bean
                                class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                            <beans:property name="delimiter" value="|"/>
                            <beans:property name="names"
                                            value= "aval,bval,cval,dval"/>
                            </beans:bean>
                    </beans:property>
                    <beans:property name="fieldSetMapper">
                        <beans:bean class="com.ImportFieldSetMapper"/>
                    </beans:property>
                </beans:bean>
            </beans:property>
        </beans:bean>
    
        <beans:bean id="ItemWriter.IstoreImportDataJob" class="org.springframework.batch.item.database.JdbcBatchItemWriter">
            <beans:property name="assertUpdates" value="false"/>
            <beans:property name="itemSqlParameterSourceProvider">
                <beans:bean name="sqlParameterSourceProvider" id="sqlParameterSourceProvider"
                            class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider"/>
            </beans:property>
            <beans:property name="sql" value="INSERT INTO TEST(A,B,C,D) VALUES (:aval,:bval,:cval,:dval)"/>
            <beans:property name="dataSource" ref="DataSourceBean.DEV.mhdev1"/>
    
        </beans:bean>

  • #2
    If you use the latest version of Spring Batch (2.2.0.M1), we have added a new concept of an item being ResourceAware. If your item implements the ResourceAware interface, the MultiResourceItemReader will inject a reference to the resource the item came from so that it is available for other artifacts to use.

    Comment


    • #3
      Does this mean I have to write a custom reader? For the moment I am getting everything to work by just wiring it up as above and then I have the ImportFieldSetMapper that just populates my dto by doing Fielset.readString, etc. Do you have an example or give me pointers on how to change the config above to get it to recognise the ResourceAware?

      Comment


      • #4
        If you use Spring Batch version 2.2.0.M1 or later, all you need to do is have your item implement ResourceAware with the MultiResourceItemReader. The rest just works.

        Comment


        • #5
          Guys,

          I am so sorry....my little bit of Spring knowledge is really letting me down. I struggled for a bit and left it and now came back. I think I made some progress...but I am still not getting it right. Firstly -we are unfortunately not using Spring 2.2.0 yet, and I don't have much say about that

          Here is what I did so far: I have overridden the FlatFileItemReader with my own simple one. Just overwrite the method setResource. Here I can actually print out the current resource to the console -so I know I have access to it at this point of time. BUT I need the resource to be set in the DTO that the FieldSetMapper is linked to. I don't know how to access the resource from there. I considered the stepContext, but not sure how to access it from the ItemReader and then the FieldSetMapper. I considered a listener - but wont that override and just keep the last resource? I also tried to set up a property in my FieldSetMapper called resource of type object. Hoping I could inject it with something from the xml configuration. But all I managed was giving it a String value - whatever I typed in there

          So the question is....can I go from the setResouce in the FlatFileItemReader and use this resource to set the value in my dto. Or perhaps is there a way I can inject the current resource into my resource object in my FieldSetMapper?

          Just for a slightly bigger picture: I have multiple files and the dto needs to indicate which file it came from. I read a list of files with a unique number into a map that is in he jobExecutionontext currently. So when know what the current resource is, the idea is to find it in the map and set the unique primary key as part of the dto (so it references nicely in the database).

          Alternatively what is the easiest way to do this?

          Comment


          • #6
            Here is what I would do. Take a look at the updated MulitResourceItemReader. That is where the ResourceAware is used. Just copy our version into your project for now so that when you do upgrade to 2.2.x in the future, you'll just need to update package names and everything will "just work".

            Comment


            • #7
              Thank you. This seems to do the trick.

              Comment


              • #8
                Solution

                In case someone comes across this forum. I wanted to put down the solution I ended up using. So if you missed it:

                I have a list of filenames and a unique number identifying this name in a map that I stored on the jobExecutionContext. I need to get the current resource from the multiresource reader and the DTO that gets populated by my FieldSetMapper must contain this unique reference number.

                I used all mminella's suggestions.

                Created my own multiresourceItemReader and used the latest version of Spring Batch source code to populate this (as we are not using latest Spring batch yet). I also had to create my own ResourceAware interface.

                My "item" (in my case a dto) has to implement resourceAware and thus also have a resource property that can be set (the multi reader will take care of the rest).

                I then implemented a StepExecutionListener in my processor, in the beforeStep I get the value of the map with filenames and set a local property on the class. Then when the processor runs I get the resource from the dto, get the link from the map and set the value of the unique sequence on my dto.

                Comment


                • #9
                  Hi Zenoe,

                  I have a similar requirement. Could you please share your own multiresourceitemreader, ResourceAware Interface and your Item.

                  Comment

                  Working...
                  X