Add encoding parameter in StaxEventItemReader

Resolves #807
This commit is contained in:
Mahmoud Ben Hassine
2019-09-30 11:17:32 +02:00
committed by Mahmoud Ben Hassine
parent a88b074c8d
commit 2952e9a039
4 changed files with 98 additions and 5 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2019 the original author or authors.
* Copyright 2006-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.batch.item.xml;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
@@ -62,6 +63,8 @@ ResourceAwareItemReaderItemStream<T>, InitializingBean {
private static final Log logger = LogFactory.getLog(StaxEventItemReader.class);
public static final String DEFAULT_ENCODING = Charset.defaultCharset().name();
private FragmentEventReader fragmentReader;
private XMLEventReader eventReader;
@@ -80,6 +83,8 @@ ResourceAwareItemReaderItemStream<T>, InitializingBean {
private XMLInputFactory xmlInputFactory = StaxUtils.createXmlInputFactory();
private String encoding = DEFAULT_ENCODING;
public StaxEventItemReader() {
setName(ClassUtils.getShortName(StaxEventItemReader.class));
}
@@ -131,6 +136,16 @@ ResourceAwareItemReaderItemStream<T>, InitializingBean {
this.xmlInputFactory = xmlInputFactory;
}
/**
* Set encoding to be used for the input file. Defaults to {@link #DEFAULT_ENCODING}.
*
* @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.
*
@@ -221,7 +236,7 @@ ResourceAwareItemReaderItemStream<T>, InitializingBean {
}
inputStream = resource.getInputStream();
eventReader = xmlInputFactory.createXMLEventReader(inputStream);
eventReader = xmlInputFactory.createXMLEventReader(inputStream, this.encoding);
fragmentReader = new DefaultFragmentEventReader(eventReader);
noInput = false;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017-2019 the original author or authors.
* Copyright 2017-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@ import org.springframework.util.StringUtils;
*
* @author Michael Minella
* @author Glenn Renfro
* @author Mahmoud Ben Hassine
* @since 4.0
*/
public class StaxEventItemReaderBuilder<T> {
@@ -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}
@@ -193,6 +196,19 @@ public class StaxEventItemReaderBuilder<T> {
return this;
}
/**
* Encoding for the input file. Defaults to {@link StaxEventItemReader#DEFAULT_ENCODING}.
*
* @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}
*
@@ -222,6 +238,7 @@ public class StaxEventItemReaderBuilder<T> {
reader.setCurrentItemCount(this.currentItemCount);
reader.setMaxItemCount(this.maxItemCount);
reader.setXmlInputFactory(this.xmlInputFactory);
reader.setEncoding(this.encoding);
return reader;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2008-2019 the original author or authors.
* Copyright 2008-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,6 +43,9 @@ import javax.xml.transform.Source;
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;
@@ -146,6 +149,26 @@ public class StaxEventItemReaderTests {
source.close();
}
/**
* Regular usage scenario with custom encoding.
*/
@Test
public void testCustomEncoding() throws Exception {
Charset encoding = StandardCharsets.ISO_8859_1;
ByteBuffer xmlResource = encoding.encode(xml);
source.setResource(new ByteArrayResource(xmlResource.array()));
source.setEncoding(encoding.name());
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();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017-2019 the original author or authors.
* Copyright 2017-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,6 +15,9 @@
*/
package org.springframework.batch.item.xml.builder;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.stream.XMLInputFactory;
@@ -116,6 +119,41 @@ public class StaxEventItemReaderBuilderTests {
assertEquals(2, executionContext.size());
}
@Test
public void testCustomEncoding() throws Exception {
Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller();
unmarshaller.setClassesToBeBound(Foo.class);
Charset charset = StandardCharsets.ISO_8859_1;
ByteBuffer xml = charset.encode(SIMPLE_XML);
StaxEventItemReader<Foo> reader = new StaxEventItemReaderBuilder<Foo>()
.name("fooReader")
.resource(new ByteArrayResource(xml.array()))
.encoding(charset.name())
.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();