Exception handle

Topics: Enterprise Library Core
Apr 22, 2007 at 9:33 AM
hi...
I have 3 tier application: data layer, business layer, and UI, and i want to use the exception handling application block, and i didn't understand how to build the exceptionTypes for each Policy. do i need to build policy for each tier, and in each policy add its exceptions type?
is that right to use it like this: in the data layer throw the exception, in business layer catch it and wrap or replace it, and in UI show the error?
do i need to build each policy's exception types by the inheritance hierarchy, or, when i add exception type with the configuration tool, he place them in correct place?
thank you....
Apr 23, 2007 at 5:21 PM
I think the quickstart, called ExceptionHandlingBasicQuickStart, is a good example on how to organize your policies. My first choice wouldn't be based on the layer, but by functionality. The quickstart has policies of:

Replace Policy
Wrap Policy
Global Policy
Handle & Resume Policy

which is similar to how I typically organize my policies.

I recommending looking at the two quickstarts for additional information.

Regards,

Dave

______________________

David Hayden
Microsoft MVP C#
Apr 23, 2007 at 10:15 PM
Edited Apr 23, 2007 at 10:16 PM
This is a good one. I'm more incline to build policy base on a layer approach. In a simple two layer approach Data/Presentation one could do the following. The best use of policy is not realy there and left up to the one implmenting it.

Data Layer Policy - Log to event and let the exception buble up a layer, rethrow.
Presentation Layer Policy - Show a User Friendly Dialog box about the error, no rethrow.

This would allow an admin to look at the Event Log after the End-User leaves the program.
This would also give the End User a nice Error Message and not one with dump stack trace info.

Application Layer psudo Code
try
{
    DataObject.GetCustomerData()
}
catch (Exception ex)
{
    bool rethrow = ExceptionPolicy.HandleException(ex, "Application Policy");
    if (rethrow)
        throw;
}
For the DataObject class there would be a method to get the data.
public void GetCustomerData()
try
{
    //
    // Cause a SqlException
    //
}
catch (Exception ex)
{
    bool rethrow = ExceptionPolicy.HandleException(ex, "Data Policy");
    if (rethrow)
        throw;
}

Then for those policies add the exception you want, and the handler to go along with it. One could add exceptoin in the data layer that not only log, but send on an email, etc... The policy for the Presentation layer could also have an exceptoin type that may or my not allow the program to continue, or have the type of exceptoin not only show the dialog box but also ask for feedback and send an update.

This also makes it clear as to which policy to use at any given time based on what layer you are trying to handle the exceptoin. When at the data level do I use a Wrapper Policy, Replace Policy, etc. Instead I use the Data Policy then the policy determines based on the Exception Type if it should then do Wrapper, a Replace or handle the error, and determine if there is a rethrow or not. Also one would pretty much know how the exception are being handled at the different layers. I know at that data layer and base on the data policy exceptions are handled either A, B, or C.

But again I'm still up in the air it just one seems to be more logical, but when doing Enterpise stuff and trying to get a Pattern down based on a simple quick start app is not easy. What the policy name should be and what should the name represent, option one Generic Use Case (Wrapp, Replace, etc..) or option two Application Layers (data, services, business logic, presentaiton, etc..) . The quick start is good in showing how to do it, but not how to fit all the pieces together in a Enterprise application with many layers and come away from the sample application with a concrete implementation pattern.

At the end of the day the reality is what makes it easier for the programmers. I could just call them the A Policy, B Policy, and C Policy. Now would that not cause some confusion or what?

Now that I'm done and have reviewed this, maybe a hybrid option would be ideal? Use these base on the layer of the application and if the results are not what you want then use a general purpose policy?


- guy


Apr 30, 2007 at 9:47 AM
hi...
thank you for your answer...
let me ask you something else:
1. Do i have to create policy to each tier?

2. Within each policy, if i want to catch specific error, and handle it differentlly, do i need to add the exceptions type to the policy for the specific error that i want to catch, or i catch it in the code?

I mean: let say i have the policy: "dataLayer policy", and this policy contain two types of exceptions: System.Text.DecoderFallBackException and System.Exception. now, i want to catch the System.Text.DecoderFallBackException and replace it with friendlly error.

so, i throw it from the dataLayer and catch it in the caller function(on the business layer), so, do i need to write the same catch block with the same policy(the preceding code below), or, do i have put another policy to the business layer, that catch also the same errors, to replace it their and throw new exception to the UI layer?

the catch block:
try
{
// TODO: Handle exceptions
}
catch (Exception ex)
{
bool rethrow = ExceptionPolicy.HandleException(ex, "dataLayer policy");
if (rethrow)
throw;
}
3. if i want to handle the System.Text.DecoderFallBackException do i need to catch it in the code:

catch (System.Text.DecoderFallBackException ex)
{
bool rethrow = ExceptionPolicy.HandleException(ex, "dataLayer policy");
if (rethrow)
throw;
}

or, is it enough to have it as exception type in the policy?


thank you....
Apr 30, 2007 at 3:17 PM
I don't know that there are any hard and fast rules on using the Exception Handling Block. Don't overcomplicate the Exception Handling Process or you will find it is difficult to debug exaclty what error happened and the actual location it happened.

You don't have to create a policy for each tier and you don't have to name your policies so that they correspond to a particular tier ( layer ). You can create only one policy, you could create a policy for each layer, or you could create a policy described by its function.

You also don't have to catch the particular exception in its own catch block unless you have some code you need to run when that exception is thrown that is outside of the scope of the Exception Block. You can simply catch (Exception ex) and specify in the Policy that when the exception is of type DecoderFallBackException that you want to replace it with a different Exception and rethrow. Unless you need to do something special when a certain exception is thrown and caught, you typically only catch Exception and run one policy inside of the catch block:

try
{
    // Do Something
}
catch(Exception ex)
{
    bool rethrow = ExceptionPolicy.HandleException(ex, "MyPolicy");
    if (rethrow)
        throw;
}

Regards,

Dave

_______________________________

David Hayden
Microsoft MVP C#
Apr 30, 2007 at 9:18 PM
Edited Apr 30, 2007 at 9:19 PM
Re-hash with hopes to answer questions and bring up new one?

For example an application my only have two layers a Data Layer and an Application Layer.

How I think of it is, how do I want to handle an error in a generic way at the given layer. I would create two Policies and add the exception type "Exception" to those two policies. Now to make them different I would define the Exception Handler for the Data Layer to be a Logging Handler and log to the Event Log. Knowing this is not the top layer I would then set this one to rethrow the exception allowing it to buble up to the next layer (Application). The application layer I would use a custom hanlder to show a custom user friendly error dialogbox instead of the .net default. This policy would not rethrow because it is a the top and the exception handling should stop at this point. With that base I would just wrap code in either layer around the try catch block and know that one layer would be logging and then the dialogbox would be shown when rethrown. See previous post.

From there I would start to handle specific Exceptions by way of adding to the Exceptoin block configuration. I would add another Exception Type to the policy. Then if need be add a different exception handler or custom exception handler. The code does not change, you just have an exception type of DecoderFallBackException in the Config file. Then if you want write a custom handler to log the additional data. Then in the customer handler for the Application Block you would show the additional data relating to DecoderFallBackException that would not be in the base Exception type.

I think where the clearity breaks down is not with the configuration, but that not all exceptions can be logged the same way and if I need more info relating to the exception how do I add to the log with out writing a special Exceptoin Handler to map the data?

    |- Applicaiton Configuration
    |
    |- Data Policy
        |- Exception
        |   |- Logging Handler
        |- DecoderFallBackException
        |   |- Logging Handler
        |- EncoderFallbackException
            |- Logging Handler
    |- Application Policy
        |- Exception
        |   |- UIException Handler
        |- DecoderFallBackException
        |   |- UIException Handler
        |- EncoderFallbackException
            |- UIException Handler
 

If I where to add an Exception Type DecoderFallbackException to my Policy: Data Policy and used the standard Logging Handler how would I map BytesUnknown or Index?. Now when I move up in the layers how would I then use my custom handler it might not be a problem but a lot of testing for specific exception to specific data. Then later if I get EncoderFallbackException how would I log CharUnknown or CharUnknownHigh or CharUnknownLow using the stander Loggin Handler? So looking at the tree view of the Configuration, how would I make the Logging Handler format the log entry for that specific error? Or more simple because it is my custom handler how would I do it in that one? That is with out some brutte force If excpetion is this then get data X, Y, Z and if it is excption123 then get data A, B, C?

I'm guessing the question may be two fold also, one for naming and the other on how to handle different Exceptions and Customize error output for that specific Exception without writing a Custom Exceptoin handler. But as stated for the first question there may not be a Hard Fast Rull for naming a policy and as stated it could even just be Policy A, B, C or even MyPolicy. For the second issue if you dive into it there realy is not issue and only being over complicated. One should not need to get at the details of an excpetion and indivual properties when reporting and erro. The details should be in the Message property. Therefore you would not need to log or display an exceptions details just the message.

I think what we are dealing with now is 1. How do we resolve the exception, what do we want done after, do we continue, do we shut down, do we abort the path. And 2. how do we report the error, display the error and get it back to the end-user.

The EntLib even though it say Exception Handlers that is not realy resolving it. EntLib to me is more of the reporting and display exceptions regardless of the details. Even though the two exceptoins DecoderFallbackException and EncoderFallbackException my be different and have different details those details should be in the Message and any Exception Handler in Entlib would use the Message and report with details between the two. These details would then show in the EventLog and the Dialog Box shown with out testing for specifig Exceptions. The draw back to this is if the Messge does not have BytesUnknown or Index or CharUnknown or CharUnknownHigh or CharUnknownLow in the wordings. Keeping it simple then one would only need this:
    |- Applicaiton Configuration
    |
    |- Data Policy
        |- Exception
            |- Logging Handler
    |- Application Policy
        |- Exception
            |- UIException Handler
 

But now lets say you need to do something special about DecoderFallbackException at the Application Lay and using the above configuration. Would you do it this way?

try
{
    // Call into the lower layer which would throw a DecoderFallbackException
   //  Or just do something here that would throw a DecoderFallbackException.
}
catch(Exception ex)
{
    // This will trap and handle the error and display on the screen
 
    bool rethrow = ExceptionPolicy.HandleException(ex, "Application Policy");
    if (rethrow)
        throw;
}
catch(DecoderFallbackExceptionex)
{
    // If you know that this Exception would happen you can do what you need to Resolved the exceptoin 
    // Allowing the process to continue or abort
}

But all this brings up the bigger question. Should you not be testing before doing what ever you are doing. Before a DecoderFallbackException happens could there be some pre-testing? In the pure world we don't try to handle know things by way of try,catch and if they are known one should do testing and not catching? In the ture case then a generic exception handler would work because you don't know what it is handling and therefore how would you know how to format the error message for the unknow? If you know what can go wrong then test and display the proper message. If you don't know then let it fail and report what ever error it reports with out special handling because you can't handle the unknown.

PSEUDOCODE 
 
try
{
    File x = File.Open(@"c:\test.txt");
}
catch(FileNotExist)
{
    MessageBox.Show("File Not Found.")
 
}
 
 
or
 
if(Directory.FileExist(@"c:\test.txt")
{
  Message.Box("File Not Found.");
}
else
{
    try
    {
       File x = File.Open(@"c:\test.txt");
    }
    catch(Exception ex)
    {
       MessageBox.Show("Unknow Error {0}", ex.Message);
       return
    }
}
 
OR Even Better Using EntLib
 
if(Directory.FileExist(@"c:\test.txt")
{
  Message.Box("File Not Found.");
  return;
}
else
{
    try
    {
       File x = File.Open(@"c:\test.txt");
    }
    catch(Exception ex)
    {
       // This will trap and handle the error and display on the screen
 
       bool rethrow = ExceptionPolicy.HandleException(ex, "Application Policy");
       if (rethrow)
          throw;    
 
       return;
    }
}
 


Ok, that is my re-hash, I almost fell of the edge and killed my self thinking through this, but that helps to better understand it, no? Now is this the cutting edge or is this the bleeding edge, I don't know which when I fell off of.