at what point do you catch db errors?

This isn't strictly a coldbox question, but since this group is full
of OO gurus I thought I'd ask :slight_smile:

if you have a handler -> service -> gateway setup, where the gateway
is doing all the database query bits, what layer *should* be
responsible for handling errors? I know that's probably as much
personal taste as anything else, but it'd be interesting (to me) to
find out what people do here.

I generally take the stance that unless I'm able to recover somehow
from an error (show a pretty screen, deliver useful alternative
content) then I let it through to the application.onError handler to
log it and display an error screen.

More recently, however, I've been moving some of this logic into the
gateway. For example returning boolean success/fail on an insert query
to indicate whether the record was inserted. I log the error where it
occurs. This seems tidier in some ways, but doesn't provide much
reporting back to the other layers as far as *what* went wrong.

Any thoughts?

If you want to keep it simple, just cfthrow(set message and type
attributes) an error in your gateway and catch/handle the error in
your application.cfc (handler)
You could create an ExceptionService, called by the onException method
in your handler, which processes different types of errors.

In ColdBox you could use the build in error handling and/or create an
interceptor(or multiple) which uses the interceptor point onException.

Ernst

Simple is good :slight_smile: So your services/gateways don't do any error
trapping beyond catch/rethrow? Do you find that clutters the handler?

I'm still coming to grips with interceptors -- that sounds like an
interesting approach. How would multiple onException interceptors work
out of curiosity? I'm imagining it like onError in application.cfc but
I assume that it can do more than that.

Which approach have you found to have the most utility?
ExceptionService/onException/interceptor?

I rarely ever code try/catches. Unless an error is recoverable, (meaning I can still successfully finish processing the request-- which is not likely) I always let the framework do its job and catch/log the error that the highest level. I use ColdBox's custom onException Handler to check for a couple errors that get a special error screen. Everything else falls through to my ColdBox CustomErrorTemplate and gets logged with LogBox.

I've seen people who put try/catches around EVERYTHING, and frankly I don't see the point. The original error message contains the full stack trace of what happened and where so there's no real benefit to catching it where it happens unless you need a "finally" block that always runs.

When rethrowing, I always use the cfrethrow tag. Trying to piece the information from the cfcatch struct back into a cfthrow often times leaves important pieces of the error out.

Also, I do have a bit of code in my application.cfc's onError that logs and redirects to my CustomErrorTemplate page. This will catch any errors that occur when the framework is still starting up.

It's also worth noting I go to great lengths to ensure my CustomErrorTemplate is a stand-alone cfm page that can be loaded without coldbox's framework, settings, or datasources being loaded. You need to make sure people still get a pretty screen even if everything else has failed. I also relocate to it via JavaScript if I have a non-recoverable JavaScript error on a page.

Thanks!

~Brad

I'm with Brad, except for a) expected exception where you're really
just testing something, and b) more importantly, db constraint
violations. The only way to actually ensure a UserName or whatever is
unique without being vulnerable to race conditions is a constraint at
the db level, and something needs to catch and interpret that to the
user.

One thing I've done in that past is a generic
throwIfUniqueKeyViolation method in the base service class, which in
its simplest form takes a match string to test the query error
against, and an error msg to throw if it matches. The save query gets
wrapped in a try/catch, and that method gets called in the catch. If
the passed exception matches the passed criteria, it throws a
validation exception with the appropriate passed in msg, otherwise it
does nothing, and by the end of the catch if nobody threw a more
specific validation exception, rethrow, and the global error handler
will deal with it.

This all relates to the other question posted recently about returning
error info from service methods. I haven't come to a settled
conclusion for a ColdBox app; still experimenting.

Dave

and b) more importantly, db constraint
violations. The only way to actually ensure a UserName or whatever is
unique without being vulnerable to race conditions is a constraint at
the db level, and something needs to catch and interpret that to the
user.

I would definitely have a db constraint, but the only way to avoid duplicates is not by simply inserting and catching any errors. This is what transactions, isolation levels, and locks are for. I haven't tried it, but off the top of my head I would think checking for that username in your user table with an exclusive table lock at the beginning of your transaction and then inserting if not found prior to committing should also guarantee uniqueness and rule out any race conditions.

This is just me, but I always thought letting something error on purpose and then catching it was kind of cheap. (Don't take it personally-- it's just what I always had in my head). I always figure you should explicitly check for something. And I have seen large amounts of error trapping to be an expensive operation.

I'm curious, do other people purposefully allow their database constraints to error and use that as the mechanism of determining uniqueness, or do they explicitly check ahead of time using database isolation to prevent dirty or phantom reads?

Thanks!

~Brad

If you are doing pessimistic/optimistic locking you need to try/catch the
error.

Regards,
Andrew Scott
http://www.andyscott.id.au/

From: coldbox@googlegroups.com [mailto:coldbox@googlegroups.com] On
Behalf Of Brad Wood
Sent: Wednesday, 10 November 2010 3:27 AM
To: coldbox@googlegroups.com
Subject: Re: [coldbox:6638] Re: at what point do you catch db errors?

I rarely ever code try/catches. Unless an error is recoverable, (meaning

I can

still successfully finish processing the request-- which is not likely) I

always let

the framework do its job and catch/log the error that the highest level.

I use

ColdBox's custom onException Handler to check for a couple errors that get

a

special error screen. Everything else falls through to my ColdBox
CustomErrorTemplate and gets logged with LogBox.

I've seen people who put try/catches around EVERYTHING, and frankly I
don't see the point. The original error message contains the full stack

trace

of what happened and where so there's no real benefit to catching it where
it happens unless you need a "finally" block that always runs.

When rethrowing, I always use the cfrethrow tag. Trying to piece the
information from the cfcatch struct back into a cfthrow often times leaves
important pieces of the error out.

Also, I do have a bit of code in my application.cfc's onError that logs

and

redirects to my CustomErrorTemplate page. This will catch any errors that
occur when the framework is still starting up.

It's also worth noting I go to great lengths to ensure my
CustomErrorTemplate is a stand-alone cfm page that can be loaded without
coldbox's framework, settings, or datasources being loaded. You need to
make sure people still get a pretty screen even if everything else has

failed. I

also relocate to it via JavaScript if I have a non-recoverable JavaScript

error on