如何在Spring Batch中从两个不同的文件夹中读取多个xml文件?

时间:2017-04-25 01:38:37

标签: java spring-batch spritebatch

我有多个文件可以从具有相同父路径的两个不同目录中读取和写入。 如果其中一个目录没有要读取的文件,是否可以在“org.springframework.batch.item.file。 MultiResourceItemReader ”中选择特定目录?

<!-- multi xml reader -->
    <bean id="multiResourceReader" class="org.springframework.batch.item.file.MultiResourceItemReader">
        <property name="resources" ref="vinFeedFileResouce" />
        <property name="delegate" ref="vinFeedReader" />
    </bean>

    <bean id="vinFeedFileResouce" class="org.springframework.core.io.FileSystemResource"    scope="step">
        <constructor-arg>
            <list>
                <ref bean="read_ONE" />
                <ref bean="read_TWO" />
            </list>
        </constructor-arg>
    </bean>

    <bean id="read_ONE" class="org.springframework.core.io.FileSystemResource"  scope="step">
        <constructor-arg value="#{path_ONE}"></constructor-arg>
    </bean>

    <bean id="read_TWO" class="org.springframework.core.io.FileSystemResource"  scope="step">
        <constructor-arg value="#{path_TWO}"></constructor-arg>
    </bean>

我为读者收到以下错误:

[pool-1-thread-1](batch.listener.ModelMasterFailureListener:13)-Encountered error on Model master read
org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:137)
    at org.springframework.batch.item.file.MultiResourceItemReader.read(MultiResourceItemReader.java:105)
    at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:90)
    at org.springframework.batch.core.step.item.FaultTolerantChunkProvider.read(FaultTolerantChunkProvider.java:87)
    at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:108)
    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:386)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
    at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:264)
    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:250)
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
    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 com.ahm.ngt.cbo.feed.batch.scheduler.RunScheduler.run(RunScheduler.java:80)
    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:597)
    at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273)
    at org.springframework.scheduling.support.MethodInvokingRunnable.run(MethodInvokingRunnable.java:65)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:51)
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'scopedTarget.vinFeedFileResouce' defined in class path resource [spring/batch/jobs/ca-vin-feed-config.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.io.File]: Could not convert constructor argument value of type [java.util.ArrayList] to required type [java.io.File]: Failed to convert value of type 'java.util.ArrayList' to required type 'java.io.File'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.util.ArrayList] to required type [java.io.File]: PropertyEditor [org.springframework.beans.propertyeditors.FileEditor] returned inappropriate value
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:702)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:196)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1003)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:907)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:329)
    at org.springframework.batch.core.scope.StepScope.get(StepScope.java:150)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:325)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:33)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:184)
    at com.sun.proxy.$Proxy1.exists(Unknown Source)
    at org.springframework.batch.item.xml.StaxEventItemReader.doOpen(StaxEventItemReader.java:187)
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:134)
    ... 45 more

2 个答案:

答案 0 :(得分:0)

如果您看到FileSystemResource的源代码,您会发现构造函数可以采用文件或字符串而不是文件列表或字符串。您可以编写自定义资源阅读器来读取多个目录中的文件。这是一个例子

    <bean id="multiResourceReader" class="org.springframework.batch.item.file.MultiResourceItemReader">
        <property name="resources" value="#{myResourceReader.read()}" />
        <property name="delegate" ref="vinFeedReader" />
    </bean>

    <bean id="myResourceReader" class="com.kp.swasthik.MyResourceReader">
        <property name="resource" value="file:///path1/*.txt, file:///path2/*.txt"></property>
    </bean>

ResourceReader类。

public class MyResourceReader {

    private String resource;

    public String getResource() {
        return resource;
    }

    public void setResource(String resource) {
        this.resource = resource;
    }

    public Resource[] read(){

        List<Resource> resources = new ArrayList<>();
        if(resource == null || resource.isEmpty()){
            return new Resource[]{};
        }
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Arrays.stream(resource.split(",")).forEach(v->{
            try {
                Collections.addAll(resources, resolver.getResources(v));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        });
        return resources.toArray(new Resource[0]);
    }

}

答案 1 :(得分:0)

切换到基于注释的配置。在那里,您可以将所有资源(来自不同的目录)添加到读者:

@Bean
public ItemReader<?> reader() {
   Resource[] res = ... //get eg using PathMatchingResourcePatternResolver multiple times on different dirs

   MultiResourceItemReader<?> r = new MultiResourceItemReader<>();
   r.setResources(res);
   return r;
}