The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Exceptions in Java : who threw ?

I feel kind of stupid for asking this but... exceptions are supposed to make our lives easier by coding the default code path all in one piece and keeping the handling of failures in exception handlers.

So instead of C style code

ret = f1();
if( ret != SUCCESS ) do something;

ret = f2();
if( ret != SUCCESS ) do something;

etc, etc for every function call....

we will do :

try {
  f1();
  f2();
  f3();
}
catch( IOException e )
{
  handle it here;
}
catch( SecurityException e )
{
  handle it here;
}

That's all well and good, but now for my question : it happens pretty often that f1, f2, f3 are system calls that are all documented as capable of throwing for example, IOException among others.

Therefore if I get an IOException, I have no way of knowing which function failed- wouldn't this information be useful to know what went wrong? What am I missing ??
28 Projects Later
Saturday, January 12, 2008
 
 
The exception object e in the catch statement above has the entire stack of calls that led to the exception. Explore it further.
-S
Saturday, January 12, 2008
 
 
If you want have different error treatments you have to put the method calls in different try/catch blocks.
Marcio Aguiar
Saturday, January 12, 2008
 
 
"What am I missing ??"

The stack trace...  every exception has'em.
Almost H. Anonymous Send private email
Saturday, January 12, 2008
 
 
> The exception object e in the catch statement above has the entire stack of calls that led to the exception. Explore it further.

I assume the OP wanted to handle each individual exception in code, not throw it out and read which line the exception occurred on. 

Marcio Aguiar was on the right track.  Expanded his suggestion yields the following:

try {
  f1();
} catch(IOException e) {
  handle it here;
} catch(SecurityException e) {
  handle it here;
}

try {
  f2();
} catch(IOException e) {
  handle it here;
} catch(SecurityException e) {
  handle it here;
}

try {
  f3();
} catch(IOException e) {
  handle it here;
} catch(SecurityException e) {
  handle it here;
}
jklp
Sunday, January 13, 2008
 
 
Thanks- I hadn't thought of the stack trace; but all I have is printStackTrace which goes to the standard error stream, I'm not sure what that is on J2ME.... I guess what I want is to log everything to a file; maybe I can redirect the err stream, I'll look into that.

In C I could write my program so that I would know that f2 returned 10456 and that's why everything went wrong.

If I have to wrap every call into individual try/catch blocks  I'm not sure what we gained.... certainly not the "more readable code" that was promised!

Anyway... I'll live... just wanted to know if anyone had some thoughts on the matter. Thanks to all who replied.
28 Projects Later
Sunday, January 13, 2008
 
 
Inspecting the stacktrace sounds like a pretty bad idea to me. Throwing a specific exception, rather than a generic one, would be the text-book way to do it.

However, you might want to reconsider what you're doing within the catch block. Most often, when an exception occurs, there is little do do about it, other than clean up the mess and bail out. If you're catching specific types of exceptions, it often suggests, that you do in fact have a way to handling these conditions. If that's the case, you should make this part of your regular program-flow, rather than throwing exceptions.

Here's an excellent article on just that subject:
http://damienkatz.net/2006/04/error_code_vs_e.html
Troels Knak-Nielsen Send private email
Sunday, January 13, 2008
 
 
@Troel: thanks for that link, nice article, and one of the comments has a link to an even better article (IMHO) at http://directorblue.blogspot.com/2004/06/return-codes-vs_108757899333825996.html
(ironically, that article is about Joel's original article....which bring us full circle)(but I digress).

Anyway.... I'm doing an embedded J2ME app, and the idea I had was to log everything so that I can bring back a logfile everytime the user syncs data, allowing me to trace the app's behavior. I used to do that in a previous app in C++ on Windows Mobile, and found a few bugs that way.

And... call me old school, but right now I'm thinking yes, I prefer return codes rather than exceptions. (there, I had to say it).
28 Projects Later
Sunday, January 13, 2008
 
 
... and (sorry, I forgot)
I'm not the one who's throwing exceptions!

These are system calls, the only way they report errors is via exceptions. In my own methods I mostly do return codes (which I guess is normal...at my age...).
28 Projects Later
Sunday, January 13, 2008
 
 
"all I have is printStackTrace"

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Throwable.html

 StackTraceElement[]     getStackTrace()

Don't worry about it too much, though. Unless you can take corrective action after an exception, normally the same exact thing happens: You throw it all the way to the part of the stack that contains the message pump, you show the user the error, the end.
my name is here
Sunday, January 13, 2008
 
 
"...printStackTrace which goes to the standard error stream, I'm not sure what that is on J2ME.... I guess what I want is to log everything to a file; maybe I can redirect the err stream, I'll look into that."

If your working in J2ME, things will be 'interesting'.

Working with a good set of tools will help massively, I use Eclipse + EclipseME for development. In addition I use and highly recommend the SonyEricsson java SDK.

Features that you'll find handy are:
Emulator which is fairly accurate.
On device debugging via bluetooth or serial cable
System.err System.out and printStackTrace in the console view of your IDE.
Network proxy so you don't run up a huge bill test network functionality
Push SMS proxy
Alec Send private email
Monday, January 14, 2008
 
 
When looking at stack traces, remember exceptions can wrap other exceptions as root causes.

Example would be a SQL exception that wraps a Socket IO exception.
Dan Fleet Send private email
Monday, January 14, 2008
 
 
try {
  f1();
  f2();
  f3();
}
catch( IOException e )
{
  handle it here;
}


You'll have to do a little more work if you want to be able to treat different sources of the same exception differently.

Typically, you'll either wrap each individual function call in its own try/catch, or keep track of progress along the way, for example:

int a=0;
int b=0;
int c=0;
try {
  a = f1();
  b = f2();
  c = f3();
}
catch( IOException e )
{
  //handle it here;
  if (a != 0) cleanup_a;
}

It's usually the case that you're calling those functuions in order to accomplish sometyhing, so you should already have local variables you can consult to determine where the exception was raised.

This is also one reason why you shouldn't chain calls to functions that can throw the same exceptions. If you do:

try
{
  f(g(h(a))))
}
catch (IOException e)
{
  //figure out what to do...
}

you'll find it a lot harder than if you did:
int a, b,c,d;
try
{
  b = h(a);
  c = g(b);
  d = f(c);
}
catch (IOException e)
{
  if (d != 0) cleanup_d();
}
Mark Bessey Send private email
Monday, January 14, 2008
 
 
> This is also one reason why you shouldn't chain calls to
> functions that can throw the same exceptions. If you do:

Can you name other reasons then? Because to me, putting everything into local variables looks awkward, compared to chaining the calls.
Troels Knak-Nielsen Send private email
Tuesday, January 15, 2008
 
 
Troels,

My number one reason to use temporary variables and not chain calls is simply to make debugging and testing easier (I work in Quality Assurance, so testing is never very far from my mind, even when I'm writing the code, rather than testing it).

I'd rather write the extra couple of assignment statements and local variables, which will be optimized out in the Release build anyway, rather than having to (carefully) break things up when I need to figure out why it's not working.

It's a bit harder to do all-paths coverage testing if things are wrapped up into a big ball of chained calls, too. well, not so much "harder", as just "more clunky". You end up setting breakpoints and single-stepping through code you don't even care about.

Besides, all my functions are teeny-tiny anyway (another style preference), so the little bit of extra verbosity doesn't hurt much.
Mark Bessey Send private email
Thursday, January 17, 2008
 
 
Interrogating the stack sounds like an over-complicated idea to me. Marcio is right - the best way to do this under normal circumstances is to put the different calls in different try blocks. If the variation in handling is only minor, and you want to do it all in one place, wrap each function call in a try block and have the catch rethrow the exception after adding a code to say what the originating function was.
DJ Clayworth
Wednesday, January 23, 2008
 
 
Taking exceptions in a different context, Eric Sink has an entertaining blog entry on the subject...

http://www.ericsink.com/entries/Business_Exceptions.html
OneMist8k
Thursday, January 24, 2008
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz