Я реализую базовое c пакетное приложение с использованием Spring Boot и Spring Batch.
Для каждого файла, найденного во входном каталоге, создается один шаг благодаря MultiResourcePartitioner
<bean id="partitioner"
class="org.springframework.batch.core.partition.support.MultiResourcePartitioner">
<description>
Create a step for each files found in the input directory
</description>
<property name="resources" value="#{resourceProvider.read()}"/>
</bean>
Каждый шаг состоит из ItemReader, ItemProcessor и ItemWriter. Моя проблема связана с ItemReader, и фактически каждый бин использует List / Map как свойство в конфигурации xml.
Мой ItemReader выглядит следующим образом:
<bean id="itemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<description>
* resource is set via step scoped late binding (see multiresourcereader)
* strict mode - we expect input files
</description>
<property name="resource" value="#{stepExecutionContext['fileName']}"/>
<property name="strict" value="true"/>
<property name="lineMapper" ref="lineMapper"/>
</bean>
<bean id="lineMapper" class="input.CustomPatternMatchingLineMapper">
<property name="fieldSetMappers">
<map>
<entry key="001*" value-ref="payloadFieldSetMapper"/>
<entry key="000*" value-ref="headerFieldSetMapper"/>
<entry key="999*" value-ref="footerFieldSetMapper"/>
</map>
</property>
<property name="tokenizers">
<map>
<entry key="001*" value-ref="payloadTokenizer"/>
<entry key="000*" value-ref="headerTokenizer"/>
<entry key="999*" value-ref="footerTokenizer"/>
</map>
</property>
</bean>
<bean id="headerTokenizer" class="input.tokenizer.HeaderTokenizer"/>
<bean id="payloadTokenizer" class="input.tokenizer.PayloadTokenizer"/>
<bean id="footerTokenizer" class="input.tokenizer.FooterTokenizer"/>
<bean id="headerFieldSetMapper" class="input.fieldsetmapper.HeaderFieldSetMapper"/>
<bean id="payloadFieldSetMapper" class="input.fieldsetmapper.PayloadFieldSetMapper"/>
<bean id="footerFieldSetMapper" class="input.fieldsetmapper.FooterFieldSetMapper"/>
вот что я получаю в журнале при создании экземпляра бина
2020-04-21 10:22:32.491 DEBUG 6808 --- [ main] o.s.beans.TypeConverterDelegate : Original ConversionService attempt failed - ignored since PropertyEditor based conversion eventually succeeded
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.util.LinkedHashMap<?, ?>] to type [@org.springframework.lang.Nullable java.util.Map<java.lang.Class<?>, java.lang.Class<java.beans.PropertyEditor>>] for value '{org.springframework.batch.item.file.transform.Range[]=org.springframework.batch.item.file.transform.RangeArrayPropertyEditor}'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [@org.springframework.lang.Nullable java.lang.Class<?>]
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:191) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:129) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:585) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.AbstractNestablePropertyAccessor.convertForProperty(AbstractNestablePropertyAccessor.java:604) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:219) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1748) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1704) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1444) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:171) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:706) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:532) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at Lanceur.main(Lanceur.java:40) ~[classes/:na]
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [@org.springframework.lang.Nullable java.lang.Class<?>]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.core.convert.support.MapToMapConverter.convertKey(MapToMapConverter.java:122) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.core.convert.support.MapToMapConverter.convert(MapToMapConverter.java:84) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
... 23 common frames omitted
А вот где процесс висит бесконечно:
2020-04-21 10:22:36.261 DEBUG 6808 --- [cTaskExecutor-4] o.s.batch.core.scope.StepScope : Creating object in scope=step, name=scopedTarget.itemReader
Для вашей информации, если я использую другой LineMapper, я не сталкиваюсь с этой проблемой.
Другая информация, поскольку я использую Spring Boot, мне пришлось переопределить определение StepScope, чтобы использовать свойство scope="step"
<bean id="stepScope" class="org.springframework.batch.core.scope.StepScope">
<property name="autoProxy" value="true"/>
</bean>
spring.main.allow-bean-definition-overriding=true
EDIT
Вот пример строки, которую я должен отобразить, связанный с ней POJO и интерфейс, который он реализует:
001234577589NNNNNN FFF M
@Data
public class Payload implements Element {
private String debLine;
private String id;
private String name;
private String firstName;
private String gender;
private int numLine;
}
public interface Element {
String getDebLine();
int getNumLine();
void setNumLine(int numLine);
}