Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 6364794
Votes 0
Synopsis Callable/Future interfaces awkward w.r.t. checked exceptions
Category java:classes_util_concurrent
Reported Against
Release Fixed
State 5-Cause Known, request for enhancement
Priority: 4-Low
Related Bugs
Submit Date 19-DEC-2005
Description
The Callable and Future interfaces, and their usage in ExecutorService, are a bit awkward to use since they assume that the body of the code can throw arbitrary Exception (when that is usually not the case); when using a Future you have to pick apart the ExecutionException and deal with it somehow, maybe trying to cast it to various subtypes. This is not very pleasant.

I am attaching a runnable prototype (NetBeans project format, should run in 5.0 anyway) of enhanced interfaces that deal with checked exceptions more gracefully, by introducing a type parameter for an exception type. A quick summary for those who do not want to open the attachment:

public interface XCallable<V, E extends Exception> {
    V call() throws E;
}

public interface XFuture<V, E extends Exception> {
    V get() throws InterruptedException, E;
    V get(long timeout, TimeUnit unit) throws InterruptedException, E, TimeoutException;
    // etc.
}

Basic usage something like:

XFuture<String,IOException> f = executorService.submit(new XCallable<String,IOException>() {
    public String call() throws IOException {
        // ...
    }
});
// ...
try {
    String v = f.get();
} catch (IOException e) {
    // ...
}

The working code should speak for itself as far as the details are concerned. Suggest that something like this could be made part of the j.u.concurrent.* APIs as a convenience, since it is not trivial to write your own (look at Bridge.java to see what I mean).

Some notes:

1. I found that using java.lang.Void was very handy as a type parameter for Callable/Future when you expect the body to return null. It forces the body to really return null (nothing else is assignable to this "type"), and the "Void" is visually reminiscent of the "void" you would use for a non-generified interface, so it is pretty clear to read - better Future<Void> than Future<?>, IMHO.

2. The type parameter for the enhanced interfaces can be RuntimeException if you do not except any checked exceptions to be thrown, and the compiler works as expected in this case (does not require anything to be caught, beyond the mandatory InterruptedException and if applicable TimeoutException).

3. If your body would throw more than one checked exception (e.g. IOException and SAXException for anything doing XML parsing), then the enhanced interfaces would not help you any (unless of course interfaces with multiple Exception type parameters were introduced). But I think this case is relatively uncommon.

4. Code in Bridge.java assumes that any Throwable caught will either be an Error or an Exception.
Posted Date : 2005-12-19 02:36:01.0
Work Around
N/A
Evaluation
Doug:

"We once discussed having Callable defined along the lines of the
suggestion in the RFE...

public interface XCallable<V, E extends Exception> {
     V call() throws E;
}

But decided not to do it. Does anyone remember why?"

Joe:

>The Callable and Future interfaces, and their usage in ExecutorService,
>> are a bit awkward to use since they assume that the body of the code
>> can throw arbitrary Exception (when that is usually not the case)

But it *is* usually the case... (Or at least it's often not possible
to assume it's *not* the case.)


Josh:

"My guess is that the reason we didn't do it is that throws and generics don't mix well.  The problem is that you have to declare the type that is thrown, which is frequently a disjunctive type, and Java provides now way of declaring such types.  So you end up throwing the least common ancestor of all the exceptions that could be thrown, which is typically Exception, which is useless. "

Brian:

"Josh and I were discussing this recently and while neither of us 
remembered why, I think it is because when a method throws one 
exception, it might just as easily throw two, and there's no way to 
express "throws IOException and SQLException" in a generic way."

Martin:

Looks like another Will Not Fix
Posted Date : 2006-02-04 01:52:13.0

Jesse:

It's true that you can only use the new interfaces if only one kind of 
exception is thrown. My guess was simply that *most* bodies run would be 
smallish and either throw no checked exceptions at all (my #2) or just 
one kind of checked exception - i.e. that multiple checked exceptions 
coalescing to j.l.Exception would be the less usual case. But this is 
just a guess - someone with access to a large and diverse body of real 
code using these interfaces would be better equipped to tell. My 
experience is limited to using homegrown concurrency utilities in 
NetBeans, where the great majority of such code blocks either throw 
nothing or IOException, and where having to always catch and ignore 
Exception would be unpleasant.

Doug:

I don't disagree that this would sometimes be useful. The trouble
is that you can't nicely have two forms of Callable etc everywhere,
and the way we have it is a bit more conservative, if sometimes more
annoying.

Jesse:

Yes, that is true. Might have been nicer to have Callable be XCallable 
to begin with since XCallable<T,Exception> ~ Callable<T>. But no matter.
Posted Date : 2006-02-12 00:51:04.0
Comments
  
  Include a link with my name & email   


PLEASE NOTE: JDK6 is formerly known as Project Mustang