2014-06-17 50 views
3

我在那裏我閱讀不同種類的輸入的文件,如下的要求相匹配的任何行:Spring Batch的:忽略不指定模式

*JAMBEG,APP=000007,123456 
AC,654321,「ABCD12121212121212」,23423423423424234,ABCDD,23423423423424234,2424,XYZ,ABC,TREX,000000002 
AC,654321,「ABCD12121212121213」,23423423423424234,ABCDD,23423423423424234,2424,XYZ,ABC, TREX,000000002 
... 
AC,654321,「ABCD12121212121214」,23423423423424234,ABCDD,23423423423424234,2424,XYZ,ABC, TREX,000000002 
*JAMEND,APP=000007,123456 
EOF 

只有標題行和記錄下我需要那忽略了以TREX,* JAMEND,EOF開頭的那一行。

這裏是我的線映射如何:

public LineMapper<Customer> lineMapper(){ 

    DelimitedLineTokenizer lineTokenizerHeader = new DelimitedLineTokenizer(); 
    lineTokenizerHeader.setNames(new String[]{"association","companyNumber","fileDate"}); 
    lineTokenizerHeader.setIncludedFields(new int[]{0,1,2}); 
    lineTokenizerHeader.setStrict(false); 

    DelimitedLineTokenizer lineTokenizerBody = new DelimitedLineTokenizer(); 
    lineTokenizerBody.setNames(new String[]{"type","acNumber","orderNumber"}); 
    lineTokenizerBody.setIncludedFields(new int[]{0,1,2}); 
    lineTokenizerBody.setStrict(false); 


    HashMap<String, DelimitedLineTokenizer> tokenizers = new HashMap<String, DelimitedLineTokenizer>(); 
    tokenizers.put("*BEG*", lineTokenizerHeader); 
    tokenizers.put("AC*", lineTokenizerBody); 

    BeanWrapperFieldSetMapper<Customer> beanWrapperFieldSetMapper = new BeanWrapperFieldSetMapper<Customer>(); 
    beanWrapperFieldSetMapper.setTargetType(Customer.class); 
    beanWrapperFieldSetMapper.setStrict(false); 

    HashMap<String, BeanWrapperFieldSetMapper<Customer>> fieldSetMappers = new HashMap<String, BeanWrapperFieldSetMapper<Customer>>(); 
    fieldSetMappers.put("*BEG*", beanWrapperFieldSetMapper); 
    fieldSetMappers.put("AC*", beanWrapperFieldSetMapper); 

    PatternMatchingCompositeLineMapper patternMatchingCompositeLineMapper = new PatternMatchingCompositeLineMapper(); 
    patternMatchingCompositeLineMapper.setTokenizers(tokenizers); 
    patternMatchingCompositeLineMapper.setFieldSetMappers(fieldSetMappers); 

    return patternMatchingCompositeLineMapper; 
} 

它我明顯的錯誤,我沒有對任何TREX映射,* JAMEND,EOF模式。因此,它拋出下面的例外:

2014年6月16日16:49:34746 [主要] DEBUG org.springframework.batch.core.step.item.FaultTolerantChunkProvider - 解析在線路錯誤:5中資源= [類路徑資源 [000.csv]],輸入= [EOF]: org.springframework.batch.item.file.FlatFileParseException 2014-06-16 16:49:34,746 [main] DEBUG org。 springframework.batch.core.step.item.FaultTolerantChunkProvider - 跳過失敗的輸入 org.springframework.batch.item.file.FlatFileParseException:解析 error:line at:5 in resource = [class path r esource [000.csv], 輸入= [EOF]在 org.springframework.batch.item.file.FlatFileItemReader.doRead(FlatFileItemReader.java:183) 在 org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader .read(AbstractItemCountingItemStreamItemReader.java:83) 在 org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:91) 在 org.springframework.batch.core.step.item.FaultTolerantChunkProvider .read(FaultTolerantChunkProvider.java:87) at org.springframework.batch.core.step.item.SimpleChunkProvider $ 1.doInIteration(SimpleChunkProvider.java:114) at org.springframe work.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368) 在 org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) 在 org.springframework.batch。 repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144) 在 org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:108) 在 org.springframework.batch.core。 step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:69) 在 org.springframework.batch.core.step.tasklet.TaskletStep $ ChunkTransactionCallback.doInTransaction(TaskletStep.java:402) 在 org.spri ngframework.batch.core.step.tasklet.TaskletStep $ ChunkTransactionCallback.doInTransaction(TaskletStep.java:326) 在 org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130) 在 org.springframework。 batch.core.step.tasklet.TaskletStep $ 2.doInChunkContext(TaskletStep.java:267) 在 org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77) 在 org.springframework .batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368) at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate。的java:215) 在 org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144) 在 org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java: 253) 在 org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:198) 在 org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148) 在 org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:386) 在 org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:135) 在 org.spring framework.batch.core.job.AbstractJob.execute(AbstractJob.java:304) 在 org.springframework.batch.core.launch.support.SimpleJobLauncher $ 1.run(SimpleJobLauncher.java:135) 在 org.springframework .core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48) 在 org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128) 在sun.reflect.NativeMethodAccessorImpl.invoke0(本地方法)在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在java.lang.reflect.Method.invoke(方法。 java:597)at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 在 org.springframework.aop.framework .ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 在 org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration $ PassthruAdvice.invoke(SimpleBatchConfiguration.java:117) 在 org.springframework.aop.framework.ReflectiveMethodInvocation .proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopPr $ proxy17.run(Unknown Source)at com.chofac.pm.batch.CustomerFileToDBJobTest.testLaunchJob(CustomerFileToDBJobTest.java:48) at sun.reflect.NativeMethodAccessorImpl。 invoke0(本機方法)在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在java.lang.reflect.Method.invoke( Method.java:597)在 org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall(FrameworkMethod.java:45) 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) 在 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 在 org.junit.internal .runners.statements.RunBefores.evaluate(RunBefores.java:28) 在 org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 在 org.springframework.test.context .Junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat。的java:72) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) 在有機junit.runners.ParentRunner $ 3.run(ParentRunner.java:231)at org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:60)at org.junit.runners.ParentRunner.runChildren(ParentRunner.java: 229)在 org.junit.runners.ParentRunner.access $在 org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:222)000(ParentRunner.java:50)在 org.springframework.test.context。 junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 在 org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 在org.junit.runners.ParentRunner.run(ParentRunner.java:300)在 org.springframework.test .context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 在 org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 在 org.eclipse.jdt.internal .junit.runner.TestExecution.run(TestExecution.java:38) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 在 org.eclipse.jdt.internal .junit.runner.RemoteTestRunner .runTests(RemoteTestRunner.java:683) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner .main(RemoteTestRunner.java:197) 引起:java.lang.IllegalStateException:在 org.springframework.batch.support.PatternMatcher.match(PatternMatcher.java:無法找到匹配的密鑰= [EOF] 模式: 226) 在 org.springframework.batch.item.file.mapping.PatternMatchingCompositeLineMapper.mapLine(PatternMatchingCompositeLineMapper.java:62) 在 org.springframework.batch.item.file.FlatFileItemReader.doRead(FlatFileItemReader.java:180) ... 67更多

我看了很多例子,this one匹配關閉,並改變了我的步驟如下,但仍然是同樣的問題。

@Bean 
public Step step(){ 
    return stepBuilders.get("step") 
    .<Customer,Customer>chunk(1) 
    .reader(CustomerAUFileReader()) 
    .faultTolerant() 
    .skipLimit(3) 
    .skip(Exception.class) 
    .processor(CustomerRecordProcessor()) 
    .writer(CustomerDBWriter()) 
    .listener(logProcessListener()) 
    .build(); 
} 

看着Spring.io docs here跳繩記錄(5.1.5配置跳過邏輯),也不管用。

請讓我知道解決此問題的理想方法。是否應該沒有簡單的方法來指定不符合特定情況的跳過記錄?請指教。謝謝。

---

我有「*」的模式映射器,我正與一個虛擬的類映射。我在過程階段返回null,但它拋出nullpointerexception。

堆棧跟蹤:

2014-06-17 10:03:01,690 [main] DEBUG org.springframework.batch.core.step.item.FaultTolerantChunkProcessor - Skipping after failed process 
org.springframework.batch.core.listener.StepListenerFailedException: Error in afterProcess. 
    at org.springframework.batch.core.listener.MulticasterBatchListener.afterProcess(MulticasterBatchListener.java:136) 
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.doProcess(SimpleChunkProcessor.java:127) 
    at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor$1.doWithRetry(FaultTolerantChunkProcessor.java:225) 
    at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:263) 
    at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:193) 
    at org.springframework.batch.core.step.item.BatchRetryTemplate.execute(BatchRetryTemplate.java:217) 
    at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor.transform(FaultTolerantChunkProcessor.java:290) 
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:192) 
    at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:75) 
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:402) 
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:326) 
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130) 
    at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:267) 
    at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77) 
    at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368) 
    at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) 
    at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144) 
    at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:253) 
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:198) 
    at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148) 
    at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:386) 
    at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:135) 
    at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:304) 
    at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135) 
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48) 
    at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:117) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
    at com.sun.proxy.$Proxy17.run(Unknown Source) 
    at com.chofac.pl.batch.CustomerFileToDBJobTest.testLaunchJob(CustomerFileToDBJobTest.java:48) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
Caused by: java.lang.NullPointerException 
    at com.chofac.pl.batch.CustomerItemProcessListener.afterProcess(CustomerItemProcessListener.java:13) 
    at org.springframework.batch.core.listener.CompositeItemProcessListener.afterProcess(CompositeItemProcessListener.java:60) 
    at org.springframework.batch.core.listener.MulticasterBatchListener.afterProcess(MulticasterBatchListener.java:133) 

回答

1

你的意圖不是跳過對象由於錯誤,但跳過一個邏輯記錄;我認爲你最好的選擇是將一個映射器綁定到'*'並返回一個自定義對象(如SkippableRecordBean)而不是Customer,並過濾掉ItemProcessor中不需要的bean。

4

一種方法:

讓您ItemReader簡單地讀取一行返回原樣。因此讀者給出的項目將是一個簡單的字符串。

編寫一個簡單ItemProcessor,這主要是做對的例子的圖案你LineMapper,基地的工作:如果該項目與模式匹配,然後轉換輸入字符串您Customer回報。如果圖案不匹配,只需返回null並且該項目將被跳過。該項目處理器

僞代碼:

class CustomPatternMatchingItemProcessor<String, Customer> 
     implements ItemProcessor<String, Customer> { 
    private String pattern; 

    public Customer process(String s) { 
     if (s matches pattern) { 
      construct Customer object base on s 
      return customer 
     } else { 
      return null; 
     } 
    } 
} 

甚至清潔劑:有一個處理器從字符串到客戶,而另一處理器做映射的工作要做正則表達式串基地的驗證。

只是使用CompositeItemProcessor鏈接您的處理器。這可以更好地分離您的每個處理器。

1

我有一個類似的問題,我發送的文件將始終有一些行不符合正確的模式。因爲我只想忽略這些行,所以我將它們記錄下來,然後跳過它們。

您可以實現 org.springframework.batch.repeat.exception.ExceptionHandler像這樣:

class LocalExceptionHandler implements ExceptionHandler { 

    @Override 
    public void handleException(RepeatContext rc, Throwable throwable) throws Throwable { 
     if (throwable instanceof FlatFileParseException) { 
      FlatFileParseException fe = (FlatFileParseException)throwable; 
      log.error("!!!! FlatFileParseException, line # is: " + fe.getLineNumber()); 
      log.error("!!!! FlatFileParseException, input is: " + fe.getInput()); 
     } 
     log.error("!!!! Message : " + throwable.getMessage()); 
     log.error("!!!! Cause : " + throwable.getCause());  
    } 
} 

,然後添加到您的一步建設者:

faultTolerantStepBuilder.exceptionHandler(new LocalExceptionHandler()); 
faultTolerantStepBuilder.skipLimit(100); 
0

我們開始從LineMapper而不是返回null虛擬對象爲空導致閱讀器跳過閱讀其他行。在ItemWriter中,寫入方法仍然會獲得這個虛擬對象,並且在處理它之前需要進行驗證。我們忽略ItemWriter中的虛擬記錄。

0
public class FileVerificationSkipper implements SkipPolicy { 

    @Autowired 
    private Environment environment; 

    @Override 
    public boolean shouldSkip(Throwable exception, int skipCount) throws SkipLimitExceededException { 
     int skipErrorsRecords = Integer.valueOf(environment.getProperty("max.error.record.count")); 
     if (exception instanceof FileNotFoundException) { 
      return false; 
     } else if (exception instanceof FlatFileParseException && (skipErrorsRecords < 0 || skipCount <= (skipErrorsRecords-1))) { 
      FlatFileParseException ffpe = (FlatFileParseException) exception; 
      StringBuilder errorMessage = new StringBuilder(); 
      errorMessage.append((skipCount+1)+", An error occured while processing the " + ffpe.getLineNumber() + " record of the file. the faulty record is:\n"); 
      errorMessage.append(ffpe.getInput() + "\n"); 
      return true; 
     } else { 
      return false; 
     } 
    } 
} 

StepBuilder是:

@Bean 
public Step step1() throws Exception{ 
    return stepBuilderFactory.get("step1") 
      .<User, User> chunk(50) 
      .reader(reader()) 
      .faultTolerant() 
      .skipPolicy(fileVerificationSkipper()) 
      .processor(processor()) 
      .writer(writer()) 
      .build(); 
}