|
Comments
|
Submitted On 21-MAY-1999
seibel
[Note: this comment was originally sent via email
to some individuals at Javasoft. Hopefully they
won't mind me posting it again here.]
I'd like to respectfully disagree with both the
claim that this is not a frequently encountered
problem and with the fear that the proposed
addition to Throwable would be creeping featurism.
There are a number of reasons that building the
concept of nested exceptions into Throwable would
be a good idea:
* Refactoring and Standardization *
Lots of folks need this functionality. Since
they don't get it from Throwable they are forced
to write it into their own exception classes
leading to code duplication and differences in
implementation. Just looking at the JDK and
standard extensions we see several examples:
java.sql.SQLException
java.lang.reflect.InvocationTargetException
java.lang.ExceptionInInitializerError
java.rmi.RemoteException
javax.naming.NamingException
These classes vary in how the nested exception
is passed in: some via constructor, some by a
setter; the name of the method to get the nested
exception: getNextException(),
getTargetException(), getException(),
getRootCause(), and even a public field; and,
finally, what printStackTrace() does with the
nested exception: many include an apparently
cut-n-pasted swatch of code to print out the
name of the exception and the nested execption's
stack trace if there is a nested exception.
Others print both stack traces (which seems the
most useful to me) and others don't print it at
all. Clearly there is a bunch of duplicated
functionality that could be refactored and
standardized by moving nesting into Throwable.
(This lack of factoring has already hurt you;
see bugs 4086279 and 4019376.) And that's just
in the JDK--every organization that I know of
that does serious Java programming pretty soon
runs into the need for nested exceptions and
starts sprinkling the code for it throughout
their system or writes their own top-level
exception (e.g. the TOPLinkException mentioned
in the RFE). At WebLogic, we found that we
needed nested exceptions so often that we went
the route of a common base class. But it
distorts our exception hierarchy to have a class
that everything extends just for code sharing.
And we still don't get a consistent interface
since we obviously don't control all the
exception classes we use.
* It allows for clean abstractions without
losing information *
One of the important (perhaps even fundamental)
ideas, it seems to me, behind exceptions is that
they are way to pass failure information across
levels of abstraction. That is, a lower-level
piece of code can indicate that something failed
without having to decide what to do about it.
But when abstractions are layered, without
nested exceptions, we run into a problem of
which layer's info to pass on. For example if my
application is using some storage API and a
particular implementation of that API uses a
networking API to store stuff on remote machines
then things could go wrong for my app at both
the storage and the network layer. Suppose my
app is responsible for initializing both the
storage subsystem and the networking layer. When
I go to use the storage API things could fail at
either the storage API level or the networking
level and in either case I need to either try to
recover or at least give a meaningful error
message about what's not configured properly.
Presumably the storage API will translate
networking exceptions into storage exceptions
(because it's not part of the storage
abstraction to throw network exceptions) but
that means that without nested exceptions I have
no good way of finding out what really went
wrong if it was a networking problem. If the
author of the storage API thought of this then
he or she could have made the storage-API's
exceptions handle nesting but then we're back to
Submitted On 21-MAY-1999
adam@organic.com
Every Java project I've worked on has implemented
its own nested exception. Since this seems to be
a common need, it would be nice if everyone didn't
have to re-invent the wheel here.
Additionally every project I've worked on has also
implemented a static method to stringify a
stacktrace. It would also be nice if there were
a good way to get this from the Throwable base
class.
Submitted On 15-AUG-1999
tbreuel
The creeping featurism is a result of requiring
exception declarations in Java. If you want
to simplify the language, just drop exception
declarations altogether, like most other
languages with exceptions have done (a
backwards compatible change). Otherwise, it seems
to me you should add better support for nested
exceptions, as well as making exceptions part
of any future genericity mechanism.
Submitted On 12-OCT-1999
MPocock
The stack traces should work something like this. If Throwable A is thrown, and
then wrapped in Throwable B, a call to A.printStackTrace() should do what it
always would have done - list the stack for that Throwable. If you call
B.printStackTrace() it should print out the message for A, A's stack trace down
to where it was caught, a message like " rethrown ", B's message and
B's stack trace from then down.
i.e.
A.printStackTrace()
BadException: Something went realy wrong
place1
place2
place3
Main
B.printStackTrace()
BadException: Something went realy wrong
place1
place2
Rethrown by ExpectedException: I noticed something wrong
place3
Main
Submitted On 10-DEC-1999
william.connor
The Federated Management Architecture Java
extension introduces an interface named
ComppositeThrowable to handle nested throwables.
It handles not just chains of throwables, but
trees of throwables, which we found neccessary
when a throwable was thrown for multiple reasons,
as is common in retry situations. Composite
throwable also does the following:
- captures stack traces during remote operations.
- uses localizable messages rather than strings.
The specification for CompositeThrowable may be
found in the FMA Specification at
http://java.sun.com/aboutJava/communityprocess/review/jsr009/index.html
Submitted On 05-JAN-2000
jglick
I'm not sure what the best solution would be but something really seems to be
needed.
I also have seen numerous (re-)implementations of nested exceptions, none of
them
of course interoperable with anyone else's code, especially that in the Java
platform.
E.g. look at the following code from 1.2.2 Beans.instantiate and think about
how you
would go about debugging things when a needed class' constructor threw a
NullPointerException
(note that no stack trace will be available):
try {
result = cl.newInstance();
} catch (Exception ex) {
// We have to remap the exception to one in our signature.
// But we pass extra information in the detail message.
throw new ClassNotFoundException("" + cl + " : " +
ex);
}
Submitted On 24-JAN-2000
MiguelM
Even if this only happens to sophisticated users, that's because they are the
ones who
know how to write maintainable code. I encountered this when adding a
third-party
spelling checker. I encapsulated all of the third-party code into a single
class. This allows
me to change to a different spell-checker in the future, without having to
rewrite a bunch
of classes. However, my encapsulating class can't throw any third-party
exceptions, or
the encapsulation will get broken. I handle this by wrapping my exception into
a custom
exception wrapper. It would be very nice to have this functionality in a single
class. Even
if you don't put this feature into Throwable, (which would be my preference),
you could
make a single wrapping exception which provides this functionality.
Submitted On 26-FEB-2000
Diekhans
This is an essentially feature if one is to implement robust
error handling in a simple way. Without providing some
complex framework outside of
the standard java error handling, one is forced to discard
information
that maybe critical to understanding a bug. This is the
cause of the
classic frustrating class of error messages where one gets
either `can not open foo' or `permission denied'' when one
needs both pieces of
information to understand what occured. While we base all
of our errors
on a set of classes that have an associated causing
exceptions, we
still run into problems with other packages not having such
a mechanism.
The proliferation of stadard java exceptions that implement
this mechanism
demostrates its importance. RemoteException,
ServletException,
SQLException, ExceptionInInitializerError, and
InvocationTargetException
all implement this in incompatbile ways. The fix is trivial
and the
value of not discarding error information huge. Please add
this
ASAP. Robust applications come from desiging in error
handling.
Help us write robust applications.
Submitted On 15-JUN-2000
ljnelson
I'd like to add my voice to those chiming for a
CompositeThrowable class. Here is a sketch at the way I'd
personally like to have it implemented:
public interface ThrowableContainer {
public Throwable getThrowable();
}
public class CompositeThrowable extends Throwable
implements ThrowableContainer {
// blah blah blah
private final Throwable contained;
public CompositeThrowable(Throwable t, String msg) {
super(msg);
this.contained = t;
}
public Throwable getThrowable() {
return this.contained;
}
}
Additionally another class, call it ThrowableUtilities (or
perhaps just a static method on CompositeThrowable or
something) should provide for extracting the String
representation of a stack trace. The String representation
of a stack trace of a CompositeThrowable should reflect all
stack traces that are available.
Submitted On 21-JUL-2000
pnkfelix
I think this RFE in general demonstrates how poorly
Exceptions are used in most parts of the Java class
libraries.
I personally don't know how necessary it is to make all
Throwables support nested exceptions...seibel said the
following:
JD: Well, I don't know about how useful that would be but I
guess you couldn't even do it without some help from
Throwable. You're
right. Let's do it...
I personally don't see why "you couldn't even do it without
some help from Throwable"... if you're designing your
Exceptions and you see a good chance that you're going to
have to deal with subExceptions, then you can add the data
and accessors to your Exception itself. The code I write
doesn't catch "Throwable", it catches specific Exception
types.
But, I suppose adding an additional method
"getSubException()" that just returns null in its default
implementations wouldn't be a bad idea.
That being said, I'm going to reiterate that the majority of
Exceptions in the JDK *do* seem to cop out in terms of
design and don't include half of the information that they
should... Why *doesn't* ClassCastException include the
castTo/castFrom fields? That just seems too logical! Why
do all the methods in java.io.* just say "throws
IOException" instead of specifying the subset of IOException
that actually might be thrown? Why doesn't
FileNotFoundException have a field with the String/File for
the file that we were attempting to find? Why AREN'T we
giving the application the information it needs to properly
recover from an error situation?
So, I guess what I'd fight for here would be for Sun to
revamp the designs they've put in for the majority* of their
Exception classes. I can see that you all are fighting for
a useful design addition for many exception types, but let's
not overlook the possibility for even more improvement in
this regard...
*I'll forgive them for not enhancing NullPointerException
C;)
Submitted On 15-SEP-2000
eblake
This feature could fix other problems. For example, it is
possible to write code that allows checked exceptions to
escape unchecked (which seems highly illegal according to
the JLS) by exploiting a hole in Class.newInstance().
import java.lang.reflect.*;
class ExceptionProblem {
public static void main(String[] args) {
try {
ExceptionProblem.class.getConstructor(null).newInstance(null);
} catch (InstantiationException e1) {
} catch (IllegalAccessException e2) {
} catch (InvocationTargetException e3) {
System.out.println("Notice that we trapped the
exception " +
e3.getTargetException());
} catch (NoSuchMethodException e4) {
} catch (RuntimeException e5) {
} catch (Error e6) {
}
try {
ExceptionProblem.class.newInstance();
} catch (InstantiationException e1) {
} catch (IllegalAccessException e2) {
} catch (RuntimeException e3) {
} catch (Error e4) {
}
System.out.println("Since all declared checked
exceptions and all unchecked
exceptions were caught by the prior try-catch block, this
should be printed.");
}
public ExceptionProblem() throws MyException {
throw new MyException("My exception must be caught, as
it is checked.");
}
}
class MyException extends Exception {
MyException(String msg) { super(msg); }
}
/* Produces the following output:
Notice that we trapped the exception MyException: My
exception must be caught,
as it is checked.
Exception in thread "main" MyException: My exception must be
caught, as it is
checked.
at java.lang.Throwable.<init>(Throwable.java:96)
at java.lang.Exception.<init>(Exception.java:44)
at MyException.<init>(ExceptionProblem.java:31)
at ExceptionProblem.<init>(ExceptionProblem.java:26)
at java.lang.Class.newInstance0(Native Method)
at java.lang.Class.newInstance(Class.java:254)
at ExceptionProblem.main(ExceptionProblem.java:16)
*/
It would be nice if Class.newInstance() behaved more like
Constructor.newInstance, wrapping any exception that occurs
in an easy-to-obtain format, and ensuring that no checked
exceptions escape out of a try block or method declaration.
Submitted On 28-FEB-2001
rfwan
> I could be wrong, but I suspect this happens mostly to
> sophisticated users, and
> is NOT all that frequent relative to all users of Java.
How about a method called by a Servlet which tries
to persist to the database and gets a SQL Exception
but is only allowed to throw an IOException, that sounds
fairly common.
> I doubt if adding this
> either as a special class or (worse) by modifying
> Throwable is justified.
the modification is short and breaks no code:
public Throwable getNestedThrowable(){return null;}
subclasses can then override the method if they need to.
> It just seems like creeping featurism.
but it is a required feature of so many exceptions that
it makes sense to make it available at the root rather
than have inconsistent implementations and naming
conventions. Take for example, ExceptionInInitializerError,
SAXException, InvocationTargetException, Class.newInstance,
SQLException. IOException should also have this
functionality but it does not. Placing the functionality
in Throwable will remove the burden from all the subclasses
to implement nested exception capability.
Submitted On 19-JUL-2001
auinger
Submitted Feb 08, 1999 and it's NOW in JDK1.4 beta..
Why did it take SO LONG???!!
Submitted On 04-MAR-2002
jqb
I'm glad to see this feature made it, but this comment
"xxxxx@xxxxx 1999-02-12
I could be wrong, but I suspect this happens mostly to sophisticated users,
and
is NOT all that frequent relative to all users of Java. I doubt if adding this
either as a special class or (worse) by modifying Throwable is justified.
It just seems like creeping featurism."
is wrong on *so* many levels -- it explains a lot of why Java has been such
a mess for so long.
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|