自定义 LineMapper 在 Spring 批量处理多个文件时抛出异常

Custom LineMapper throwing exception in Spring Batch multiple files process

我正在尝试实现自定义线映射器,以下是我的代码。 当我 运行 此代码出现异常时(也添加了异常)
在我的资源文件中,每行的分隔符可能不同。有些行的分隔符是','或'|'我想在 CustomLineMapper class 中处理。

工作-阅读-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.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.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.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

谁能帮帮我?谢谢

试试这个:

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

您需要像设置 fieldSetMapper 一样在超级 class 中设置 lineTokenizer。在 DefaultLineMapperafterPropertiesSet 方法中,它正在检查它是否有 lineTokenizer,但它没有(不是超级 class 可以访问的) ).所以它抛出 IllegalArgumentException: 'The LineTokenizer must be set'.