Skip to content

Commit 21bc4d5

Browse files
committed
Allow StaxEventItemReader to auto-detect the input file encoding
Before this commit, it was not possible to pass a null encoding to the StaxEventItemReader, which prevents the XML event reader to auto-detect the file encoding. This commits makes the encoding setter more lenient by accepting a null value. Resolves #4101
1 parent ec161f8 commit 21bc4d5

File tree

3 files changed

+49
-9
lines changed

3 files changed

+49
-9
lines changed

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2022 the original author or authors.
2+
* Copyright 2006-2023 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.
@@ -142,10 +142,10 @@ public void setXmlInputFactory(XMLInputFactory xmlInputFactory) {
142142

143143
/**
144144
* Set encoding to be used for the input file. Defaults to {@link #DEFAULT_ENCODING}.
145-
* @param encoding the encoding to be used
145+
* @param encoding the encoding to be used. Can be {@code null}, in which case, the
146+
* XML event reader will attempt to auto-detect the encoding from tht input file.
146147
*/
147-
public void setEncoding(String encoding) {
148-
Assert.notNull(encoding, "The encoding must not be null");
148+
public void setEncoding(@Nullable String encoding) {
149149
this.encoding = encoding;
150150
}
151151

@@ -239,7 +239,8 @@ protected void doOpen() throws Exception {
239239
}
240240

241241
inputStream = resource.getInputStream();
242-
eventReader = xmlInputFactory.createXMLEventReader(inputStream, this.encoding);
242+
eventReader = this.encoding != null ? xmlInputFactory.createXMLEventReader(inputStream, this.encoding)
243+
: xmlInputFactory.createXMLEventReader(inputStream);
243244
fragmentReader = new DefaultFragmentEventReader(eventReader);
244245
noInput = false;
245246

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2020 the original author or authors.
2+
* Copyright 2017-2023 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.
@@ -26,6 +26,7 @@
2626

2727
import org.springframework.batch.item.xml.StaxEventItemReader;
2828
import org.springframework.core.io.Resource;
29+
import org.springframework.lang.Nullable;
2930
import org.springframework.oxm.Unmarshaller;
3031
import org.springframework.util.Assert;
3132
import org.springframework.util.StringUtils;
@@ -194,12 +195,13 @@ public StaxEventItemReaderBuilder<T> xmlInputFactory(XMLInputFactory xmlInputFac
194195

195196
/**
196197
* Encoding for the input file. Defaults to
197-
* {@link StaxEventItemReader#DEFAULT_ENCODING}.
198+
* {@link StaxEventItemReader#DEFAULT_ENCODING}. Can be {@code null}, in which case
199+
* the XML event reader will attempt to auto-detect the encoding from tht input file.
198200
* @param encoding String encoding algorithm
199201
* @return the current instance of the builder
200202
* @see StaxEventItemReader#setEncoding(String)
201203
*/
202-
public StaxEventItemReaderBuilder<T> encoding(String encoding) {
204+
public StaxEventItemReaderBuilder<T> encoding(@Nullable String encoding) {
203205
this.encoding = encoding;
204206

205207
return this;

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

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2022 the original author or authors.
2+
* Copyright 2008-2023 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.
@@ -19,6 +19,7 @@
1919
import org.hamcrest.Matchers;
2020
import org.junit.jupiter.api.BeforeEach;
2121
import org.junit.jupiter.api.Test;
22+
2223
import org.springframework.batch.item.ExecutionContext;
2324
import org.springframework.batch.item.ItemCountAware;
2425
import org.springframework.batch.item.ItemStreamException;
@@ -36,8 +37,10 @@
3637
import javax.xml.namespace.QName;
3738
import javax.xml.stream.FactoryConfigurationError;
3839
import javax.xml.stream.XMLEventReader;
40+
import javax.xml.stream.XMLInputFactory;
3941
import javax.xml.stream.XMLStreamException;
4042
import javax.xml.stream.events.EndElement;
43+
import javax.xml.stream.events.StartDocument;
4144
import javax.xml.stream.events.StartElement;
4245
import javax.xml.stream.events.XMLEvent;
4346
import javax.xml.transform.Source;
@@ -58,6 +61,9 @@
5861
import static org.junit.jupiter.api.Assertions.assertSame;
5962
import static org.junit.jupiter.api.Assertions.assertThrows;
6063
import static org.junit.jupiter.api.Assertions.assertTrue;
64+
import static org.mockito.Mockito.mock;
65+
import static org.mockito.Mockito.verify;
66+
import static org.mockito.Mockito.when;
6167

6268
/**
6369
* Tests for {@link StaxEventItemReader}.
@@ -159,6 +165,37 @@ void testCustomEncoding() throws Exception {
159165
source.close();
160166
}
161167

168+
@Test
169+
void testNullEncoding() throws Exception {
170+
// given
171+
XMLEventReader eventReader = mock(XMLEventReader.class);
172+
when(eventReader.peek()).thenReturn(mock(StartDocument.class));
173+
174+
Resource resource = mock(Resource.class);
175+
InputStream inputStream = mock(InputStream.class);
176+
when(resource.getInputStream()).thenReturn(inputStream);
177+
when(resource.isReadable()).thenReturn(true);
178+
when(resource.exists()).thenReturn(true);
179+
XMLInputFactory xmlInputFactory = mock(XMLInputFactory.class);
180+
when(xmlInputFactory.createXMLEventReader(inputStream)).thenReturn(eventReader);
181+
182+
StaxEventItemReader<Object> reader = new StaxEventItemReader<>();
183+
reader.setUnmarshaller(new MockFragmentUnmarshaller());
184+
reader.setFragmentRootElementName(FRAGMENT_ROOT_ELEMENT);
185+
reader.setResource(resource);
186+
reader.setEncoding(null);
187+
reader.setStrict(false);
188+
reader.setXmlInputFactory(xmlInputFactory);
189+
reader.afterPropertiesSet();
190+
191+
// when
192+
reader.open(new ExecutionContext());
193+
194+
// then
195+
verify(xmlInputFactory).createXMLEventReader(inputStream);
196+
reader.close();
197+
}
198+
162199
@Test
163200
void testItemCountAwareFragment() throws Exception {
164201
StaxEventItemReader<ItemCountAwareFragment> source = createNewItemCountAwareInputSource();

0 commit comments

Comments
 (0)