From 4785cef9820715c36e131f253d20f01bfdfd116d Mon Sep 17 00:00:00 2001 From: lucasward Date: Mon, 9 Mar 2009 13:06:02 +0000 Subject: [PATCH] BATCH-1127:Added logging statement to FFIR for parsing exceptions, and wrap all exceptions within DefaultLineMapper with a FlatFileParseException. --- .../batch/item/file/FlatFileItemReader.java | 9 +++- .../item/file/mapping/DefaultLineMapper.java | 15 +++++- .../file/mapping/DefaultLineMapperTests.java | 51 +++++++++++++++++++ 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemReader.java index 706904c1d..e8efdfa2c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemReader.java @@ -176,7 +176,14 @@ public class FlatFileItemReader extends AbstractItemCountingItemStreamItemRea return null; } else { - return lineMapper.mapLine(logicalLine, lineCount); + try{ + return lineMapper.mapLine(logicalLine, lineCount); + } + catch(Exception ex){ + logger.error("Parsing error at line: " + lineCount + " in resource=" + + resource.getDescription() + ", input=[" + line + "]", ex); + throw ex; + } } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/DefaultLineMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/DefaultLineMapper.java index daedfc5d5..0db1366dd 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/DefaultLineMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/DefaultLineMapper.java @@ -16,6 +16,7 @@ package org.springframework.batch.item.file.mapping; +import org.springframework.batch.item.file.FlatFileParseException; import org.springframework.batch.item.file.transform.FieldSet; import org.springframework.batch.item.file.transform.LineTokenizer; import org.springframework.beans.factory.InitializingBean; @@ -23,9 +24,13 @@ import org.springframework.util.Assert; /** * Two-phase {@link LineMapper} implementation consisting of tokenization of the - * line into {@link FieldSet} followed by mapping to item. + * line into {@link FieldSet} followed by mapping to item. By default, any exceptions + * thrown by either delegates will be wrapped in a {@link FlatFileParseException} before + * being rethrown. If finer grained control of exceptions is needed, the {@link LineMapper} + * interface should be implemented directly. * * @author Robert Kasanicky + * @author Lucas Ward * * @param type of the item */ @@ -36,7 +41,13 @@ public class DefaultLineMapper implements LineMapper, InitializingBean { private FieldSetMapper fieldSetMapper; public T mapLine(String line, int lineNumber) throws Exception { - return fieldSetMapper.mapFieldSet(tokenizer.tokenize(line)); + try{ + return fieldSetMapper.mapFieldSet(tokenizer.tokenize(line)); + } + catch(Exception ex){ + throw new FlatFileParseException("Parsing error at line: " + lineNumber + + ", input=[" + line + "]", ex, line, lineNumber); + } } public void setLineTokenizer(LineTokenizer tokenizer) { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/DefaultLineMapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/DefaultLineMapperTests.java index f95905dca..1ce6f2044 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/DefaultLineMapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/DefaultLineMapperTests.java @@ -4,6 +4,7 @@ import static org.easymock.EasyMock.*; import static org.junit.Assert.*; import org.junit.Test; +import org.springframework.batch.item.file.FlatFileParseException; import org.springframework.batch.item.file.transform.DefaultFieldSet; import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; import org.springframework.batch.item.file.transform.FieldSet; @@ -52,4 +53,54 @@ public class DefaultLineMapperTests { verify(fsMapper); } + + @Test + public void testTokenizerException() throws Exception { + final String line = "TEST"; + + LineTokenizer tokenizer = createStrictMock(LineTokenizer.class); + expect(tokenizer.tokenize(line)).andThrow(new RuntimeException()); + replay(tokenizer); + + @SuppressWarnings("unchecked") + FieldSetMapper fsMapper = createStrictMock(FieldSetMapper.class); + + tested.setLineTokenizer(tokenizer); + tested.setFieldSetMapper(fsMapper); + + try{ + tested.mapLine(line, 1); + } + catch(FlatFileParseException ex){ + assertEquals(ex.getLineNumber(), 1); + assertEquals(ex.getInput(), line); + } + } + + @Test + public void testMapperException() throws Exception { + final String line = "TEST"; + final FieldSet fs = new DefaultFieldSet(new String[]{"token1", "token2"}); + + LineTokenizer tokenizer = createStrictMock(LineTokenizer.class); + expect(tokenizer.tokenize(line)).andReturn(fs); + replay(tokenizer); + + @SuppressWarnings("unchecked") + FieldSetMapper fsMapper = createStrictMock(FieldSetMapper.class); + expect(fsMapper.mapFieldSet(fs)).andThrow(new RuntimeException()); + replay(fsMapper); + + tested.setLineTokenizer(tokenizer); + tested.setFieldSetMapper(fsMapper); + + try{ + tested.mapLine(line, 1); + } + catch(FlatFileParseException ex){ + assertEquals(ex.getLineNumber(), 1); + assertEquals(ex.getInput(), line); + } + + } }