Skip to content

Commit 2952e9a

Browse files
committed
Add encoding parameter in StaxEventItemReader
Resolves #807
1 parent a88b074 commit 2952e9a

4 files changed

Lines changed: 98 additions & 5 deletions

File tree

spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemReader.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2019 the original author or authors.
2+
* Copyright 2006-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818

1919
import java.io.IOException;
2020
import java.io.InputStream;
21+
import java.nio.charset.Charset;
2122
import java.util.ArrayList;
2223
import java.util.List;
2324
import java.util.NoSuchElementException;
@@ -62,6 +63,8 @@ public class StaxEventItemReader<T> extends AbstractItemCountingItemStreamItemRe
6263

6364
private static final Log logger = LogFactory.getLog(StaxEventItemReader.class);
6465

66+
public static final String DEFAULT_ENCODING = Charset.defaultCharset().name();
67+
6568
private FragmentEventReader fragmentReader;
6669

6770
private XMLEventReader eventReader;
@@ -80,6 +83,8 @@ public class StaxEventItemReader<T> extends AbstractItemCountingItemStreamItemRe
8083

8184
private XMLInputFactory xmlInputFactory = StaxUtils.createXmlInputFactory();
8285

86+
private String encoding = DEFAULT_ENCODING;
87+
8388
public StaxEventItemReader() {
8489
setName(ClassUtils.getShortName(StaxEventItemReader.class));
8590
}
@@ -131,6 +136,16 @@ public void setXmlInputFactory(XMLInputFactory xmlInputFactory) {
131136
this.xmlInputFactory = xmlInputFactory;
132137
}
133138

139+
/**
140+
* Set encoding to be used for the input file. Defaults to {@link #DEFAULT_ENCODING}.
141+
*
142+
* @param encoding the encoding to be used
143+
*/
144+
public void setEncoding(String encoding) {
145+
Assert.notNull(encoding, "The encoding must not be null");
146+
this.encoding = encoding;
147+
}
148+
134149
/**
135150
* Ensure that all required dependencies for the ItemReader to run are provided after all properties have been set.
136151
*
@@ -221,7 +236,7 @@ protected void doOpen() throws Exception {
221236
}
222237

223238
inputStream = resource.getInputStream();
224-
eventReader = xmlInputFactory.createXMLEventReader(inputStream);
239+
eventReader = xmlInputFactory.createXMLEventReader(inputStream, this.encoding);
225240
fragmentReader = new DefaultFragmentEventReader(eventReader);
226241
noInput = false;
227242

spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/builder/StaxEventItemReaderBuilder.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2019 the original author or authors.
2+
* Copyright 2017-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
3333
*
3434
* @author Michael Minella
3535
* @author Glenn Renfro
36+
* @author Mahmoud Ben Hassine
3637
* @since 4.0
3738
*/
3839
public class StaxEventItemReaderBuilder<T> {
@@ -55,6 +56,8 @@ public class StaxEventItemReaderBuilder<T> {
5556

5657
private XMLInputFactory xmlInputFactory = StaxUtils.createXmlInputFactory();
5758

59+
private String encoding = StaxEventItemReader.DEFAULT_ENCODING;
60+
5861
/**
5962
* Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
6063
* should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
@@ -193,6 +196,19 @@ public StaxEventItemReaderBuilder<T> xmlInputFactory(XMLInputFactory xmlInputFac
193196
return this;
194197
}
195198

199+
/**
200+
* Encoding for the input file. Defaults to {@link StaxEventItemReader#DEFAULT_ENCODING}.
201+
*
202+
* @param encoding String encoding algorithm
203+
* @return the current instance of the builder
204+
* @see StaxEventItemReader#setEncoding(String)
205+
*/
206+
public StaxEventItemReaderBuilder<T> encoding(String encoding) {
207+
this.encoding = encoding;
208+
209+
return this;
210+
}
211+
196212
/**
197213
* Validates the configuration and builds a new {@link StaxEventItemReader}
198214
*
@@ -222,6 +238,7 @@ public StaxEventItemReader<T> build() {
222238
reader.setCurrentItemCount(this.currentItemCount);
223239
reader.setMaxItemCount(this.maxItemCount);
224240
reader.setXmlInputFactory(this.xmlInputFactory);
241+
reader.setEncoding(this.encoding);
225242

226243
return reader;
227244
}

spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemReaderTests.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2019 the original author or authors.
2+
* Copyright 2008-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -43,6 +43,9 @@
4343
import java.io.File;
4444
import java.io.IOException;
4545
import java.io.InputStream;
46+
import java.nio.ByteBuffer;
47+
import java.nio.charset.Charset;
48+
import java.nio.charset.StandardCharsets;
4649
import java.util.ArrayList;
4750
import java.util.Arrays;
4851
import java.util.List;
@@ -146,6 +149,26 @@ public void testFragmentWrapping() throws Exception {
146149
source.close();
147150
}
148151

152+
/**
153+
* Regular usage scenario with custom encoding.
154+
*/
155+
@Test
156+
public void testCustomEncoding() throws Exception {
157+
Charset encoding = StandardCharsets.ISO_8859_1;
158+
ByteBuffer xmlResource = encoding.encode(xml);
159+
source.setResource(new ByteArrayResource(xmlResource.array()));
160+
source.setEncoding(encoding.name());
161+
source.afterPropertiesSet();
162+
source.open(executionContext);
163+
164+
// see asserts in the mock unmarshaller
165+
assertNotNull(source.read());
166+
assertNotNull(source.read());
167+
assertNull(source.read()); // there are only two fragments
168+
169+
source.close();
170+
}
171+
149172
@Test
150173
public void testItemCountAwareFragment() throws Exception {
151174
StaxEventItemReader<ItemCountAwareFragment> source = createNewItemCountAwareInputSource();

spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/builder/StaxEventItemReaderBuilderTests.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2019 the original author or authors.
2+
* Copyright 2017-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,6 +15,9 @@
1515
*/
1616
package org.springframework.batch.item.xml.builder;
1717

18+
import java.nio.ByteBuffer;
19+
import java.nio.charset.Charset;
20+
import java.nio.charset.StandardCharsets;
1821
import javax.xml.bind.annotation.XmlRootElement;
1922
import javax.xml.stream.XMLInputFactory;
2023

@@ -116,6 +119,41 @@ public void testConfiguration() throws Exception {
116119
assertEquals(2, executionContext.size());
117120
}
118121

122+
@Test
123+
public void testCustomEncoding() throws Exception {
124+
Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller();
125+
unmarshaller.setClassesToBeBound(Foo.class);
126+
127+
Charset charset = StandardCharsets.ISO_8859_1;
128+
ByteBuffer xml = charset.encode(SIMPLE_XML);
129+
130+
StaxEventItemReader<Foo> reader = new StaxEventItemReaderBuilder<Foo>()
131+
.name("fooReader")
132+
.resource(new ByteArrayResource(xml.array()))
133+
.encoding(charset.name())
134+
.addFragmentRootElements("foo")
135+
.currentItemCount(1)
136+
.maxItemCount(2)
137+
.unmarshaller(unmarshaller)
138+
.xmlInputFactory(XMLInputFactory.newInstance())
139+
.build();
140+
141+
reader.afterPropertiesSet();
142+
143+
ExecutionContext executionContext = new ExecutionContext();
144+
reader.open(executionContext);
145+
Foo item = reader.read();
146+
assertNull(reader.read());
147+
reader.update(executionContext);
148+
149+
reader.close();
150+
151+
assertEquals(4, item.getFirst());
152+
assertEquals("five", item.getSecond());
153+
assertEquals("six", item.getThird());
154+
assertEquals(2, executionContext.size());
155+
}
156+
119157
@Test(expected = ItemStreamException.class)
120158
public void testStrict() throws Exception {
121159
Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller();

0 commit comments

Comments
 (0)