Exception Handling

L

Lew

Novice said:
And that brings up a minor point that I've wondered about for a while. Is
there any standard approach to the integers that are used in System.exit
(). For instance, does a value of 16 typically indicate a severe error
while a 4 indicates a minor error? (I'm thinking of the old IBM mainframe
codes in my example.) It seems to me that the Java community may have
some conventions in this regard that I should follow....

No.

It parallels the use in C of exit values. What's the standard in C?

You can answer your own question yourself from first principles. You should
get in the habit of doing that. What is the purpose of the return value of the
program? What uses that value? How does it use that value?
 
N

Novice

Lew said:
No.

It parallels the use in C of exit values. What's the standard in C?
Not being a C programmer, I don't know. But I googled and all Wikipedia
says is that 0 means success and 1 means failure. Another article was
more elaborate but, this sentence expresses the essence: "Your program
should follow an existing convention if an existing convention makes
sense for it". In other words, there is no widely-used standard
convention for the value of the integer in exit().

And that's fine. As usual, it means follow the shop standard if there is
one; otherwise you can do what you like.
You can answer your own question yourself from first principles. You
should get in the habit of doing that. What is the purpose of the
return value of the program? What uses that value? How does it use
that value?

That's closer to the thought process I'd use if I was trying to _create_
a convention. I was trying to determine if there is already a convention
out there that the majority of skilled professionals are using so that I
could use it.

After further googling, I'm not seeing any. In that case, I'll follow a
shop standard if there is one and do my own thing if there isn't, keeping
to the "0 is fine and everything else is bad news" convention.
 
N

Novice

Lew said:
This is treading into the matter of art. I can show the idiom, but no
way can I generate an entire project for you to show the impact of the
logging strategy across the project, which is the point of the idiom.

Your entire application has layers. The deeper low-level layers are
most likely to encounter problems first. Runtime exceptions are
indicative of programming errors, but they're slippery, too. You don't
have to catch them, which means an unguarded runtime exception can
bring your system crashing down. That's not something you want to
design it to do.

A low-level layer by definition brings some model of the world into
conformance with your application's model. It might read a file and
extract data to objects, or persist objects to a database, or
transform your application's model into and out of XML documents for
communication to other modules. Whatever the low layer does, the
higher-level client code deals with abstractions relevant to the
program. It's no longer a database record, for example, it's a
'Customer' with related 'Order' elements in a collection.

If something goes wrong at a deep layer, the higher-level client must
first, become aware of it, and second, have some way to handle it. At
that level, "runtime exception" or 'IOException' are too low-level -
they aren't in the semantics of the application model. So the lower
level, in addition to transforming extrinsic models of good stuff into
the application domain, also must transform bad stuff like exceptions.

One good way to do this is to have an application-specific checked
exception like 'FooException' for the "Foo" application. As Patricia
says, this marks for higher-level code that lower-level stuff has done
its job. At the higher level, we care only that the details are
packaged in the exception's 'cause', not what the details are. A
'FooException', being checked, must be caught, so it cannot
accidentally crash the application. Since all higher-level code sees
'FooException' as a marker for bad stuff, and a black box, they all do
the same thing with it, more or less. They return the program to valid
state

"state" - definable by a quick Google search, for Pete's sake! Come
on, man! Do a /little/ of the lifting yourself. And no, this isn't
"bludgeoning". You get your ego in the way and you won't learn.
There's a reason we expect you to act like a professional.

such as a decision screen or restart position, perhaps extracting
standardized fields from the 'FooException' for the error message.

Much of programming only makes sense if you think architecturally -
that is, holistically. Each layer has its own job, and its own
vocabulary for that job. "Foo" has no business knowing about "I/O" in
its Foo-specific logic, and no business knowing about "Foo" behavior
in its I/O logic.

Separation of concerns.
Law of Demeter.
Object oriented.
Modularity.

I can see why it's hard to be specific about this issue without actually
building a whole, complex project. I don't want to ask too much of anyone
on this newsgroup and building a complex project is surely excessive.
It's just that I really need to hear both principles AND concrete
examples to be sure I really understand the principles. But let's try to
keep this at the principle level for the most part.

I see your point about how the low levels of a program are very narrowly
focused on doing something like finding a resource and don't know - and
shouldn't care - about the significance of that low level task. Those low
level methods don't know what the resource bundle is for or what the
consequences are if the bundle can't be found. It makes sense that the
decision about what to do if that search fails should be higher up in the
logic. The higher level will know if that is a show-stopper or is
recoverable. Some programs may have practical recovery options if the
bundle is missing while others may not.

I suppose it also makes sense that the higher level logic wants to think
in terms of "Foo problems" rather than IllegalArgumentExceptions. The
person writing Foo just wants to know if the problem in the lower level
method is a show-stopper or is recoverable and probably doesn't care if
it is a checked or unchecked exception or an error.

But I'm not quite seeing all the implications yet.

Are you envisioning that our hypothetical Foo would have a single
FooException that it wraps around everything that percolates up from the
lower levels? Or would there be a bunch of FooExceptions, each handling
different sorts of problems?

And what happens with logging? Do we just log the error as an
IllegalArgumentException (or whatever) when we find it at the low level?
Or do we also log it again, this time as a FooException, when we deal
with it at the higher levels? I'm uneasy about writing what are
effectively redundant messages to the log.

For what it's worth, I've cobbled together a CrashDialog class which my
higher level methods, getLocalizedText() for example, displays when it
handles an IllegalArgumentException() if it is thrown by getResources().
(I'm now throwing IllegalArgumentException for nulls in the parameters as
well as a failed getBundle()). In that case, the CrashDialog class says:

===================================================================
Foo - Severe Error

The program has to stop for the following reason: Certain language
resources were not available.

The problem has been logged and Technical Support will begin resolving
the error shortly.

[Okay]
====================================================================

The line about Technical Support resolving the problem shortly is
somewhat fanciful since I'm the whole development team and the entire
universe of end users at the moment ;-) I'm just envisioning what I'd say
in a real production application.

The bit about the language resources being unavailable is not completely
satisfactory because it is probably not very helpful to a non-technical
user but it seemed better to summarize the situation than to use the
message from the exception; the user is even less likely to comprehend
"the baseName must not be null" or "Unable to find resources for base
name, com.novice.foo.FooTextzzz, and locale, jp_JP. Check the spelling of
the base name". And I certainly don't want to display a stacktrace to the
user!

I've also logged the fact that the user clicked on okay to end the
program as another SEVERE error. Mind you, that seems redundant and I'm
inclined to remove that code again. I'm assuming that in the real world,
one SEVERE error is going to be enough to get the attention of the
appropriate people and producing two or three SEVERE errors about the
same problem is not going to get the problem examined any sooner. Correct
me if I'm wrong!

Now, that behavior wouldn't be standard for all cases. If the error is
recoverable, the user would get different instructions that would lead
him/her through whatever needs to be done to recover. And some errors
might not be severe at all and just be informational. In those cases, the
dialog might say "Information" instead of Severe Error and simply
describe whatever workaround Foo adopted to get past the problem.

I'm feeling good about the error handling and logging now. It's starting
to fall into place for me, aside from the whole custom exception
question.
 
N

Novice

Using the same exception for "illegal argument" and "already logged and
wrapped" is unlikely to get you into much trouble in a short program
viewed for a few minutes.

The potential trouble comes when you have a large program, too large to
read the whole thing before making a change, and it is being modified by
a programmer who does not know, or does not remember, that the exception
has those two meanings.

That makes it difficult to illustrate in a small example.

Remember that a lot of what you are being told, both in the newsgroup
and in the articles you are reading, is based on experience with
maintaining large programs over many years.

As I've replied to Lew, I see the difficulty in talking about this. There
are so many different situations that come up that it's hard to be
specific without saying something that is only valid for the specific
situation but might be misleading if applied to the general situation.

I'm mostly focused on my little program and understanding what it should
do. There is definitely a danger that I might over-generalize from the
specifics of my case and use techniques that are appropriate for my
situation in ways that are inappropriate to a very different program.

You responders are thinking about lots of different programs, often much
vaster than anything I'm doing, and generalizing to cover a lot of cases,
some very different from mine.

There's no getting away from it. This is a tricky thing to communicate
and learn. I'll just have to do my best to apply general principles to
specific situations and stand ready to adjust my techniques as I get more
experience with things.

I look forward to the day when I have real code walkthroughs again. For
now, I think I need to focus on principles and coding things that are at
least fairly close to best practices but maintain the flexibility to
tweak my code as necessary when I discover that it doesn't work well or
fails to fit best practices used in the Java community.

Thanks, as always, for your thoughts on these matters, Patricia.
 
G

Gene Wirchenko

[snip]
Not being a C programmer, I don't know. But I googled and all Wikipedia
says is that 0 means success and 1 means failure. Another article was
more elaborate but, this sentence expresses the essence: "Your program
should follow an existing convention if an existing convention makes
sense for it". In other words, there is no widely-used standard
convention for the value of the integer in exit().

Well, there is. 0 and 1 is the standard. The more elaborate
article has it wrong. Now, quite commonly, the return value is used
by the operating system as a return code, but this is not part of the
C standard.

[snip]

Sincerely,

Gene Wirchenko
 
N

Novice

[ SNIP ]
I suppose I'm too easily swayed by other opinions. Arved, who seems
very knowledgeable, cited that article, which seemed to give it his
seal of approval. I don't know the author of the article but I tend
to assume he must be an expert to be asked to write about a Java
topic. The author cites people who he considers experts and the
upshot is that the advice seems to argue against putting positioning
information in the log unless its necessary (which it probably isn't
if the stacktrace is in the log). Now you make a persuasive argument
contradicting the article. I'm satisfied that you have serious
expertise in this area so I have no reason to dismiss your argument.
But why didn't the experts who wrote the article modify their remarks
accordingly?
[ SNIP ]

The article did have my "seal of approval". That's to say, I read the
article, and agreed with most of it. Not 100 percent, but most of it.
And I didn't see anything in it which would lead a person down the
garden path. I recommend it because it's a useful read...but you
shouldn't accept it as the gospel, just as you shouldn't accept
"Effective Java" as the gospel either.
Absolutely. Please understand that I didn't mean to imply that you gave
your whole-hearted endorsement to every bit of it. I just meant that
you'd suggested it in an approving manner, which suggested that it was
basically sound, not necessarily perfect in every detail.
Logging is also a somewhat subjective matter. That's why different
opinions on different specifics. Ultimately TIMTOWTDI, to borrow a
Perl motto.
I dabbled in Perl briefly some years ago but didn't know that acronym.
But, as Lew likes to remind me, Google is my friend so now I know what it
means ;-)
What really counts is when the rubber meets the road, and
the logs have to be _used_, did the ops support people get what they
needed out of the logs, without too much anguish?
That makes perfect sense to me.
You've heard different viewpoints - mine and others' - on including
positional informational in logs. In the final analysis what matters
is the sufficiency of information in the logs. Don't worry overmuch
about logging performance until it's a problem; the whole point of
having layouts in a properties file is that you can tweak them if
necessary. I have a specific reason why I don't normally include
certain positional information, except for error stacktraces, but
someone else might have a good reason for why they do want this info.
Speaking with my programmer hat on, I tend to find that the stacktrace
meets most of my needs. I mostly use the class name, method name, and
line numbers to see where the problem is and what the message is. And I
don't tend to worry about performance until it starts to become an
obvious problem either. But I always start feeling a bit anxious when
people start talking about performance and wonder if I'm shooting myself
(or my system) in the foot with the techniques I use. But, so far, that
hasn't been a frequent problem.
One note: *never* assume that because somebody has an article in a
blog or an Internet magazine or a dead tree magazine or even a
scholarly journal that they are experts. Check the references. Check
the style of the prose: are the conclusions backed up by
understandable argument, or are they just "put out there"? Google for
other articles on the same topic.
In all honesty, I had that in the back of my mind too. I don't really
blindly assume that everything I read is written by an expert. I tend to
give people the benefit of the doubt, especially in topics where I have
minimal knowledge, but I know that some articles are just nonsense. But
if a guy who knows his stuff (like you) recommends an article to me and
it is in a journal that I haven't actually heard trashed by someone
knowledgable, I tend to assume that knowledgable editors will have done a
conscientious job of keeping out anything that is complete nonsense. But
I realize that is hardly a bulletproof approach. So I do retain some
basic skepticism about things I read ;-)
 
A

Arne Vajhøj

I've been trying to get my head around exception handling for the last
few days concurrently with my efforts to start doing logging correctly.

I've re-read the Java Tutorials section on exception handling. I read
Bloch's remarks on Exception Handling in Effective Java (2nd edition)
several days ago. I'm working my way through Stelting's Robust Java.

It's time to ask some questions to make sure I'm on the right track.

I'm struggling with the best way to revise some of my existing code.
Let's consider a concrete example and then see if we can generalize to
come up with a proper error handling strategy.

I have a utility class called LocalizationUtils which basically houses
convenience methods dealing with i18n/l10n. One of its methods is
getResources(). It expects two parameters, a String representing the
"base name" (the leading part of the resource file name) and a locale.
In terms of trouble spots, I know from experience that getResources()
will throw a MissingResourceException, which is an unchecked exception,
if the base name is misspelled. A null value in either parameter is also
going to make the getResources() method fail: ResourceBundle.getBundle()
will throw a NullPointerException if either parameter is null.

My objective is to code getResources() and getLocalizedText() as
professionally as possible. If the methods fail, I want to write a clear
message to my log and the log record needs to include a stacktrace. (I'm
assuming that a console is not necessarily available to the operators
running this program and I need to know where the error took place. Based
on an article Arved suggested in another thread,
http://www.javacodegeeks.com/2011/01/10-tips-proper-application-
logging.html, I'm inclined to minimize "position" information - class
name, method name, line number - in the log and instead get all of that
from the stacktrace.)

I would not worry about the performance until you know that you
have a problem.
Since the only exceptions I anticipate, MissingResourceException and
NullPointerException, are unchecked exceptions, I gather than I shouldn't
really do anything about them aside from logging when they happen.

If you only log - then what?
Okay,
fair enough; I certainly don't want to display the source code to my
user, make them enter the correct value for the baseName, make them
recompile the program and then run it again! But when/where should I log
the error? For instance, if I mess up my coding somehow and inadvertently
pass a null in the baseName, should getResources() be testing its input
parameters individually to see if they are null and write a message to
the log if they are null from within that method? I'm inclined to say yes
to that but I'm not sure what to do next. It seems pointless to carry on
with getResources() since ResourceBundle.getBundle(baseName, locale)
will fail on a NullPointerException with a null in either parameter. I
could throw a NullPointerException so that getLocalizedText() can deal
with it. But how do I get a stacktrace into the log if I follow that
strategy? It's easy enough to get the stacktrace once I've caught an
exception but I'm just talking about recognizing that an input parameter
is null; there's no exception at that point to put in my log.

If I let getResources() throw NullPointerException if either parameter is
null, then I can let getLocalizedText() catch those NullPointerExceptions
and get the stacktraces from the exception and write them to the log. In
that case, I may as well just check the input parameters for nulls, and
simply throw NullPointerException with a specific message within
getResources(); then getLocalizedText() can have a try/catch block. The
try/catch can detect the NullPointerException and write both the message
and the stacktrace to the log.

But I gather that you should handle the error as close to where it
happened as possible when you can. I'd tend to prefer to handle the null
parameter values in getResources() except that I'm not sure how to write
the stack trace to the log before any exception has happened.

Do you need the stacktrace in that case?
One other questions. When, if ever, should I execute System.exit() with a
non-zero integer?

When you want to terminate the program with an error status to the
shell.

Arne
 
A

Arne Vajhøj

Novice wrote:
[lot if stuff that I agree with cut out]
Never. Program exit should be under user control.

I don't s much point in "This app is completely fubar. Do you want to
exit or do you want to experience random behavior including possible
data corruption?".

:)

Arne
 
A

Arne Vajhøj

Generally, you should use different Exception subclasses for cases that
may need different handling, so that callers can set up appropriate
catch blocks.

I think the word *may* is critical here.

It is not just if one need to write two different catch blocks
within the next 10 minutes.

It is actually if it is reasonable likely that someone will want
to write two different catch blocks within the next 10 or 20 years.

Arne
 
N

Novice

I would not worry about the performance until you know that you
have a problem.


If you only log - then what?


Do you need the stacktrace in that case?

Yes. I call getResources() from several places in the program and just
knowing getResources() was called doesn't tell me which call had the
problem. Was it the call in the main menu that launches the program? Was
it the call in the program itself that sets up the GUI? Was it the call
in the preferences dialog? etc. So I'm going to have trouble determining
which bundle was desired unless I know at least the method which called
getResources(). Now, if getResources() was only invoked once in the life
of the program, just knowing that it happened would be all I'd need to
know what it was trying to find.
 
L

Lew

Novice said:
Yes. I call getResources() from several places in the program and just
knowing getResources() was called doesn't tell me which call had the
problem. Was it the call in the main menu that launches the program? Was
it the call in the program itself that sets up the GUI? Was it the call
in the preferences dialog? etc. So I'm going to have trouble determining
which bundle was desired unless I know at least the method which called
getResources(). Now, if getResources() was only invoked once in the life
of the program, just knowing that it happened would be all I'd need to
know what it was trying to find.

None of that explains why you need a stack trace instead of other ways to get those data. Why do you prefer the stack trace to other techniques?

Mind you, I'm not arguing against a stack trace. Have you looked at your log output to see if the stack trace is usable information?

Well, have you?
Okay, thanks.

This is the same answer, in its essentials, that you keep getting over and over.

Over and over we tell you, "What is the use that will get?"

So, what is the use that will get?

This has two parts: What will use the exit code? What will it do with the exit code?

Well, what will?
 
A

Arivald

W dniu 2012-03-12 23:43, Novice pisze:
Yes. I call getResources() from several places in the program and just
knowing getResources() was called doesn't tell me which call had the
problem. Was it the call in the main menu that launches the program? Was
it the call in the program itself that sets up the GUI? Was it the call
in the preferences dialog? etc. So I'm going to have trouble determining

Instead of stack trace, you may be more interested in resource ID
program try to load and failed. If You fix missing resource, it will
work in all places.

Just add resource name and locale data to log message.
 
A

Arved Sandstrom

W dniu 2012-03-12 23:43, Novice pisze:

Instead of stack trace, you may be more interested in resource ID
program try to load and failed. If You fix missing resource, it will
work in all places.

Just add resource name and locale data to log message.
Agreed. In the general case, simply make sure that your log statements
print enough stuff. It's much less useful, than you might think, to know
who the caller was; the main reason people believe it's important is
because they forgot to log enough data and so are desperate to somehow
recover that by guessing from the calling context.

Static analysis as part of debugging will tell you the potential
callers. If it's really important to know what did call, hey, just log
the potential calling sites also: you have a log statement in
getResources() and a statement in each of the N methods that use
getResources().

Keep stack traces for errors. Rely on a flow of single-line log entries
to help you trace a flow of execution. It's uniform, easier to analyze
with a variety of tools. Logging is cheap this way. No harm done if you
add log statements; you can switch them on and off by class or package
as needed at various levels. If you log like this the only stack traces
that you see belong to real errors.

Make your life easier by enhancing your messages. slf4j helps out with
this by providing argument placeholders, but it's easy to do this
yourself with java.text.MessageFormat. Keep your log message format
strings in a properties file, and consider a utility class that loads
these, and can be accessed at logging time with a property key and the
log message arguments. This utility class uses MessageFormat to do the
work, and returns a fully formatted message to the site of the log.

Consider all the extra identifiers in a message that help trace a flow
of execution: thread ID, logged-in user in a web application etc. Use
PatternLayout (log4j) or similar, or other helper methods
(getAuthenticatedUser() in your utility class) to simplify this framing.

HTH,
AHS
 
L

Lew

Novice said:
Are you envisioning that our hypothetical Foo would have a single
FooException that it wraps around everything that percolates up from the
lower levels? Or would there be a bunch of FooExceptions, each handling
different sorts of problems?

Quite often a single exception type suffices. You would only add another if
there were a crying need for it.
And what happens with logging? Do we just log the error as an
IllegalArgumentException (or whatever) when we find it at the low level?

Did you read Patricia's advice on this very matter?
Or do we also log it again, this time as a FooException, when we deal
with it at the higher levels? I'm uneasy about writing what are
effectively redundant messages to the log.

Patricia recommended, and I agree, that the custom exception serve as a signal
that the lower-level problem has been logged. Remember?
For what it's worth, I've cobbled together a CrashDialog class which my
higher level methods, getLocalizedText() for example, displays when it
handles an IllegalArgumentException() if it is thrown by getResources().
(I'm now throwing IllegalArgumentException for nulls in the parameters as
well as a failed getBundle()). In that case, the CrashDialog class says:

Is a failed 'getBundle()' really a programming error? Is it really an illegal
argument? There was nothing illegal about the argument /per se/ if the
resource just happened not to be available.

I suggest a checked exception, either 'IOException' or a subtype thereof, for
a missing bundle, unless it really and truly is completely under programmer
control. (And deployment-time issues never are.)
===================================================================
Foo - Severe Error

The program has to stop for the following reason: Certain language
resources were not available.

The problem has been logged and Technical Support will begin resolving
the error shortly.

[Okay]
====================================================================

The line about Technical Support resolving the problem shortly is
somewhat fanciful since I'm the whole development team and the entire
universe of end users at the moment ;-) I'm just envisioning what I'd say
in a real production application.

Be careful of making promises because you must keep them.

Well, technically you don't have to, but do you want to be that guy?
The bit about the language resources being unavailable is not completely
satisfactory because it is probably not very helpful to a non-technical
user but it seemed better to summarize the situation than to use the
message from the exception; the user is even less likely to comprehend
"the baseName must not be null" or "Unable to find resources for base
name, com.novice.foo.FooTextzzz, and locale, jp_JP. Check the spelling of
the base name". And I certainly don't want to display a stacktrace to the
user!

I've also logged the fact that the user clicked on okay to end the
program as another SEVERE error. Mind you, that seems redundant and I'm

How is that any kind of error?
inclined to remove that code again. I'm assuming that in the real world,
one SEVERE error is going to be enough to get the attention of the
appropriate people and producing two or three SEVERE errors about the
same problem is not going to get the problem examined any sooner. Correct
me if I'm wrong!

Don't worry, we will.

But you have a brain. What makes sense there? What would look funny to the ops
guy?

Are you really thinking like a troubleshooter in the field, or like the
programmer whose name that troubleshooter will curse?
Now, that behavior wouldn't be standard for all cases. If the error is
recoverable, the user would get different instructions that would lead
him/her through whatever needs to be done to recover. And some errors
might not be severe at all and just be informational. In those cases, the
dialog might say "Information" instead of Severe Error and simply
describe whatever workaround Foo adopted to get past the problem.

I'm feeling good about the error handling and logging now. It's starting
to fall into place for me, aside from the whole custom exception
question.

What do you mean by "recoverable"? I mean able to show an error dialog and
invite the operator to shut down. Is that not a valid program state?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top