user7981386
user7981386

Reputation: 111

Java 8 Stream as data source for Spring Batch ItemReader

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

Answers (2)

Hafsa Ch
Hafsa Ch

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

Holger
Holger

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

Related Questions