experience trying out lambda-8-b74

Zhong Yu zhong.j.yu at gmail.com
Mon Feb 4 15:03:59 PST 2013

On Mon, Feb 4, 2013 at 12:01 PM, Henry Jen <henry.jen at oracle.com> wrote:
> If we don't extend any exception handling or need type information, we don't really need a wrapper as Throwable already has hasCause() method.

UncheckedIOException is a wrapper for IOException. I'm arguing that
JDK should instead have a generic wrapper for Exception, so that all
libraries have a uniformed way of smuggling/unsmuggling checked
exceptions. Otherwise there are serious interoperability obstacles.

It appears that the lambda team does not take checked exceptions
seriously. It might be the right attitude academically, but real world
Java applications are full of checked exceptions. Without a guideline
from Java czars, lots of hacky ways will be invented when they try to
integrate with Stream.

Zhong Yu

> I recall there were discussion of transparent exception handling, which is still an open topic I believe.
> Cheers,
> Henry
> On Feb 2, 2013, at 9:06 AM, Zhong Yu <zhong.j.yu at gmail.com> wrote:
>> Also, what about other checked exceptions? If I make a stream based on
>> JDBC ResultSet, how do I handle SQLExceptions? Should I create a
>> proprietary UncheckedSQLException? Should multiple libraries each
>> provide their own version of UncheckedXxxExceptions for every
>> XxxException? We'll be in this hell for some years to come before the
>> language gives a better device.
>> Meanwhile, why not provide a generic wrapper exception whose explicit
>> and sole purpose is to wrap another checked exception? I know the idea
>> is trivia, but why not?
>> The Wrapper can provide convenience methods like
>>    class Wrapper extends RuntimeException
>>        // if cause is E1, throw cause; otherwise throw wrapper.
>>        <E1> RuntimeException rethrow(Class<E1> type) throws E1, Wrapper
>> so we can
>>    catch(Wrapper w)
>>        throw w.rethrow(IOException.class, SQLException.class);
>> or to handle causes inline
>>    catch(Wrapper w)
>>        w.on(IOException.class, e->{ handle e; })
>>           .on(SQLException.class, e->{ handle e; });
>>    <Ei, Eo> Wrapper on(Class<Ei> type, ExceptionHandler<Ei,Eo>) throws Eo;
>>    interface ExceptionHandler<Ei,Eo>
>>        void handle(Ei e) throws Eo;
>> obviously not elegant, but at least give us something of the sort that
>> can alleviate the pain in the short term.
>> Zhong Yu
>> On Fri, Feb 1, 2013 at 11:38 PM, Peter Levart <peter.levart at gmail.com> wrote:
>>> On 02/02/2013 12:44 AM, Henry Jen wrote:
>>>> On 01/28/2013 12:16 AM, Peter Levart wrote:
>>>>> On 01/28/2013 12:06 AM, Henry Jen wrote:
>>>>>> http://cr.openjdk.java.net/~henryjen/lambda/nio.5/webrev/
>>>>> Hi Henry,
>>>>> I can imagine that many times a single block of code would be
>>>>> responsible for constructing a Path stream (possibly enclosed into a
>>>>> try-with-resources construct) and consuming it's results, so having to
>>>>> deal with the duality of IOException/UncheckedIOException is a
>>>>> complication for a user in my opinion. Wouldn't it be better also for
>>>>> the stream-factory methods to throw UncheckedIOException and for
>>>>> CloseableStream.close() to also throw UncheckedIOException (that means,
>>>>> only inheriting from AutoCloseable, not Closeable and co-variant-ly
>>>>> redefining the throws declaration):
>>>>> public interface CloseableStream<T> extends Stream<T>, AutoCloseable {
>>>>>     @Override
>>>>>     void close() throws UncheckedIOException;
>>>>> }
>>>> Hi Peter,
>>> Hi Henry,
>>>> Sorry for the late reply, I want to let the idea sink a little bit.
>>>> After couple days, I am slightly prefer not to change it because,
>>>> 1) The CloseableStream-factory method throws IOException reminds use of
>>>> try-with-resource better than an unchecked exception.
>>> The *Closeable*Stream method return type name also reminds of that ;-)
>>>> 2) As factory methods throwing IOException, developer is dealing with
>>>> duality already.
>>> He is dealing with duality already *if* the factory methods are throwing
>>> IOException. If they are throwing UncheckedIOException, he is not
>>> dealing with duality.
>>>> 3) If the close method throws UncheckedIOException as the stream
>>>> handling, the suppressing of exceptions will be more confusing. Should
>>>> developer look into cause IOException or the UncheckedIOException?
>>> Do you think a programmer might want to handle different subtypes of
>>> IOException differently? If that is the case, the javadoc should
>>> document all the possible situations. And what about different subtypes
>>> of IOException wrapped by UncheckedIOException while consuming the
>>> stream? If the programmer already bothers to unwrap the unchecked
>>> exception to do the cause analisys, then this same handler would be good
>>> also for dealing with exceptions thrown in factory methods and
>>> CloseableStream.close(). The streams API is a higher-lever wrapper over
>>> the java.nio.file.DirectoryStream API and it is already wrapping the
>>> lower-level IOException with UncheckedIOException when consuming the
>>> CloseableStream. I think it should do it consistently. By doing it
>>> consistently, it simplifies correct exception handling logic in *all*
>>> situations.
>>>> 4) When the implementation is a Closeable, the wrapping of IOException
>>>> into an UncheckedIOException doesn't do any good except overhead in case
>>>> developer want to deal with it. On the other hand, a IOException handler
>>>> is probably in place as the factory methods throws IOException.
>>> It is probably in place *if* the factory methods are throwing
>>> IOException. If they are throwing UncheckedIOException, then such
>>> handler is not there. The question is whether the UncheckedIOException
>>> handler is in place too. If I look in one of your tests:
>>>  148         public void testWalk() {
>>>  149                 try(CloseableStream<Path> s = Files.walk(testFolder)) {
>>>  150                         Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
>>>  151                         assertEquals(actual, all);
>>>  152                 } catch (IOException ioe) {
>>>  153                         fail("Unexpected IOException");
>>>  154                 }
>>>  155         }
>>> You haven't bothered to handle the UncheckedIOException (because the
>>> test would fail anyway if it was thrown). But I'm afraid that average
>>> programmer will walk away from similar codes with false sense of
>>> confidence that he handled all exceptional situations when he put the
>>> checked exception handler in place. I think that being consistent and
>>> throwing UncheckedIOException everywhere would actually have greater
>>> probability for average programmer to not miss the handling of
>>> exceptional situations while consuming the stream - at least all
>>> exceptional situations would be handled or not handled equally.
>>> Regards, Peter
>>>> Does it make sense?
>>>> I updated the webrev to have some test coverage for exception handling,
>>>> it's painful as always, but the duality is not what bothers me.
>>>> http://cr.openjdk.java.net/~henryjen/lambda/nio.6/webrev/
>>>> Cheers,
>>>> Henry

More information about the lambda-dev mailing list