Help with MultiResourceItemReader - file archiving and logging
Hi,
In our application, text files within a folder are read using MultiResourceItemReader, and data is updated in a database.
everything is working fine for me but I am unable to achieve two things
1) Log the actual file name before and after it is processed
2) after the file is read, move it to an archive folder.
Below is my job configuration
Code:
<job id="samplejob" xmlns="http://www.springframework.org/schema/batch">
<step id="processStep">
<tasklet>
<chunk reader="multiResourceReader" writer="customItemWriter"
processor="validatingItemProcessor" commit-interval="1" skip-limit="4">
<skippable-exception-classes>
<include
class="org.springframework.batch.item.file.FlatFileParseException" />
</skippable-exception-classes>
<streams>
<stream ref="errorItemWriter" />
</streams>
</chunk>
</tasklet>
</step>
</job>
<bean id="multiResourceReader"
class="org.springframework.batch.item.file.FlatFileParseException"
scope="step">
<property name="resources" value="#{jobParameters[fileInputPath]}" />
<property name="delegate" ref="flatFileItemReader" />
</bean>
<!--
flatFileItemReader is a simple reader reading delimited text and we
have a custom writer to update multiple tables.
-->
With ItemReadListener, I get items within the files but not the path of the file read by the MRIR. I have tried different listener configurations but unable to get access to the file being processed to achieve my objectives. I know I have to write a tasklet to achieve the file archiving but unable to do so.
Any hints in this regard would be of great help to me.
And i should admit, spring batch is cool...:)
Thanks in advance
Log file name in case of multiple file processing.
Hi Dave,
As you said, in StepExecutionListener, if i call update() on the MultiResourceItemReader, i can get the current resource. I'm trying to configure this, but it throws $proxy10 exception.
Here is the configuration which i used.
ApplicationContextProvider is a Bean which implements ApplicationContextAware to get the MultiResourceItemReader
Code:
<bean id="applicationContextProvider" class="org.springframework.sample.batch.example.ApplicationContextProvider"/>
<bean id="stepListener" class="org.springframework.sample.batch.example.ExampleStepExecutionListener">
<property name="applicationContextProvider" ref="applicationContextProvider"/>
</bean>
And here what i do in the after method of stepExecutionListener.
Code:
public ExitStatus afterStep(StepExecution stepExecution) {
ApplicationContext applicationContext = this.applicationContextProvider.getApplicationContext();
log.info("object type is : " + applicationContext.getType("reader").getName());
MultiResourceItemReader multiResourceItemReader = (MultiResourceItemReader) applicationContext.getBean("reader");
ExecutionContext executionContext = stepExecution.getExecutionContext();
multiResourceItemReader.update(executionContext);
log.info("current file name (after): " + multiResourceItemReader.getCurrentResource().getFilename());
return ExitStatus.COMPLETED;
}
Here is the full Exception stack trace..
Code:
java.lang.IllegalArgumentException: Unable to invoke method: [public org.springframework.batch.core.ExitStatus org.springframework.sample.batch.example.ExampleStepExecutionListener.afterStep(org.springframework.batch.core.StepExecution)] on object: [org.springframework.sample.batch.example.ExampleStepExecutionListener@48bc64] with arguments: [[StepExecution: id=1, version=22, name=step1, status=COMPLETED, exitStatus=COMPLETED, readCount=20, filterCount=0, writeCount=20 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=21, rollbackCount=0, exitDescription=]]
at org.springframework.batch.support.SimpleMethodInvoker.invokeMethod(SimpleMethodInvoker.java:108)
at org.springframework.batch.core.listener.MethodInvokerMethodInterceptor.invoke(MethodInvokerMethodInterceptor.java:68)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy11.afterStep(Unknown Source)
at org.springframework.batch.core.listener.CompositeStepExecutionListener.afterStep(CompositeStepExecutionListener.java:62)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:223)
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 org.springframework.sample.batch.example.ExampleJobConfigurationTests.testLaunchJob(ExampleJobConfigurationTests.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.batch.support.SimpleMethodInvoker.invokeMethod(SimpleMethodInvoker.java:105)
... 45 more
Caused by: java.lang.ClassCastException: $Proxy10
at org.springframework.sample.batch.example.ExampleStepExecutionListener.afterStep(ExampleStepExecutionListener.java:50)
... 50 more
It clearly says ClassCastException, i think MultiResourceItemReader is now a proxy bean, so how exactly i can get this bean to call update method.
Is there any alternative to know what is the current file that is being processed in case of multiple file processing.
Thanks in advance.