Skip to content

Add encoding parameter in StaxEventItemReader #728

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ public class StaxEventItemReader<T> extends AbstractItemCountingItemStreamItemRe

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

public static final String DEFAULT_ENCODING = "UTF-8";

private FragmentEventReader fragmentReader;

private XMLEventReader eventReader;
Expand All @@ -80,6 +82,8 @@ public class StaxEventItemReader<T> extends AbstractItemCountingItemStreamItemRe

private XMLInputFactory xmlInputFactory = StaxUtils.createXmlInputFactory();

private String encoding = DEFAULT_ENCODING;

public StaxEventItemReader() {
setName(ClassUtils.getShortName(StaxEventItemReader.class));
}
Expand Down Expand Up @@ -131,6 +135,16 @@ public void setXmlInputFactory(XMLInputFactory xmlInputFactory) {
this.xmlInputFactory = xmlInputFactory;
}

/**
* Set encoding to be used for input file.
*
* @param encoding the encoding to be used
*/
public void setEncoding(String encoding) {
Assert.notNull(encoding, "The encoding must not be null");
this.encoding = encoding;
}

/**
* Ensure that all required dependencies for the ItemReader to run are provided after all properties have been set.
*
Expand Down Expand Up @@ -221,7 +235,7 @@ protected void doOpen() throws Exception {
}

inputStream = resource.getInputStream();
eventReader = xmlInputFactory.createXMLEventReader(inputStream);
eventReader = xmlInputFactory.createXMLEventReader(inputStream, this.encoding);
fragmentReader = new DefaultFragmentEventReader(eventReader);
noInput = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
*
* @author Michael Minella
* @author Glenn Renfro
* @author Mahmoud Ben Hassine
* @since 4.0
*/
public class StaxEventItemReaderBuilder<T> {
Expand All @@ -55,6 +56,8 @@ public class StaxEventItemReaderBuilder<T> {

private XMLInputFactory xmlInputFactory = StaxUtils.createXmlInputFactory();

private String encoding = StaxEventItemReader.DEFAULT_ENCODING;

/**
* Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
* should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
Expand Down Expand Up @@ -193,6 +196,19 @@ public StaxEventItemReaderBuilder<T> xmlInputFactory(XMLInputFactory xmlInputFac
return this;
}

/**
* Encoding for the input file. Defaults to UTF-8.
*
* @param encoding String encoding algorithm
* @return the current instance of the builder
* @see StaxEventItemReader#setEncoding(String)
*/
public StaxEventItemReaderBuilder<T> encoding(String encoding) {
this.encoding = encoding;

return this;
}

/**
* Validates the configuration and builds a new {@link StaxEventItemReader}
*
Expand Down Expand Up @@ -222,6 +238,7 @@ public StaxEventItemReader<T> build() {
reader.setCurrentItemCount(this.currentItemCount);
reader.setMaxItemCount(this.maxItemCount);
reader.setXmlInputFactory(this.xmlInputFactory);
reader.setEncoding(this.encoding);

return reader;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -146,6 +149,26 @@ public void testFragmentWrapping() throws Exception {
source.close();
}

/**
* Regular usage scenario with custom encoding.
*/
@Test
public void testEncoding() throws Exception {
Charset encoding = StandardCharsets.ISO_8859_1;
ByteBuffer xmlResource = encoding.encode(xml);
source.setResource(new ByteArrayResource(xmlResource.array()));
source.setEncoding(encoding.toString());
source.afterPropertiesSet();
source.open(executionContext);

// see asserts in the mock unmarshaller
assertNotNull(source.read());
assertNotNull(source.read());
assertNull(source.read()); // there are only two fragments

source.close();
}

@Test
public void testItemCountAwareFragment() throws Exception {
StaxEventItemReader<ItemCountAwareFragment> source = createNewItemCountAwareInputSource();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package org.springframework.batch.item.xml.builder;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.stream.XMLInputFactory;

Expand Down Expand Up @@ -116,6 +118,40 @@ public void testConfiguration() throws Exception {
assertEquals(2, executionContext.size());
}

@Test
public void testEncoding() throws Exception {
Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller();
unmarshaller.setClassesToBeBound(Foo.class);

ByteBuffer xml = StandardCharsets.ISO_8859_1.encode(SIMPLE_XML);

StaxEventItemReader<Foo> reader = new StaxEventItemReaderBuilder<Foo>()
.name("fooReader")
.resource(new ByteArrayResource(xml.array()))
.encoding(StandardCharsets.ISO_8859_1.toString())
.addFragmentRootElements("foo")
.currentItemCount(1)
.maxItemCount(2)
.unmarshaller(unmarshaller)
.xmlInputFactory(XMLInputFactory.newInstance())
.build();

reader.afterPropertiesSet();

ExecutionContext executionContext = new ExecutionContext();
reader.open(executionContext);
Foo item = reader.read();
assertNull(reader.read());
reader.update(executionContext);

reader.close();

assertEquals(4, item.getFirst());
assertEquals("five", item.getSecond());
assertEquals("six", item.getThird());
assertEquals(2, executionContext.size());
}

@Test(expected = ItemStreamException.class)
public void testStrict() throws Exception {
Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller();
Expand Down