2012-03-07 3 views
2

У меня есть требование в моем проекте, где я хочу обрабатывать данные в файлах фиксированной длины. Файл данных содержит одну строку заголовка и множество строк подробностей. Строка заголовка содержит сводку & консолидирует информацию о деталях линий. например отчетный период, отчет работодателя, общая сумма и т. д. Строка сведений содержит информацию для каждого отдельного сотрудника. например вклад сотрудников, период вклада и т. д. Будет много файлов данных, полученных от разных работодателей, которые должны обрабатываться работой.Spring Batch Questions

Итак, я создал работу одним шагом со следующими читателями & писателей и других пользовательских классов a. MultiResourceItemReade для чтения всех файлов в папке. b. FlatFileItemReader для чтения каждого файла. Делегировано из MultiResourceItemReader. c. Я пропускаю первую строку и обрабатываю LineCallbackHandler d. Я могу разобрать строку заголовка и преобразовать его в объект Report. e. Я использую DefaultLineMapper и BeanWrapperFieldSetMapper для синтаксического анализа строки и преобразования в объект MemberRecrod.

Мне нужна помощь в достижении следующей весенней порции.

  1. Я хочу, чтобы один объект 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.

  1. В настоящее время у меня есть образцы данных в папке под папкой webinf/conf/data. В идеале я хочу обработать все файлы из местоположения FTP. Как указать расположение папки FTP для свойства ресурса.
  2. После успешной обработки каждого файла мне нужно архивировать файл в другую папку. Как архивировать файлы с помощью Spring Batch.
  3. Если есть какие-то исключения из-за неправильного формата данных, мне нужно обновить запись в БД и переместить файл с ошибкой в ​​папку «Ошибка». Я не хочу, чтобы работа была остановлена ​​из-за этой ошибки. Я хочу продолжить обработку других файлов. Как обрабатывать исключения в этом случае.

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

+0

Моего требование похоже на ваш: обрабатывать входящие файлы, перемещать правильно обработанные файлы «успех» каталог и ошибочные файлы в «ошибка». Как вы его реализовали? – dsatish

ответ

0

При обработке входящих файлов с FTP последующей обработкой необходимо интегрировать Spring Integration и Spring Batch для создания система, основанная на событиях.

  1. Настройте интеграцию Spring для прослушивания вашего ftp-сервера.
  2. Spring Integration будет запускать задание после обнаружения входящего файла.
  3. Spring Batch обрабатывает входящий файл и сохраняет данные в базе данных.
  4. Примечания: для добавления функциональности архивирования необходимо добавить его либо на JobListener Spring Batch или StepListener