(You are Anonymous)

Error Handling

How to display simple error message?

What's a good way to abort normal processing and display a simple error message? ([http://www.mail-archive.com/cgiapp@lists.erlbaum.net/msg01082.html archive]) 

I'd like to abort the run-mode method, in mid-stream, and let another one take over. -- Mark Fuller

Return the results of another runmode

(Cees Hek): Inside your runmode return the results of another runmode.

pseudocode:

sub my_runmode {
  my $self = shift;

  if (mysql_call_failed) {
    <b>return $self->error_runmode($mysql_error_message);</b>
  }
  ...
}

sub error_runmode {
  my $self = shift;
  my @errors = @_;

  my $template [= new HTML::Template(filename =]> 'error.tmpl');

  $template->param(errors => [EMAIL PROTECTED]);
  return $template->output()

}

Use eval to trap die in subroutine

(Mark Stosberg): Use eval to trap die in subroutine

If your run mode calls a subroutine, and that subroutine has a problem, things get a little more complicated, since the subroutine could signal that it has an error by returning 'undef', some kind of error message, or just dying.

If the subroutine might die, you could trap that in your run mode:

eval{ $result = _my_tricky_sub() };
return $self->error_runmode($@) if $@;

Generally, I like the design philosophy of detecting errors at a low level, but handing them at a high level. The above design gives you more flexibility to handle errors differently depending on the context.

For example, perhaps you want to run the same tricky subroutine from a cron script, where returning an error message as HTML doesn't make sense.


Let the subroutine die and provide an error_mode

Thilo Planz: Let the subroutine die and provide an error_mode

This is similar to the answer above, except that you do not have to write the eval-block yourself.

Newer versions of CGI::App provide integrated support for catching any exceptions your runmodes could run into. You can define an error_mode to handle the exception in an appropriate manner. It receives the exception (the argument to die(), could be string, could be an object, up to you) as a parameter.


Use CAP::LogDispatch

(Jason Purdy): Use CGI::Application::Plugin::LogDispatch to also let you know

use CGI::Application::Plugin::LogDispatch;

sub setup {
  # ...
  $self->error_mode( 'error' );
}

sub cgiapp_init {
  my ( $self );

  $self = shift;
  $self->log_config(
    LOG_DISPATCH_MODULES => [
      {
        module     => 'Log::Dispatch::Email::MailSend',
        name       => 'email',
        to         => 'admin@example.com',
        subject    => 'CGIApp Emergency Alert Message',
        min_level  => 'emerg',
      }
    ],
    APPEND_NEWLINE => 1,
    );

}

sub error {
  my ( $self, $error, $admin_msg, $message );

  $self = shift;
  $error = $@;

  # Let's also log a critical error!
  $admin_msg = <<_EOF_;
Hey dude,

Just wanted to let you know that we got a critical error sent to the user:

Error Msg: $error
CGIApp Dump:
------------
_EOF_
  $admin_msg .= $self->dump();

  $self->log->emerg( $admin_msg );

  # ... now do the public thing, too ...

}

But there is a problem with this method

Regarding the answer from Thilo Planz above: The error runmode method doesn't get the die argument as a parameter, but as an argument.

sub error_mode {
  my $self = shift;
  my $error = shift;

  return "<html><body>$error</body></html>";
}

Anon Guest - 23 Dec 2004

However, be sure not to use error_mode as the name of your error_mode or you will override the function. Use a name such as display_error or something.

William Mc Kee - 09 Jul 2005