2012-03-07 157 views
2

我在我的項目中要求處理固定長度文件中的數據。數據文件包含一個標題行和許多詳細信息行。標題行包含摘要&合併詳細信息行的信息。例如報告期,報告僱主,總金額等。詳細信息行包含每個員工的信息。例如員工貢獻,貢獻期等。從不同的僱主那裏收到很多需要由工作處理的數據文件。Spring批處理問題

所以我創建了一個步驟的作業,下面的讀者&作家和其他自定義類 a。 MultiResourceItemReade讀取文件夾中的所有文件。 b。 FlatFileItemReader讀取每個文件。從MultiResourceItemReader委託。 c。我正在跳過第一行,並處理LineCallbackHandler d。我能夠解析標題行並將其轉換爲Report對象。 e。我使用DefaultLineMapper和BeanWrapperFieldSetMapper來解析細節行並將其轉換爲MemberRecrod對象。

我需要幫助實現以下使用spring批處理。

  1. 我想要一個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實現以下功能的建議。

  1. 目前我正在將我的示例數據文件放在webinf/conf/data文件夾下的文件夾中。理想情況下,我想處理來自FTP位置的所有文件。如何指定資源屬性的FTP文件夾位置。
  2. 成功處理每個文件後,我需要將文件歸檔到不同的文件夾。如何使用Spring Batch存檔文件。
  3. 如果由於數據格式錯誤而導致有任何異常,我需要更新數據庫中的記錄並將錯誤的文件移動到錯誤文件夾中。由於這個錯誤,我不希望工作停止。我想繼續處理其他文件。在這種情況下如何處理異常。

作業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(); 
    } 

感謝, 維傑

+0

我的要求是與你相似:處理傳入的文件,將正確處理文件,以「成功」目錄和差錯文件「錯誤」。你是如何實現它的? – dsatish 2013-05-09 13:04:44

回答

0

在從FTP處理傳入的文件,那麼你的處理需要集成Spring集成和Spring Batch的創建基於事件的系統。

  1. 將Spring集成配置爲偵聽您的ftp服務器。
  2. Spring Integration將在檢測到傳入文件後運行作業。
  3. Spring Batch將處理傳入文件並將數據保存到數據庫。
  4. 注:添加歸檔功能,你需要添加它無論是在春季批次的JobListener或StepListener