Link to home
Start Free TrialLog in
Avatar of kkamm
kkammFlag for United States of America

asked on

Exception handling in an n-Tier application-best practices?

I have an application that consists of 3 layers: a DAL layer, a BLL layer, and a UI layer. I need to be able to propagate exceptions from the DAL up through the other two so I can do cleanup in the UI and BLL if a database call fails. I also need to be able to trap exceptions originating locally in the BLL and UI layers.

I haven't dealt with n-Tier exception handling before and I am interested in what is considered a best practice approach to this.

As a starting point, I have attached a code snippet with a very basic first attempt. I have a custom exception defined for each call level so I can trap  and rethrow those separately from exceptions originating locally. If an exception occurs locally it is rethrown as a new custom exception defined for that level.


Private Class CallOneException
        Inherits Exception
End Class
 
Private Class CallTwoException
        Inherits Exception
End Class
 
 
Private Sub BaseCall()
	Try
	CallOne
	Catch CallOneEx As CallOneException
        Catch CallTwoEx As CallTwoException
	Catch Ex As Exception
        Finally
        End Try
    End Sub
 
Private Sub CallOne()
	Try
	CallTwo
        Catch CallTwoEx As CallTwoException
	Throw
        Catch Ex As Exception
        Throw New CallOneException       
	Finally
        End Try
    End Sub 
 
Private Sub CallTwo()
        Try
        Catch ex As Exception
        Throw New CallTwo Exception
        Finally
        End Try
    End Sub

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of openshac
openshac

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Avatar of Éric Moreau
Éric Moreau
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of kkamm

ASKER

Thanks for the links. It seems like this is a pretty common issue.

>Remember the GUI should have no references to anything in the datalayer.  So if you get a data layer >error, let the business layer interpret that and decide whether to handle it or how to push it to the GUI.

My DAL CRUD routines currently return either booleans or data objects to indicate the status of an operation, but not any exception info, which is what I am looking to do. Any knowable DAL exceptions, such as an offline server, are handled by conditionals locally and not by exception code. I will probably take care of detailed logging, cleanup etc. locally, but I still need to give the user some indication of what kind of error occurred.

 Is it still considered bad form to pass just the error message up the call stack?


Avatar of openshac
openshac

I guess what I was refering to was your line in BaseCall :
Catch CallTwoEx As CallTwoException

>>Is it still considered bad form to pass just the error message up the call stack?
Certainly not, you should never just handle unexpected errors blindly.  That would mean you are allowing your code to run in an unexpected state.

But if as you say the DB server is offline, then by all means get a friendly error to the GUI (it doesn't need to know the stack trace etc, the BL could log this).
Avatar of kkamm

ASKER

So the convention of rethrowing an exception up to the caller is considered an ok practice, as long as the actual handling (cleanup,etc.) is done at the originating layer?

Part of the complexity of this for me is having to do related cleanup through the call chain. If a user updates an item in the UI, and there is a problem with the server, then the app won't know this until it attempts a DAL operation. In the meantime, the grid view has an updated row, as well as the collection it is bound to. What I am doing currently is holding off on any updates being finalized in the UI and BLL until the call to the DAL is completed successfully. If it isn't, and an exception is thrown, then the BLL and UI updates are cancelled before being committed.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of kkamm

ASKER

Do you define all your custom exceptions in a separate project and then reference that from the 3 layers? Right now, I have an exception class for each layer, but I think I would be better off grouping these together into a separate project.

 I would like to define separate exceptions for each layer, but some of those exceptions are going to be rethrown from DAL to BLL and up to the UI, so each layer has to be able to reference the type. Ultimately, the UI is going to notify the user for every exception, so it will be catching each custom exception type one way or the other. The BLL and DAL will simply log and rethrow their exceptions, as I do not want either of those to have UI thread access (modal dialogs,status bars,etc.)

Also-do you separate your custom exceptions according to the exception domain? (i.e. MySQLException,MyNetworkException,etc.)

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of kkamm

ASKER

There is a lot of good info in the links provided. It tells me that I definitely do not want to pass exceptions as return values, which I was considering.
> There is a lot of good info in the links provided.

Tx. If you like the answers (good), why do you do a low-grade then? Please consider the guideline about the 10pts must principle at EE. In short B or C should only be used in rare situations where you still yearn for more information but you don't get it, or the information is just not good and the expert does not follow up with something better.