我目前有一個應用程序,我試圖診斷什麼在我做了不正確的設置,並沒有任何運氣,以確定爲什麼它不工作以外的非常具體情況。當從自定義項目讀取器訪問FlatFileItemReader
首先我正在使用的代碼。
Configuration.java
@EnableBatchProcessing
@SpringBootApplication(scanBasePackages="com.lcbo")
@EnableIntegration
public class COnfig {
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Autowired
private LCBOInventoryTrackerProperties inventoryTrackerProperties;
@Bean
public Job processLCBOInventory(@Qualifier("getLCBOStoreDataStep") final Step getLCBOStoreDataStep) {
return jobBuilderFactory
.get("processLCBOInventory")
.incrementer(new RunIdIncrementer())
.start(getLCBOStoreDataStep)
.build();
}
/**
* This tasklet downloads the .zip file, unzips, and saves it in the appropriate folder under resources.
* Execute at 6am daily
*
// * @param AcquireDataFileTasklet acquireDataFiles
* @return Step - returns Step status; either SUCCESS or FAILURE
*/
@Bean
public Step getCurrentLCBODataStep(final AcquireDataFileTasklet acquireDataFiles,
final ExecutionContextPromotionListener listener) {
return stepBuilderFactory
.get("getCurrentLCBODataStep")
.tasklet(acquireDataFiles)
.allowStartIfComplete(true)
.listener(listener)
.build();
}
@Bean
public Step getLCBOStoreDataStep(final LCBOStoreReader lcboStoreReader,
final LCBOStoreWriter lcboStoreWriter) {
return stepBuilderFactory
.get("getLCBOStoreDataStep")
.<LCBOStore, LCBOStore>chunk(inventoryTrackerProperties.getDefaults().getChunkSize())
.reader(lcboStoreReader)
.writer(lcboStoreWriter)
.build();
}
}
讀者類
@Component
public class LCBOStoreReader extends AbstractLCBOReader implements ItemReader, InterstepDataRetriever {
private static final Logger log = LoggerFactory.getLogger(LCBOStoreReader.class);
@Override
public ItemReader<LCBOStore> read() throws UnexpectedInputException, ParseException, NonTransientResourceException {
Class<LCBOStore> classType = LCBOStore.class;
return createCSVReader(classType, currentCSVFilePath, inventoryTrackerProperties.getLCBOFilPropertiess().getStores());
}
/*
@Override
public void beforeStep(final StepExecution stepExecution) {
JobExecution jobExecution = stepExecution.getJobExecution();
ExecutionContext jobContext = jobExecution.getExecutionContext();
this.currentWorkingDate = (String) jobContext.get("currentWorkingDateKey");
}
*/
@Override
public void retrieveInterstepDataFromJobContext(final ExecutionContext jobContext) {
this.currentCSVFilePath = (String) jobContext.get("currentCSVFilePathKey");
}
}
和其延伸(因爲FlatFileItemReader設置用於通過多個閱讀器)的類
public abstract class AbstractLCBOReader {
@Autowired
protected LCBOInventoryTrackerProperties inventoryTrackerProperties;
protected String currentCSVFilePathKey;
protected String currentCSVFilePath;
private static final Logger log = LoggerFactory.getLogger(AbstractLCBOReader.class);
protected <T> ItemReader<T> createCSVReader(final Class<T> classType,
final String currentCSVFilePath,
final LCBOFileDetailsProperties properties) {
FlatFileItemReader<T> reader = new FlatFileItemReader<>();
// Skip a line to ignore the header information in these files
reader.setLinesToSkip(properties.getNumberOfLinesToSkipInFile());
reader.setResource(new FileSystemResource(currentCSVFilePath + File.separator + properties.getFileName()));
reader.setLineMapper(createLineMapper(classType, properties));
reader.setRecordSeparatorPolicy(new DefaultRecordSeparatorPolicy());
reader.setEncoding("utf8");
return reader;
}
private <T> LineMapper<T> createLineMapper(final Class<T> classType, final LCBOFileProperties.LCBOFileDetailsProperties properties) {
DefaultLineMapper<T> lineMapper = new DefaultLineMapper<>();
lineMapper.setLineTokenizer(createLineTokenizer(properties));
lineMapper.setFieldSetMapper(createFieldSetMapper(classType));
return lineMapper;
}
private <T> FieldSetMapper<T> createFieldSetMapper(final Class<T> classType) {
BeanWrapperFieldSetMapper<T> fieldSetMapper = new BeanWrapperFieldSetMapper<>();
fieldSetMapper.setTargetType(classType);
return fieldSetMapper;
}
private LineTokenizer createLineTokenizer(final LCBOFileProperties.LCBOFileDetailsProperties properties) {
LCBOFileProperties.Column[] columns = properties.getColumns();
int[] columnIndexes = new int[columns.length];
String[] columnNames = new String[columns.length];
// populating the columnIndexes
for (int i = 0; i < columns.length; i++) {
columnIndexes[i] = columns[i].getColumnIndex();
columnNames[i] = columns[i].getColumnName();
}
DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
lineTokenizer.setIncludedFields(columnIndexes);
lineTokenizer.setNames(columnNames);
lineTokenizer.setDelimiter(",");
lineTokenizer.setQuoteCharacter('"');
return lineTokenizer;
}
}
的執行此操作時會出現錯誤該對象不能從FlatFileItemreader強制轉換爲作爲createCSVReader中第一個參數傳遞的對象。這是一個例子。
public class LCBOStore {
private Long id;
private String addressLineOne;
private String addressLineTwo;
private String city;
private String postalCode;
private String latitude;
private String longitude;
private String updatedAt; //Convert to Date
public LCBOStore(final Long id, final String addressLineOne, final String addressLineTwo, final String city,
final String postalCode, final String latitude, final String longitude, final String updatedAt) {
this.id = id;
this.addressLineOne = addressLineOne;
this.addressLineTwo = addressLineTwo;
this.city = city;
this.postalCode = postalCode;
this.latitude = latitude;
this.longitude = longitude;
this.updatedAt = updatedAt;
}
public Long getId() {
return id;
}
public String getAddressLineOne() {
return addressLineOne;
}
public String getAddressLineTwo() {
return addressLineTwo;
}
public String getCity() {
return city;
}
public String getPostalCode() {
return postalCode;
}
public String getLatitude() {
return latitude;
}
public String getLongitude() {
return longitude;
}
public String getUpdatedAt() {
return updatedAt;
}
public void setId(final Long id) {
this.id = id;
}
public void setAddressLineOne(final String addressLineOne) {
this.addressLineOne = addressLineOne;
}
public void setAddressLineTwo(final String addressLineTwo) {
this.addressLineTwo = addressLineTwo;
}
public void setCity(final String city) {
this.city = city;
}
public void setPostalCode(final String postalCode) {
this.postalCode = postalCode;
}
public void setLatitude(final String latitude) {
this.latitude = latitude;
}
public void setLongitude(final String longitude) {
this.longitude = longitude;
}
public void setUpdatedAt(final String updatedAt) {
this.updatedAt = updatedAt;
}
@Override
public String toString() {
return "StoreDBModel [id=" + id + ", addressLineOne=" + addressLineOne + ", city=" + city
+ ", postalCode=" + postalCode + ", latitude=" + latitude + ", longitude="
+ longitude + ", updatedAt=" + updatedAt + "]";
}
}
現在,如果我動議存在createCSVReader到定製的閱讀器類的構造函數的FlatFileItemReader模式,還是有它,所以它的配置文件中,它工作正常。然而,我無法弄清楚如何在這些配置中使用作業和步驟上下文(構造函數在您可以訪問步驟和jobContext之前執行,它似乎來自於我的測試,並且在放入Config類時我永遠不會知道如何訪問)。此外,至少對於我來說,讓它自己的文件中的Reader代碼不會塞入構造函數中看起來更乾淨。
所以簡而言之,有沒有一種方法可以解決這個問題,讓它在自己的閱讀器類中工作?我是否做得不正確,並使用不好的做法?也許是兩者的混合?如果有什麼遺漏,請詢問,我會嘗試澄清。
您的閱讀器返回'ItemReader',因爲它應該在委託項讀取器上調用read方法並返回'YourObject'。讀取方法的全部目的是返回實際的對象而不是潛在的項目讀取器。 –
'LCBOStoreReader.read()'可能會返回'LCBOStore',而不是'ItemReader' ... – OhadR
知道這將是簡單的事情,閱讀功能正在按預期工作,只爲根csvParser類,沒有一個自動方式來讀取。無論哪種方式,感謝您的支持,它幫助我找到了解決方案。 – canadiancreed