我在我的项目中要求处理固定长度文件中的数据。数据文件包含一个标题行和许多详细信息行。标题行包含摘要&合并详细信息行的信息。例如报告期,报告雇主,总金额等。详细信息行包含每个员工的信息。例如员工贡献,贡献期等。从不同的雇主那里收到很多需要由工作处理的数据文件。Spring批处理问题
所以我创建了一个步骤的作业,下面的读者&作家和其他自定义类 a。 MultiResourceItemReade读取文件夹中的所有文件。 b。 FlatFileItemReader读取每个文件。从MultiResourceItemReader委托。 c。我正在跳过第一行,并处理LineCallbackHandler d。我能够解析标题行并将其转换为Report对象。 e。我使用DefaultLineMapper和BeanWrapperFieldSetMapper来解析细节行并将其转换为MemberRecrod对象。
我需要帮助实现以下使用spring批处理。
- 我想要一个Report对象在ItemWriter中可用于文件夹中处理的每个文件。所以我可以将所有MemberRecord对象[细节行]添加到Report对象并将其保存到数据库[我正在使用Hibernate for ORM]。我试图通过将Report对象添加到JobExecutionContext并在ItemWriter中访问它。所以我从MemberRecordHeaderLineHandler类[这实现了LineCallbackHandler]扩展了StepExecutionListenerSupport。并覆盖beforeStep方法。我能够在jobStep方法上获得JobExection对象,并且将JobExection对象存储到MemberRecordHeaderLineHandler类中的局部变量中。但是当控件进入handleLine方法时,JobExection变量为null。我解析标题行并将其转换为handleLine方法中的Report对象。由于JobExection为空,我无法将Rerpot对象添加到JobExecutionContext对象。我不知道如何将Report对象传递给ItemWriter。请教我如何从LineCallBackHandler到ItemWriter的值。
我还需要关于如何使用Spring Batch实现以下功能的建议。
- 目前我正在将我的示例数据文件放在webinf/conf/data文件夹下的文件夹中。理想情况下,我想处理来自FTP位置的所有文件。如何指定资源属性的FTP文件夹位置。
- 成功处理每个文件后,我需要将文件归档到不同的文件夹。如何使用Spring Batch存档文件。
- 如果由于数据格式错误而导致有任何异常,我需要更新数据库中的记录并将错误的文件移动到错误文件夹中。由于这个错误,我不希望工作停止。我想继续处理其他文件。在这种情况下如何处理异常。
作业xml文件。
<bean id="erLoadFolderReader" class="org.springframework.batch.item.file.MultiResourceItemReader" scope="step">
<property name="resources" value="#{jobParameters['FILE_NAME']}" />
<property name="delegate" ref="erLoadFileReader" />
<property name="saveState" value="false" />
</bean>
<bean id ="memberRecordHeaderLineHandler" class="com.htcinc.rs.batch.infrastructure.erLoadJob.MemberRecordHeaderLineHandler" />
<bean id="erLoadFileReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<property name="saveState" value="false" />
<property name="resource" value="#{jobParameters['FILE_NAME']}" />
<property name="linesToSkip" value="1" />
<property name="skippedLinesCallback">
<bean class="com.htcinc.rs.batch.infrastructure.erLoadJob.MemberRecordHeaderLineHandler">
<property name="wcReportService" ref="wcReportService" />
<property name="names" value="empNo,planCode,startDate,endDate,totalEmprContrb,totalEmplContrb,reportType" />
<property name="headerTokenizer">
<bean class="org.springframework.batch.item.file.transform.FixedLengthTokenizer">
<property name="names" value="organizationCode,planCode,beginDate,endDate,totalEmployerContribution,totaEmployeeContribution,reportingType"></property>
<property name="columns" value="1-9,10-17,18-25,26-33,34-48,49-63,64-67" />
</bean>
</property>
</bean>
</property>
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean class="org.springframework.batch.item.file.transform.FixedLengthTokenizer">
<property name="names" value="ssn,firstName,lastName,middleName,birthDateText,genderCode,addressStartDateText,addrLine1,addrLine2,addrLine3,city,state,zip,zipPlus,wagesText,employerContributionText,employeeContributionText,recordType,startDateText,endDateText,serviceCreditDaysText,serviceCreditHoursText,jobClassCode,positionChangeDateText,hireDateText,terminationDateText,notes" />
<property name="columns" value="1-9,10-29,30-59,60-79,80-87,88-88,89-96,97-126,127-146,147-166,167-181,182-183,184-188,189-192,193-205,206-214,215-223,224-227,228-235,236-243,244-246,247-251,252-255,256-263,264-271,272-279,280-479" />
</bean>
</property>
<property name="fieldSetMapper">
<bean
class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<property name="targetType"
value="com.htcinc.rs.domain.batch.MemberRecord" />
</bean>
</property>
</bean>
</property>
</bean>
<bean id="memberRecordItemWriter" class="com.htcinc.rs.batch.infrastructure.erLoadJob.MemberRecordItemWriter" />
<bean id="memberRecordItemProcessor" class="com.htcinc.rs.batch.infrastructure.erLoadJob.MemberRecordItemProcessor" />
<batch:job id="erLoadJob">
<batch:step id="erLoadJob_step1">
<batch:tasklet>
<batch:chunk reader="erLoadFolderReader" writer="memberRecordItemWriter" processor="memberRecordItemProcessor" commit-interval="1" />
</batch:tasklet>
<batch:listeners>
<batch:listener ref="memberRecordHeaderLineHandler"/>
</batch:listeners>
</batch:step>
</batch:job>
</beans>
MemberRecordHeaderLineHandler。Java的文件
private WCReportServiceDefaultImpl wcReportService;
private WCReport wcReport;
private JobExecution jobExecution;
private LineTokenizer headerTokenizer;
private String names;
public WCReportServiceDefaultImpl getWcReportService() {
return wcReportService;
}
public void setWcReportService(WCReportServiceDefaultImpl wcReportService) {
this.wcReportService = wcReportService;
}
public LineTokenizer getHeaderTokenizer() {
return headerTokenizer;
}
public void setHeaderTokenizer(LineTokenizer headerTokenizer) {
this.headerTokenizer = headerTokenizer;
}
public String getNames() {
return names;
}
public void setNames(String names) {
this.names = names;
}
@Override
public void handleLine(String headerLine) {
FieldSet fs = getHeaderTokenizer().tokenize(headerLine);
String datePattern = "MMddyyyy";
Date defaultDate = Utility.getDefaultDate();
try {
wcReport = wcReportService.getWCReport(Integer.toString(fs.readInt("organizationCode")), fs.readString("planCode"),fs.readDate("beginDate", datePattern, defaultDate), fs.readDate("endDate", datePattern, defaultDate), fs.readString("reportingType"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(jobExecution != null && wcReport != null) {
ExecutionContext jobContext = jobExecution.getExecutionContext();
jobContext.put("WCREPORT_OBJECT", wcReport);
}
}
@Override
public void beforeStep(StepExecution stepExecution) {
this.jobExecution = stepExecution.getJobExecution();
}
MemberRecordItemWriter.java文件
private int iteration = 0;
private JobExecution jobExecution;
@Override
public void write(List<? extends MemberRecord> records) throws Exception {
System.out.println("Iteration-" + iteration++);
Object wcReport = jobExecution.getExecutionContext().get("WCREPORT_OBJECT");
for (MemberRecord mr : records) {
//System.out.println(header);
System.out.println(mr.getLastName());
}
}
@BeforeStep
public void beforeStep(StepExecution stepExecution) {
this.jobExecution = stepExecution.getJobExecution();
}
感谢, 维杰
我的要求是与你相似:处理传入的文件,将正确处理文件,以“成功”目录和差错文件“错误”。你是如何实现它的? – dsatish 2013-05-09 13:04:44