[Catalyst] Catching Exceptions

Matt S Trout dbix-class at trout.me.uk
Mon Apr 3 15:38:27 CEST 2006


Mark Blythe wrote:
> 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?

While I much prefer just handling $c->error in my own code (and calling e.g. 
$self->foo2($c) if I want to see thrown exceptions), you might want to have a 
look at Catalyst::Plugin::MortalForward which makes forward die on error.

-- 
      Matt S Trout       Offering custom development, consultancy and support
   Technical Director    contracts for Catalyst, DBIx::Class and BAST. Contact
Shadowcat Systems Ltd.  mst (at) shadowcatsystems.co.uk for more information

+ Help us build a better perl ORM: http://dbix-class.shadowcatsystems.co.uk/ +



More information about the Catalyst mailing list