动态提供输入、输出路径时出错

Getting error while dynamically providing input,output path

我已经创建了一个多文件reader和平面文件写入器(后来,我必须将它扩展为多文件读取到多文件写入,一对一映射)。当我通过 属性 文件提供输入路径时,一切正常,但是当我尝试通过 jobExecutionContext 提供路径时,它开始给我错误。令我惊讶的是,作者成功地从 executionContext 获取路径并写入我提供的任何位置,但不是 reader.

PS:我使用"SingleItemPeekableItemReader"是因为我在文件中的数据是多行记录,无法确定一条记录何时结束。知道记录 2 已经开始的唯一方法是当您可以访问下一行并且您知道它是新记录的开始时。

谁能通过一些光,我做错了什么。

<bean id="itemReader" class="com.varun.reader.AccountDataReader">
    <property name="fieldSetReader"         ref="PeekableitemReader" />
    <property name="headerFieldSetMapper"   ref="headerFieldSetMapper" />
    <property name="multiReader"            ref="multiResourceReader"/>
</bean>

<bean id="PeekableitemReader" class="org.springframework.batch.item.support.SingleItemPeekableItemReader" >
    <property name="delegate" ref="multiResourceReader"/>
</bean>

<bean id="multiResourceReader"  class=" org.springframework.batch.item.file.MultiResourceItemReader" >
    <property name="resources" value="file:${file.input.dir}*.DAT" />
    <property name="delegate" ref="fileItemReader" />
</bean>

<bean id="fileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader">
    <property name="lineMapper">
        <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
            <property name="lineTokenizer" ref="accountDataTokenizer"/>
            <property name="fieldSetMapper">
                <bean class="org.springframework.batch.item.file.mapping.PassThroughFieldSetMapper" />
            </property>
        </bean>
    </property>
    <property name="comments" value=""></property>
</bean>

它出错了,当我在 multiresourceReader 中提供如下资源时

<property name="resources" value="file:#{JobExecutionContext[input_dir]}*.DAT" />

错误日志如下:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'step1': Cannot resolve reference to bean 'itemReader' while setting bean property 'itemReader'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'itemReader' defined in class path resource [spring/config/process-config.xml]: Cannot resolve reference to bean 'PeekableitemReader' while setting bean property 'fieldSetReader'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'PeekableitemReader' defined in class path resource [spring/config/process-config.xml]: Cannot resolve reference to bean 'multiResourceReader' while setting bean property 'delegate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'multiResourceReader' defined in class path resource [spring/config/process-config.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'JobExecutionContext' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1481)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:753)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)

在将 multireader 作用域作为步骤后,我得到了错误,因为 below.I 也尝试将作用域放在所有其他委托 reader 上,但我得到了相同的结果错误。

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'step1': Cannot resolve reference to bean 'itemReader' while setting bean property 'itemReader'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'itemReader' defined in class path resource [spring/config/process-config.xml]: Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type [com.sun.proxy.$Proxy11 implementing org.springframework.batch.item.ItemStreamReader,org.springframework.batch.item.ItemStream,org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.batch.item.file.MultiResourceItemReader] for property 'multiReader'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [com.sun.proxy.$Proxy11 implementing org.springframework.batch.item.ItemStreamReader,org.springframework.batch.item.ItemStream,org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.batch.item.file.MultiResourceItemReader] for property 'multiReader': no matching editors or conversion strategy found
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1481)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:753)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.varun.JobScheduler.main(JobScheduler.java:9)

我的习惯Reader

public class AccountDataReader implements ItemReader<AccountDataBO> {
private static Log log = LogFactory.getLog(AccountDataReader.class);
private boolean recordFinished;

private AccountDataBO acctObj = new AccountDataBO();

private SingleItemPeekableItemReader<FieldSet> fieldSetReader;
private HeaderFieldSetMapper headerFieldSetMapper;
private MultiResourceItemReader<FieldSet> multiReader;

@Override
public AccountDataBO read() throws Exception {
    recordFinished = false;

    while (!recordFinished) {
        process(fieldSetReader.read());
    }
    AccountDataBO result = acctObj;
    acctObj = new AccountDataBO();

    return result;
}

private void process(FieldSet fieldSet) throws Exception {

    if (fieldSet == null) {
        log.debug("FINISHED Reading");
        recordFinished = true;
        acctObj=null;
        return;
    }

    String lineId = fieldSet.readString(0);

    if (!StringUtils.isEmpty(lineId) && lineId.contains(AccountDataBO.ACCOUNT)) {
        log.debug("Starting new Record");
        acctObj.setHeader(headerFieldSetMapper.mapFieldSet(fieldSet));
        acctObj.setResource(multiReader.getCurrentResource());

    }

    //Code

}

private void CheckEOFNewAccount() throws Exception {
    if ((fieldSetReader.peek() != null
            && ((fieldSetReader.peek().getValues())[0].contains(AccountDataBO.ACCOUNT)))
            || fieldSetReader.peek() == null) {
        log.debug("Next Line is Account or EOF Hence returning for current Account");
        recordFinished = true;
        return;
    }
}

public void setFieldSetReader(SingleItemPeekableItemReader<FieldSet> fieldSetReader) {
    this.fieldSetReader = fieldSetReader;
}

public void setHeaderFieldSetMapper(HeaderFieldSetMapper headerFieldSetMapper) {
    this.headerFieldSetMapper = headerFieldSetMapper;
}

public void setMultiReader(MultiResourceItemReader<FieldSet> multiReader) {
    this.multiReader = multiReader;
}

}

为了将作业参数注入批处理组件,该组件需要在步骤范围内。所以在你的例子中,改变这个:

<bean id="multiResourceReader"  
      class=" org.springframework.batch.item.file.MultiResourceItemReader" >

为此:

<bean id="multiResourceReader"  
      class=" org.springframework.batch.item.file.MultiResourceItemReader" 
      scope="step" >