[Catalyst] Catching Exceptions

Mark Blythe list at markblythe.com
Mon Apr 3 07:55:40 CEST 2006


Hi,

I'm using Exception::Class, and I'm trying to figure out how to catch
a non-fatal exception thrown by a controller which was called from
another controller via $c->forward().  I started out trying the normal
Exception::Class way:

sub foo1 : Local {
   my ($self, $c) = @_;

   eval {
      $c->forward('foo2');
   };

   if (my $e = MyApp::Exception::Special->caught()) {
      ... some special recovery code ...
   }
}

sub foo2 : Private {
   my ($self, $c) = @_;

   MyApp::Exception::Special->throw(message => 'death!');
}

This fails miserably.  The catching code is never triggered, as if
there was no exception, yet I end up at the Catalyst exception page. 
After a lot of digging, I finally figured out that Catalyst is
intercepting the exception in forward() and *clearing* $@ as well. 
Some experimentation brought me to this solution:

sub foo1 : Local {
   my ($self, $c) = @_;

   $c->forward('foo2');

   if ($c->error()) {
      # restore $@ so Exception::Class will work
      local ($@) = @{$c->error()};

      if (my $e = MyApp::Exception::Special->caught()) {
         ... some special recovery code ...
      }
   }
}

Is this the best solution?  Has anybody else done this a different (better) way?

Thanks -- Mark



More information about the Catalyst mailing list