Froody::Error - Froody error class


Froody documentation Contained in the Froody distribution.

Index


Code Index:

NAME

Top

Froody::Error - Froody error class

SYNOPSIS

Top

  use Froody::Error qw(err);

  # throw an error
  eval { 
    Froody::Error->throw("user.problem", "user '$userid' not known", $data);
  };

  # "user.problem, user '9BC6DD8C-1E25-11DA-98F1-DDB51046DF9C' not known, "
  print $@->code .", ". $@->msg

  # and a stacktrace
  print $@->stacktrace

  # print the data section
  print Dumper $@->data;

  # check if the error is the right class
  if (err("user"))
  {
    ...
  }

DESCRIPTION

Top

Froody::Error is the Froody error class. It's designed to be powerful, yet simple to use. It's a subclass of Error.pm.

Often, the easiest way to create an error response from within Froody is to throw a Froody::Error. This will be caught by the server, and it'll be turned into an error response before dispatching it to the client.

Standard Froody::Error errors that are thrown by Froody itself indicating that something is wrong with Froody (e.g. you've asked for a method that doesn't exist, or you've ommited a required parameter) are listed in Froody::Error::Standard.

throw

To throw an error with Froody::Error you just have to call the throw method with up to three arguments:

  # throw an error with its code, reporting the default message
  Froody::Error->throw("what");

  # throw an error with its code, reporting a custom message
  Froody::Error->throw("what", "bang");

  # throw an error with code, custome message, and some data
  Froody::Error->throw("what", bang", { thingy => "broken" });

In each case this creates a new Froody::Error object and then dies with it.

The first argument is the code that defines the type of error that we're throwing. The second argument is a message, a string which describes the error. If this error is translated to a Froody error response then these will be mapped to the code and message attributes of the <err> repectivly. The third argument is the data, a set of parameters that decribe in a computer understandable format what causes the error. This data potentially will be transformed into the children of the <err> tag based on what specification is in the errortypes of the repository.

Hierarchal Error Messages

Error messages use 'dot' notation to indicate what error messages are sub-types of other error messages.

For example:

  Froody::Error->throw("io", "Bad IO");

And, a more particular error:

  Froody::Error->throw("io.file", "There was a problem with the file");

And an even more particular error

  Froody::Error->throw("io.file.notfound", "File not found");

But all these methods can be detected with isa_err

  if ($@->isa_err("io")) { ... }

Or even better with the err functions (as this won't go "bang" if $@ is a hashref)

  use Froody::Error qw(err);
  if (err("io")) { ... }

METHODS

Top

new( message )

define

code

Return the error code. Read only.

message / msg / text

Returns the error message. Read only.

data

Return (a copy of) the error data. Read only.

stringify

Returns a string containing both the error code and the error text, and a stacktrace. This is what is returned if you try and use a Froody::Error in string context.

BACKWARDS COMPATIBILITY

Top

We used to have a different sort of error. Rather than having hierarchal error codes that looked like this:

  <err code="file.rwerr" message="unable to write to disk" />

We used to use simple numbers and have errors that looked like this:

  <err code="12" message="unable to write to disk" />

This is fine. The key here to remember is that numbered error codes are a subset of the hierarchal error codes. The numbers are all just top level errors that are made up of alphanumerics that are just digits. It's just a not very hierarchal hierarchal error code.

BUGS

Top

None known.

Please report any bugs you find via the CPAN RT system. http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Froody

AUTHOR

Top

Copyright Fotango 2005. All rights reserved.

Please see the main Froody documentation for details of who has worked on this project.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

SEE ALSO

Top

Froody::Error::Standard, Froody::Response::Error


Froody documentation Contained in the Froody distribution.
package Froody::Error;
use base qw(Exporter Error);
our @EXPORT_OK = qw(err);

use strict;
use warnings;

use Scalar::Util qw(blessed);
use Storable;
use YAML::Syck;

# err is documented
sub err
{ 
  no warnings 'uninitialized';
  
  my $code = shift;

  return unless length $@;       # no err? Not an error
  return 1 unless length $code;  # empty spec? Always true
  
  # Froody::Error?  Of the right code?
  if (blessed($@) && $@->isa("Froody::Error"))
    { return $@->isa_err($code) }
  
  # It's an unknown error, were we looking for that?
  # There's no easy way I can see to make this functionality overridable
  # after all, we're in a *function* here, not a method.
  return $code eq "unknown" || $code eq "999";
}

# isa_err is documented
sub isa_err 
{
  no warnings 'uninitialized';

  my $self = shift;
  my $err = shift;

  # empty string === root node === always match
  return 1 unless length $err;

  # if we've no code then we must fail, as we can't possibly match it
  return 0 unless length $self->code;
  
  # do we match? 
  $err = quotemeta($err);
  return $self->code =~ /^$err(?:\.|$)/
}

sub new {
  my $self  = shift;
  local $Error::Debug = 1;
  local $Error::Depth = $Error::Depth + 1;
  my $code    = shift;
  my $text    = shift;
  my $data    = shift;
  $self->SUPER::new(
    -text => $text,
    -code => $code,
    -data => $data,
  );
}

sub code {
  no warnings 'uninitialized';
  length($_[0]->{-code}) ? $_[0]->{-code} : "unknown";
}

sub text    { shift->{-text} }
sub msg     { shift->{-text} }
sub message { shift->{-text} }

sub _dclone {
 return $_[0] unless ref $_[0];
 return Storable::dclone $_[0];
}

sub data { _dclone(shift->{-data}) }

sub stringify {
  no warnings 'uninitialized';
  my $self    = shift;
  
  my $strace = $self->stacktrace;
  $strace =~ s/^/  /mg;
  
  my $return = $self->code;
  $return .= " - " . $self->message if length($self->message);
  # don't call the ->data method here, as we don't really need to clone the data
  $return .= "\nData:\n".Dump($self->{-data}) if defined $self->{-data};
  return $return . "\nStack trace:\n$strace"
}

1;