experience trying out lambda-8-b74

Zhong Yu zhong.j.yu at gmail.com
Mon Feb 4 20:00:11 PST 2013


On Mon, Feb 4, 2013 at 9:48 PM, Zhong Yu <zhong.j.yu at gmail.com> wrote:
> On Mon, Feb 4, 2013 at 8:45 PM, Ricky Clarkson <ricky.clarkson at gmail.com> wrote:
>> "And there's nothing harmful
>> to make a more general UncheckedAnyException, instead of just
>> UncheckedIOException."
>>
>> What's wrong with RuntimeException for that?
>
> We cannot unambiguously determine whether a RuntimeException e1 is a
> simple wrapper of an checked exception e2 for the purpose of smuggling
> e2 across a method that doesn't throw checked exception, or an
> ordinary exception that represents an erroneous condition by itself.
>
> We had a similar discussion on Doug Lea's CompletableFuture.
> Originally it used RuntimeException to smuggle checked exceptions. It
> was then changed to use a specific "CompletionException" for the

see http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/CompletableFuture.java?revision=1.36&view=markup

search "instanceof CompletionException"

Apparently CompletionException is just a shell; it's discarded
whenever not needed; it doesn't carry meaning of app error by itself.

> purpose. My fear is that each library will invent its own wrapper
> exception for the purpose. Why not have an official wrapper?
>
>> On Mon, Feb 4, 2013 at 8:32 PM, Zhong Yu <zhong.j.yu at gmail.com> wrote:
>>>
>>> On Mon, Feb 4, 2013 at 5:11 PM, Brian Goetz <brian.goetz at oracle.com>
>>> wrote:
>>> > I knew it wouldn't be long before this turned into yet another
>>> > barely-laundered proposal to try yet again to get us to deprecate
>>> > checked
>>> > exceptions.  I get it, you find checked exceptions frustrating.
>>> > Sometimes I
>>> > do too.  But we still believe a world without them would be worse, and
>>> > we're
>>> > not interested in pushing people towards that.
>>>
>>> I neither hate or love checked exceptions; they are here, they are
>>> widely used by Java applications, so we must deal with it.
>>>
>>> > There are places in the Java libraries -- mostly from the very early
>>> > days --
>>> > where the use of checked exceptions turned out to be a mistake.  (An
>>> > obvious
>>> > example is close() throwing IOException -- what could a user possibly do
>>> > to
>>> > recover from that?)  The workarounds we're doing here are to mitigate
>>> > the
>>>
>>> (digression - failure of close() is real and is important; at least
>>> app can tell the user that the file can't be saved, instead of
>>> assuming otherwise)
>>>
>>> > worst mistakes of the past, not to rewrite history.  And we're satisfied
>>> > that this small workaround handles 90% of the 2% of cases where
>>> > exceptions
>>> > turn out to intrude in lambda libraries.  So we've made the decision to
>>> > stop
>>> > there for now, and not because it didn't occur to us to go farther.
>>>
>>> I don't quite get it - are you saying that IOException is the 90% of
>>> the checked exceptions, so UncheckedIOException is good enough,
>>> instead of a more generic wrapper for arbitrary Exception.
>>>
>>> I don't think IOException is that special. And there's nothing harmful
>>> to make a more general UncheckedAnyException, instead of just
>>> UncheckedIOException.
>>>
>>> >
>>> >
>>> > On 2/4/2013 6:03 PM, Zhong Yu wrote:
>>> >>
>>> >> 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