Announcement Announcement Module
Collapse
No announcement yet.
Getting Current Resource Filename in ItemReader Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Getting Current Resource Filename in ItemReader

    Hi,

    I currently have a class InvoiceFileItemReader which implements ItemReader. I am overriding the read() method and I need to access the filename of the currently executing file. I know that a MultiResourceItemReader has a getCurrentResource() method. I want to do the same sort of thing using an ItemReader.

    What is the best possible way to achieve this?

    Any help will be greatly appreciated.

    Thanks,

  • #2
    Where is the source of the filename? Where are you looking to retrieve it from?

    Comment


    • #3
      Hi mminella,

      Thanks for your response. Let me provide you with more information as well as my configuration. I am fairly new to Spring and Spring Batch so I am not sure if what I have done is correct.

      An extract of invoice-context.xml
      Code:
      <bean id="invoiceFileReader" class="za.org.joburg.shared.batch.InvoiceFileItemReader">
      	<property name="delegate" ref="ffItemReader" />
      	<property name="exceptionDAO" ref="exceptionDAO"/>
      </bean>
      
      <bean id="ffItemReader" class="org.springframework.batch.item.file.MultiResourceItemReader">
      	<property name="strict" value="false" />
      	<property name="resources" value="${batch.inv.file.location}" />
      	<property name="delegate">
      		<bean class="org.springframework.batch.item.file.FlatFileItemReader">
      			<property name="strict" value="false" />
      			<property name="lineMapper">
      				<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
      					<property name="lineTokenizer" ref="invoiceFileTokenizer" />
      					<property name="fieldSetMapper">
      						<bean class="org.springframework.batch.item.file.mapping.PassThroughFieldSetMapper" />
      					</property>
      				</bean>
      			</property>
      		</bean>
      	</property>
      </bean>
      As you can see from the configuration above, the list of files is in a directory and I read the location from a properties file.

      An extract from InvoiceFileItemReader.java
      Code:
      public class InvoiceFileItemReader implements ItemReader<SourceFile> {
      	private ItemReader<FieldSet> delegate;
      
      	public ItemReader<FieldSet> getDelegate() {
      		return delegate;
      	}
      
      	public void setDelegate(ItemReader<FieldSet> delegate) {
      		this.delegate = delegate;
      	}
      
      	public SourceFile read() throws Exception, UnexpectedInputException, ParseException {
      		SourceFile sourceFile = new SourceFile();
      		sourceFile.setFilename(((MultiResourceItemReader<FieldSet>) delegate).getCurrentResource().getFilename());
      	}
      {
      When I try and cast the delegate (ItemReader) to a MultiResourceItemReader I get the following exception:
      Code:
      java.lang.ClassCastException: $Proxy30 cannot be cast to org.springframework.batch.item.file.MultiResourceItemReader
      	at za.org.joburg.shared.batch.InvoiceFileItemReader.read(InvoiceFileItemReader.java:61)
      	at za.org.joburg.shared.batch.InvoiceFileItemReader.read(InvoiceFileItemReader.java:1)
      	at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:90)
      	at org.springframework.batch.core.step.item.SimpleChunkProvider.read(SimpleChunkProvider.java:127)
      	at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:106)
      	at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367)
      	at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214)
      	at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143)
      	at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:103)
      	at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:68)
      	at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:353)
      	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
      	at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:261)
      	at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:76)
      	at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367)
      	at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214)
      	at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143)
      	at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:247)
      	at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:196)
      	at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135)
      	at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61)
      	at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
      	at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
      	at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
      	at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
      	at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281)
      	at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
      	at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
      	at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:114)
      	at za.org.joburg.shared.web.controller.JobLauncherController.launch(JobLauncherController.java:34)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      	at java.lang.reflect.Method.invoke(Unknown Source)
      	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
      	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)
      	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
      	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
      	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
      	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
      	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
      	at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
      	at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
      	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
      	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
      	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
      	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
      	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
      	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
      	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
      	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
      	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
      	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
      	at java.lang.Thread.run(Unknown Source)
      I understand what the problem is but I don't know how to fix it. Please advise on what I need to do or change to get the filename.

      Thanks so much,

      Comment


      • #4
        Two things:
        1. Why is the delegate a proxy in this case? Are you doing any type of AOP that isn't in the configuration provided?
        2. If you are willing to use the current snapshot for Spring Batch, we actually have a new feature than handles what you are attempting to do for you. We have created a new interface called ResourceAware. If your item implements this interface, when being read in from a MultiResourceItemReader, we will inject the resource the item came from automatically (no additional code required from you). We'd love any feedback on the new feature!

        Comment


        • #5
          Hi Martin,

          Sorry I am still new to the whole proxy aspect of things. As far as I know the configuration provided is the only configuration that is being used.

          Originally the InvoiceFileItemReader had it's delegate declared as a MultiResourceItemReader but that also led me to a ClassCastException because apparently I had to code to the interface ItemReader rather than the concrete class MultiResourceItemReader . My original post can be found here: http://forum.springsource.org/showth...695#post434695

          In terms of ResourceAware would I then implement both ItemReader and ResourceAware?

          Thanks so much again for your quick response.

          Comment


          • #6
            Using the new feature I described, you wouldn't need your InvoiceFileItemReader at all. Your SourceFile class would implement ResourceAware and you would just use the MultiResourceItemReader. We take care of the rest. You can see the new interface (ResourceAware) here: https://github.com/SpringSource/spri...urceAware.java

            Comment


            • #7
              Thanks, I will have to investigate and see how it works. The reason why I wrote a class that implements ItemReader is because I needed to process lines according to a specific token in the line.

              Comment


              • #8
                The FlatFileItemReader supports custom tokens including dynamic ones. Take a look at the DelimitedLineTokenzier. While a comma is the default delimiter, you can configure any character you want (you can use a String in the current snapshot version). You can also implement your own LineTokenizer to parse the given line however you need. I would shy away from creating an entire ItemReader just to parse a line though.

                Comment

                Working...
                X