diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java index 8ec1534a6..7d23c926e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java @@ -110,13 +110,22 @@ public class FlatFileItemWriterTests { * because running the tests in a UNIX environment locks the file if it's open for writing. */ private String readLine() throws IOException { + return readLine("UTF-8"); + } + + /* + * Read a line from the output file, if the reader has not been created, recreate. This method is only necessary + * because running the tests in a UNIX environment locks the file if it's open for writing. + */ + private String readLine(String encoding) throws IOException { if (reader == null) { - reader = new BufferedReader(new InputStreamReader(new FileInputStream(outputFile), "UTF-8")); + reader = new BufferedReader(new InputStreamReader(new FileInputStream(outputFile), encoding)); } return reader.readLine(); - } + } + /* * Properly close the output file reader. */ @@ -434,8 +443,18 @@ public class FlatFileItemWriterTests { @Test // BATCH-1959 - public void testTransactionalRestartWithMultiByteCharacter() throws Exception { + public void testTransactionalRestartWithMultiByteCharacterUTF8() throws Exception { + testTransactionalRestartWithMultiByteCharacter("UTF-8"); + } + @Test + // BATCH-1959 + public void testTransactionalRestartWithMultiByteCharacterUTF16BE() throws Exception { + testTransactionalRestartWithMultiByteCharacter("UTF-16BE"); + } + + private void testTransactionalRestartWithMultiByteCharacter(String encoding) throws Exception { + writer.setEncoding(encoding); writer.setFooterCallback(new FlatFileFooterCallback() { @Override @@ -492,15 +511,14 @@ public class FlatFileItemWriterTests { // verify what was written to the file for (int i = 1; i <= 8; i++) { - assertEquals("téstLine" + i, readLine()); + assertEquals("téstLine" + i, readLine(encoding)); } - assertEquals("footer", readLine()); + assertEquals("footer", readLine(encoding)); // 3 lines were written to the file after restart - assertEquals(3, executionContext.getLong(ClassUtils.getShortName(FlatFileItemWriter.class) + ".written")); - - } + assertEquals(3, executionContext.getLong(ClassUtils.getShortName(FlatFileItemWriter.class) + ".written")); + } @Test public void testOpenWithNonWritableFile() throws Exception { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java index 5b10370c1..a467fdaf7 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java @@ -60,13 +60,26 @@ public class StaxEventItemWriterTests { private JAXBItem jaxbItem = new JAXBItem(); + // test item for writing to output with multi byte character + private Object itemMultiByte = new Object() { + @Override + public String toString() { + return ClassUtils.getShortName(StaxEventItemWriter.class) + "-téstStrïng"; + } + }; + private List items = Collections.singletonList(item); + private List itemsMultiByte = Collections.singletonList(itemMultiByte); + private List jaxbItems = Collections.singletonList(jaxbItem); private static final String TEST_STRING = "<" + ClassUtils.getShortName(StaxEventItemWriter.class) + "-testString/>"; + private static final String TEST_STRING_MULTI_BYTE = "<" + ClassUtils.getShortName(StaxEventItemWriter.class) + + "-téstStrïng/>"; + private static final String NS_TEST_STRING = ""; @@ -185,6 +198,68 @@ public class StaxEventItemWriterTests { assertTrue(outputFile.contains("" + TEST_STRING + TEST_STRING + "")); } + @Test + // BATCH-1959 + public void testTransactionalRestartWithMultiByteCharacterUTF8() throws Exception { + testTransactionalRestartWithMultiByteCharacter("UTF-8"); + } + + @Test + // BATCH-1959 + public void testTransactionalRestartWithMultiByteCharacterUTF16BE() throws Exception { + testTransactionalRestartWithMultiByteCharacter("UTF-16BE"); + } + + private void testTransactionalRestartWithMultiByteCharacter(String encoding) throws Exception { + writer.setEncoding(encoding); + writer.open(executionContext); + + PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); + + new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + @Override + public Object doInTransaction(TransactionStatus status) { + try { + // write item + writer.write(itemsMultiByte); + } + catch (Exception e) { + throw new UnexpectedInputException("Could not write data", e); + } + // get restart data + writer.update(executionContext); + return null; + } + }); + writer.close(); + + // create new writer from saved restart data and continue writing + writer = createItemWriter(); + writer.setEncoding(encoding); + writer.open(executionContext); + new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + @Override + public Object doInTransaction(TransactionStatus status) { + try { + writer.write(itemsMultiByte); + } + catch (Exception e) { + throw new UnexpectedInputException("Could not write data", e); + } + // get restart data + writer.update(executionContext); + return null; + } + }); + writer.close(); + + // check the output is concatenation of 'before restart' and 'after + // restart' writes. + String outputFile = getOutputFileContent(encoding); + assertEquals(2, StringUtils.countOccurrencesOf(outputFile, TEST_STRING_MULTI_BYTE)); + assertTrue(outputFile.contains("" + TEST_STRING_MULTI_BYTE + TEST_STRING_MULTI_BYTE + "")); + } + @Test @SuppressWarnings({"unchecked", "rawtypes"}) public void testTransactionalRestartFailOnFirstWrite() throws Exception { @@ -692,11 +767,21 @@ public class StaxEventItemWriterTests { * @return output file content as String */ private String getOutputFileContent() throws IOException { - String value = FileUtils.readFileToString(resource.getFile(), null); - value = value.replace("", ""); + return getOutputFileContent("UTF-8"); + } + + + /** + * @param encoding the encoding + * @return output file content as String + */ + private String getOutputFileContent(String encoding) throws IOException { + String value = FileUtils.readFileToString(resource.getFile(), encoding); + value = value.replace("", ""); return value; } + /** * @return new instance of fully configured writer */ diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareBufferedWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareBufferedWriterTests.java index dcba51971..d562543e3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareBufferedWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareBufferedWriterTests.java @@ -189,7 +189,7 @@ public class TransactionAwareBufferedWriterTests { @Test @SuppressWarnings({"unchecked", "rawtypes"}) // BATCH-1959 - public void testBufferSizeInTransactionWithMultiByteCharacter() throws Exception { + public void testBufferSizeInTransactionWithMultiByteCharacterUTF8() throws Exception { ArgumentCaptor bb = ArgumentCaptor.forClass(ByteBuffer.class); when(fileChannel.write(bb.capture())).thenReturn(5); @@ -210,6 +210,32 @@ public class TransactionAwareBufferedWriterTests { assertEquals(0, writer.getBufferSize()); } + @Test + @SuppressWarnings({"unchecked", "rawtypes"}) + // BATCH-1959 + public void testBufferSizeInTransactionWithMultiByteCharacterUTF16BE() throws Exception { + writer.setEncoding("UTF-16BE"); + + ArgumentCaptor bb = ArgumentCaptor.forClass(ByteBuffer.class); + when(fileChannel.write(bb.capture())).thenReturn(6); + + new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + @Override + public Object doInTransaction(TransactionStatus status) { + try { + writer.write("fóó"); + } + catch (IOException e) { + throw new IllegalStateException("Unexpected IOException", e); + } + assertEquals(6, writer.getBufferSize()); + return null; + } + }); + + assertEquals(0, writer.getBufferSize()); + } + @Test @SuppressWarnings({"unchecked", "rawtypes"}) public void testWriteWithRollback() throws Exception {