自定义LineMapper在Spring Batch多文件进程中抛出异常

时间:2016-02-16 09:15:02

标签: java spring spring-boot spring-batch

我正在尝试实现自定义Line Mapper,以下是我的代码。 当我运行此代码时,会引发异常(异常也会添加) 在我的资源文件中,每行的分隔符可能不同。分界符的某些行是','或者' |'我想在CustomLineMapper类中处理。

job-read-files.xml

<bean id="domain" class="com.di.pos.Domain" />
<job id="readMultiFileJob" xmlns="http://www.springframework.org/schema/batch">
    <step id="step1">
        <tasklet>
            <chunk reader="multiResourceReader" writer="flatFileItemWriter"
                commit-interval="1" />
            <!-- <listeners> <listener ref="customItemReaderListener" /> </listeners> -->
        </tasklet>
    </step>
</job>

<bean id="multiResourceReader" class="org.springframework.batch.item.file.MultiResourceItemReader">
    <property name="resources" value="file:csv/inputs/domain-*.csv" />
    <property name="delegate" ref="flatFileItemReader" />
</bean>

<bean id="flatFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader">
    <property name="lineMapper">
    <!--    <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">-->
            <bean class="com.di.pos.CustomLineMapper">

            <property name="lineTokenizer">
                <bean
                    class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                    <property name="names" value="id, domain" />
                </bean>
            </property>
            <property name="fieldSetMapper">
                <bean
                    class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
                    <property name="prototypeBeanName" value="domain" />
                </bean>
            </property>
        </bean>
    </property>
</bean>

和 的 CustomLineMapper.java 在这里,我已经覆盖了一些方法。

public class CustomLineMapper<T> extends DefaultLineMapper<T> {
public LineTokenizer lineTokenizer;
public FieldSetMapper<Domain> fieldSetMapper;

@Override
public T mapLine(String line, int lineNumber) throws Exception {
    System.out.println("======" + line);

    DelimitedLineTokenizer delimitedLineTokenizer = new DelimitedLineTokenizer();

    if (line.indexOf("|") == -1) {
        if (line.indexOf(",") == -1) {
        } else {
            delimitedLineTokenizer.setDelimiter(",");
        }
    } else {
        delimitedLineTokenizer.setDelimiter("|");
    }
    setLineTokenizer(delimitedLineTokenizer);
    return (T) this.fieldSetMapper.mapFieldSet(this.lineTokenizer.tokenize(line));
}

public LineTokenizer getLineTokenizer() {
    return lineTokenizer;
}

public void setLineTokenizer(LineTokenizer lineTokenizer) {
    this.lineTokenizer = lineTokenizer;
}

public FieldSetMapper<Domain> getFieldSetMapper() {
    return fieldSetMapper;
}

@Override
public void setFieldSetMapper(FieldSetMapper<T> fieldSetMapper) {
    super.setFieldSetMapper(fieldSetMapper);
}

}

当我执行此代码时,我收到以下异常。

    Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'step1': Cannot resolve reference to bean 'multiResourceReader' while setting bean property 'itemReader'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'multiResourceReader' defined in class path resource [spring/batch/jobs/job-read-files.xml]: Cannot resolve reference to bean 'flatFileItemReader' while setting bean property 'delegate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flatFileItemReader' defined in class path resource [spring/batch/jobs/job-read-files.xml]: Cannot create inner bean 'com.di.pos.CustomLineMapper#3c50507' of type [com.di.pos.CustomLineMapper] while setting bean property 'lineMapper'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.di.pos.CustomLineMapper#3c50507' defined in class path resource [spring/batch/jobs/job-read-files.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: The LineTokenizer must be set
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1393)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1134)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:608)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
    at com.di.pos.App.run(App.java:23)
    at com.di.pos.App.main(App.java:15)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'multiResourceReader' defined in class path resource [spring/batch/jobs/job-read-files.xml]: Cannot resolve reference to bean 'flatFileItemReader' while setting bean property 'delegate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flatFileItemReader' defined in class path resource [spring/batch/jobs/job-read-files.xml]: Cannot create inner bean 'com.di.pos.CustomLineMapper#3c50507' of type [com.di.pos.CustomLineMapper] while setting bean property 'lineMapper'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.di.pos.CustomLineMapper#3c50507' defined in class path resource [spring/batch/jobs/job-read-files.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: The LineTokenizer must be set
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1393)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1134)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:323)
    ... 16 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flatFileItemReader' defined in class path resource [spring/batch/jobs/job-read-files.xml]: Cannot create inner bean 'com.di.pos.CustomLineMapper#3c50507' of type [com.di.pos.CustomLineMapper] while setting bean property 'lineMapper'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.di.pos.CustomLineMapper#3c50507' defined in class path resource [spring/batch/jobs/job-read-files.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: The LineTokenizer must be set
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:282)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:121)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1393)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1134)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:323)
    ... 26 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.di.pos.CustomLineMapper#3c50507' defined in class path resource [spring/batch/jobs/job-read-files.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: The LineTokenizer must be set
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1488)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:271)
    ... 36 more
Caused by: java.lang.IllegalArgumentException: The LineTokenizer must be set
    at org.springframework.util.Assert.notNull(Assert.java:112)
    at org.springframework.batch.item.file.mapping.DefaultLineMapper.afterPropertiesSet(DefaultLineMapper.java:56)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1547)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1485)
    ... 39 more

任何人都可以帮助我吗?感谢。

1 个答案:

答案 0 :(得分:1)

试试这个:

@Override
public void setLineTokenizer(LineTokenizer lineTokenizer) {
    super.setLineTokenizer(lineTokenizer);
    this.lineTokenizer = lineTokenizer;
}

您需要在超类中设置lineTokenizer,就像fieldSetMapper一样。在afterPropertiesSet的{​​{1}}方法中,它检查它是否有DefaultLineMapper,但它没有一个(不是超类可访问的那个)。所以它会抛出lineTokenizer:'必须设置LineTokenizer'。