У меня есть требование в моем проекте, где я хочу обрабатывать данные в файлах фиксированной длины. Файл данных содержит одну строку заголовка и множество строк подробностей. Строка заголовка содержит сводку & консолидирует информацию о деталях линий. например отчетный период, отчет работодателя, общая сумма и т. д. Строка сведений содержит информацию для каждого отдельного сотрудника. например вклад сотрудников, период вклада и т. д. Будет много файлов данных, полученных от разных работодателей, которые должны обрабатываться работой.Spring Batch Questions
Итак, я создал работу одним шагом со следующими читателями & писателей и других пользовательских классов a. MultiResourceItemReade для чтения всех файлов в папке. b. FlatFileItemReader для чтения каждого файла. Делегировано из MultiResourceItemReader. c. Я пропускаю первую строку и обрабатываю LineCallbackHandler d. Я могу разобрать строку заголовка и преобразовать его в объект Report. e. Я использую DefaultLineMapper и BeanWrapperFieldSetMapper для синтаксического анализа строки и преобразования в объект MemberRecrod.
Мне нужна помощь в достижении следующей весенней порции.
- Я хочу, чтобы один объект Report был доступен в ItemWriter для каждого файла, обработанного в папке. Так что я могу добавить все объекты MemberRecord [подробные строки] в объект Report и сохранить его в БД [я использую спящий режим для ORM]. Я попытался сделать это, добавив объект Report в JobExecutionContext и получив доступ к нему в ItemWriter. Поэтому я расширил StepExecutionListenerSupport из класса MemberRecordHeaderLineHandler [это реализует LineCallbackHandler]. И переопределить метод beforeStep. Я могу получить объект JobExection в методе beforeStep, и я сохраняю объект JobExection для локальной переменной в классе MemberRecordHeaderLineHandler. Но когда элемент управления переходит к методу handleLine, переменная JobExection имеет значение NULL. Я разбираю строку заголовка и преобразовываю его в объект Report в методе handleLine. Поскольку JobExection равно null, я не могу добавить объект Rerpot к объекту JobExecutionContext. Я не уверен, как передать объект Report в ItemWriter. Пожалуйста, посоветуйте мне, как значения от LineCallBackHandler до ItemWriter.
Мне также нужно предложить, как реализовать следующую функциональность, используя Spring Batch.
- В настоящее время у меня есть образцы данных в папке под папкой webinf/conf/data. В идеале я хочу обработать все файлы из местоположения FTP. Как указать расположение папки FTP для свойства ресурса.
- После успешной обработки каждого файла мне нужно архивировать файл в другую папку. Как архивировать файлы с помощью Spring Batch.
- Если есть какие-то исключения из-за неправильного формата данных, мне нужно обновить запись в БД и переместить файл с ошибкой в папку «Ошибка». Я не хочу, чтобы работа была остановлена из-за этой ошибки. Я хочу продолжить обработку других файлов. Как обрабатывать исключения в этом случае.
Job xml file.
<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();
}
Спасибо, Vijay
Моего требование похоже на ваш: обрабатывать входящие файлы, перемещать правильно обработанные файлы «успех» каталог и ошибочные файлы в «ошибка». Как вы его реализовали? – dsatish