Reputation: 111
I would like to use a Java 8
Stream as a data source for a Spring Batch ItemReader
.
Is there any way to do this?
I am currently using Spring Batch 3.0.7.
Upvotes: 1
Views: 1986
Reputation: 43
If you have a stream as resultType you can also return an IteratorItemReader:
Stream<BigDecimal> stream = repository.getStream();
return new IteratorItemReader<>(stream.iterator());
Upvotes: 3
Reputation: 298203
You could use an adapter method like
public static <T> ItemReader<T> itemReader(BaseStream<? extends T,?> stream) {
Spliterator<? extends T> source = stream.spliterator();
List<T> container = new ArrayList<>(1);
return () -> source.tryAdvance(container::add)? container.remove(0): null;
}
which also handles primitive streams, e.g.
for(ItemReader<Integer> r = itemReader(IntStream.range(0, 10));;) {
Integer i = r.read();
if(i == null) break;
System.out.println(i);
}
But care must be taken not to have null
elements in the stream when using a reference type stream, as null
references returned by the ItemReader
are interpreted as end marker.
An alternative is to throw an exception when encountering a null
reference in the stream:
public static <T> ItemReader<T> itemReader(BaseStream<? extends T,?> stream) {
Spliterator<? extends T> source = stream.spliterator();
List<T> container = new ArrayList<>(1);
if(source.hasCharacteristics(Spliterator.NONNULL))
return () -> source.tryAdvance(container::add)? container.remove(0): null;
else
return () -> source.tryAdvance(container::add)?
Objects.requireNonNull(container.remove(0)): null;
}
Upvotes: 2