Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 - closing stream on Exception?

Is there a way for Stream to be closed if exception will occur during invocation of any element of the built stream chain?

For example, the code:

    Stream.of(new Object())
            .filter(e -> {
                if (true) throw new IllegalStateException();
                return true;
            })
            .onClose(() -> System.out.println("OnClose"))
            .collect(Collectors.toList());

will produce the following output:

Exception in thread "main" java.lang.IllegalStateException
at my.className.lambda$main$2(LdapRealm.java:114)
at my.className$$Lambda$1/1607521710.test(Unknown Source)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:174)
at java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:419)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at my.className.main(LdapRealm.java:118)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

Note that "OnClose" message was not printed because onClose() haven't been called. Is there any good solution for this problem if I want this stream to be used by third party code and I don't sure if that code will facilitate try/catch+Autocloseable feature?

like image 350
Askar Kalykov Avatar asked Dec 24 '22 23:12

Askar Kalykov


1 Answers

If the user of your class doesn't use try/finally or try-with-resources, you can do absolutely nothing about cleanup. (Except finalizers, which are not a good solution.)

If you have a function that returns the stream

Stream<Object> getStream() {
    return Stream.of(new Object())
        .filter(e -> {
            if (true) throw new IllegalStateException();
            return true;
        })
        .onClose(() -> System.out.println("OnClose"));
}

then the correct usage of this function is

List<Object> result;
try (Stream<Object> s = getStream()) {
    result = s.collect(Collectors.toList());
}
like image 192
Sebastian Redl Avatar answered Dec 27 '22 14:12

Sebastian Redl