Peter's Gekko

Sponsors

The Lounge

Wicked Cool Jobs

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
What really went wrong ? Check the inner exception

In his recent overview on Exceptions Karl briefly mentioned the inner exception. By passing an exception to the constructor of the new exception, the exception passed in becomes the new exception's InnerException property.

private void workWithFile()
{
    try
    {
        // do something        
    }
    catch (FileNotFoundException ex)
    {
        throw new Exception("Cannot find the file", ex);
    }
}
Code using this method can catch the exception
try
{
    workWithFile();
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

Now this exception caught here does not contain very much useful information. It would be interesting to know the name and location of the missing file. To get at that you have to inspect the inner exception.

try
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
    FileNotFoundException fnfEx = ex.InnerException as FileNotFoundException;
    if (fnfEx != null)
        Console.WriteLine(fnfEx.FileName);
}

Instead of discussing the design issues here (drop the catch in the method and just catch a  FileNotFoundException in the consuming code) I want to take a look on a situation in real life where the inner exception does tell the story.

When initializing a sessionfactory in nHibernate a lot of things can go wrong and will throw an exception. My nHibernatemanger does not handle any of them, so my code will have to check. At first sight this might look OK

try
private void reportException(Exception ex)
{
    Console.Write("* ");
    Console.WriteLine(ex.GetType().ToString());
    Console.WriteLine(ex.Message);
    Console.WriteLine();
}

[Test]
public void CanReportOuterException()
{
    try
    {
        INhibernateHelper nhh = GetNHhelper();
    }
    catch (Exception ex)
    {
        reportException(ex);    
    }
}

Running the code will not make me much wiser

Also here the real information is in an inner exception. As each (inner) exception can have another innerexception my code is going to handle every inner exception it can find

[Test]
public void CanReportAllExceptions()
{
    try
    {
        INhibernateHelper nhh = GetNHhelper();
    }
    catch (Exception ex)
    {
        while (ex != null)
        {
            reportException(ex);
            ex = ex.InnerException;
        }
    }
}

A stack of three exceptions turn up. Together they describe very well what really went wrong. In this case I misspelled the name of the mapping assembly.

I have "misused" resharpers unit test runner to develop this code. In fact the result is much like the testrunner's report on handling an exception not caught by a test.

[Test]
public void CanCreateHelper()
{
    INhibernateHelper nhh = GetNHhelper();
    Assert.IsNotNull(nhh);
}

Note that the runner lists the exception the other way round, starting at the most inner exception.

Instead of delving though the stack of exceptions you could use the ToString() method of the exception. Which results in a bulky string including information on the inner exceptions and more. But this info is not as well structured and misses the type info of the inner exceptions.

I'm not quite sure why nHibernate does wrap its exceptions this way, but what I have learned is to look inside.


Posted Tue, Jun 10 2008 11:10 AM by pvanooijen
Filed under:

[Advertisement]

Comments

Dew Drop – June 10, 2008 | Alvin Ashcraft's Morning Dew wrote Dew Drop – June 10, 2008 | Alvin Ashcraft's Morning Dew
on Tue, Jun 10 2008 8:42 AM

Pingback from  Dew Drop – June 10, 2008 | Alvin Ashcraft's Morning Dew

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Devlicio.us