Skip to content

Commit bebde26

Browse files
garyrussellartembilan
authored andcommitted
INT-4506: Splitter: close stream and Closeables
JIRA: https://jira.spring.io/browse/INT-4506 Capture the actual splitter result in the `FunctionIterator and close it if necessary. **cherry-pick to 5.0.x** Add Closeable to proxy in test; remove AutoCloseable check. Closeable extends AutoCloseable. Fix javadocs; test for AutoCloseable instead of Closeable Polishing - PR comments; tighten up API. A `CloseableIterator` is now an `AutoCloseable` with an overridden `close()`` (no exception) to avoid lint problem. * Polishing omissions, code style and `@author` **Cherry-pick to 5.0.x**
1 parent 0d0605b commit bebde26

File tree

5 files changed

+153
-55
lines changed

5 files changed

+153
-55
lines changed

spring-integration-core/src/main/java/org/springframework/integration/splitter/AbstractMessageSplitter.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package org.springframework.integration.splitter;
1818

19-
import java.io.Closeable;
2019
import java.util.Arrays;
2120
import java.util.Collection;
2221
import java.util.Collections;
@@ -44,6 +43,7 @@
4443
* @author Dave Syer
4544
* @author Artem Bilan
4645
* @author Ruslan Stelmachenko
46+
* @author Gary Russell
4747
*/
4848
public abstract class AbstractMessageSplitter extends AbstractReplyProducingMessageHandler {
4949

@@ -155,7 +155,8 @@ else if (result instanceof Publisher<?>) {
155155
return flux.map(messageBuilderFunction);
156156
}
157157
else {
158-
return new FunctionIterator<>(iterator, messageBuilderFunction);
158+
return new FunctionIterator<>(result instanceof AutoCloseable && !result.equals(iterator)
159+
? (AutoCloseable) result : null, iterator, messageBuilderFunction);
159160
}
160161
}
161162

@@ -235,9 +236,9 @@ protected void produceOutput(Object result, Message<?> requestMessage) {
235236
}
236237
}
237238
finally {
238-
if (iterator instanceof Closeable) {
239+
if (iterator instanceof AutoCloseable) {
239240
try {
240-
((Closeable) iterator).close();
241+
((AutoCloseable) iterator).close();
241242
}
242243
catch (Exception e) {
243244
// ignored

spring-integration-core/src/main/java/org/springframework/integration/util/CloseableIterator.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,20 @@
1616

1717
package org.springframework.integration.util;
1818

19-
import java.io.Closeable;
2019
import java.util.Iterator;
2120

2221
/**
2322
* A {@link CloseableIterator} is intended to be used when it may hold resources (such as file or socket handles).
2423
* This allows implementations to clean up any resources they need to keep open to iterate over elements.
2524
*
2625
* @author Ruslan Stelmachenko
26+
* @author Gary Russell
2727
*
2828
* @since 4.3.15
2929
*/
30-
public interface CloseableIterator<E> extends Iterator<E>, Closeable {
30+
public interface CloseableIterator<E> extends Iterator<E>, AutoCloseable {
31+
32+
@Override
33+
void close(); // override throws Exception
34+
3135
}

spring-integration-core/src/main/java/org/springframework/integration/util/FunctionIterator.java

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,72 @@
1616

1717
package org.springframework.integration.util;
1818

19-
import java.io.Closeable;
20-
import java.io.IOException;
2119
import java.util.Iterator;
2220
import java.util.function.Function;
2321

22+
import org.springframework.lang.Nullable;
23+
2424
/**
2525
* An {@link Iterator} implementation to convert each item from the target
2626
* {@link #iterator} to a new object applying the {@link #function} on {@link #next()}.
2727
*
2828
* @author Artem Bilan
2929
* @author Ruslan Stelmachenko
30+
* @author Gary Russell
3031
* @since 4.1
3132
*/
3233
public class FunctionIterator<T, V> implements CloseableIterator<V> {
3334

35+
private final AutoCloseable closeable;
36+
3437
private final Iterator<T> iterator;
3538

3639
private final Function<? super T, ? extends V> function;
3740

41+
/**
42+
* Construct an instance with the provided iterable and function.
43+
* @param iterable the iterable.
44+
* @param function the function.
45+
*/
3846
public FunctionIterator(Iterable<T> iterable, Function<? super T, ? extends V> function) {
39-
this(iterable.iterator(), function);
47+
this(null, iterable.iterator(), function);
48+
}
49+
50+
/**
51+
* Construct an instance with the provided root object, iterable and function.
52+
* @param closeable an {@link AutoCloseable} to close when iteration is complete.
53+
* @param iterable the iterable.
54+
* @param function the function.
55+
* @since 5.0.7
56+
*/
57+
public FunctionIterator(@Nullable AutoCloseable closeable, Iterable<T> iterable,
58+
Function<? super T, ? extends V> function) {
59+
60+
this(closeable, iterable.iterator(), function);
4061
}
4162

63+
/**
64+
* Construct an instance with the provided iterator and function.
65+
* @param newIterator the iterator.
66+
* @param function the function.
67+
*/
4268
public FunctionIterator(Iterator<T> newIterator, Function<? super T, ? extends V> function) {
43-
this.iterator = newIterator;
44-
this.function = function;
69+
this(null, newIterator, function);
4570
}
4671

47-
@Override
48-
public void remove() {
49-
throw new UnsupportedOperationException("Cannot remove from a collect iterator");
72+
/**
73+
* Construct an instance with the provided root object, iterator and function.
74+
* @param closeable an {@link AutoCloseable} to close when iteration is complete.
75+
* @param newIterator the iterator.
76+
* @param function the function.
77+
* @since 5.0.7
78+
*/
79+
public FunctionIterator(@Nullable AutoCloseable closeable, Iterator<T> newIterator,
80+
Function<? super T, ? extends V> function) {
81+
82+
this.closeable = closeable;
83+
this.iterator = newIterator;
84+
this.function = function;
5085
}
5186

5287
@Override
@@ -60,9 +95,22 @@ public V next() {
6095
}
6196

6297
@Override
63-
public void close() throws IOException {
64-
if (this.iterator instanceof Closeable) {
65-
((Closeable) this.iterator).close();
98+
public void close() {
99+
if (this.iterator instanceof AutoCloseable) {
100+
try {
101+
((AutoCloseable) this.iterator).close();
102+
}
103+
catch (Exception e) {
104+
// NOSONAR
105+
}
106+
}
107+
if (this.closeable != null) {
108+
try {
109+
this.closeable.close();
110+
}
111+
catch (Exception e) {
112+
// NOSONAR
113+
}
66114
}
67115
}
68116

0 commit comments

Comments
 (0)