FlowPDF::Exception

4 minute read

A superclass for exceptions in FlowPDF. All out-of-the box exceptions that are provided by FlowPDF are subclasses of this one. For more details about exceptions and how to use them follow Plugin Developer’s Guide.

All out of the box exceptions should be created using new() method. Each exception has 3 different parameters set for new() method. Two of them are the same across all exceptions:

  • No parameters: new();

  • Scalar error message: new("This is error message");

  • Using hash reference with keys as parameters. This option is described for each exception individually. Note, that not all parameters are required. Keys could be omitted. Only RuntimeException does not have this option.

FlowPDF provides out of the box the following exceptions:

FlowPDF::Exception::UnexpectedEmptyValue

An exception that could be used when something returned an unexpected undef or empty string.

Keys
  • where: A description where it happened.

  • expected: An expected value.

FlowPDF::Exception::UnexpectedEmptyValue->new({ where => 'function result', expected => 'non-empty value' })->throw();

FlowPDF::Exception::MissingFunctionDefinition

An exception, that could be used when class does not have required function defined.

Keys
  • class: A class where function is missing.

  • function: A name of the function, that is not implemented (missing).

FlowPDF::Exception::MissingFunctionDefinition->new({ class => 'MyClass', function => 'mySub' })->throw();

FlowPDF::Exception::MissingFunctionArgument

An exception, that could be used when function expecting required parameter, and this parameter is missing.

Keys
  • argument: An argument, that is missing.

  • functions: A name of the function, that didn’t receive a mandatory argument.

FlowPDF::Exception::MissingFunctionArgument->new({ argument => 'user name', function => 'greetUser' })->throw();

FlowPDF::Exception::WrongFunctionArgumentType

An exception, that could be used when function received an argument, but it has different type.

Keys
  • item argument: An argument, that has a wrong type.

  • function: A name of the function, that received an argument of a wrong type.

  • got: A type of argument that were gotten.

  • expected: An expected type of an argument.

FlowPDF::Exception::MissingFunctionArgument->new({ argument => 'user name', function => 'greetUser', got => 'HASH', expected => 'scalar' })->throw();

FlowPDF::Exception::WrongFunctionArgumentValue

An exception, that could be used when function received an argument, but its value is wrong.

Keys
  • argument: An argument, that has a wrong value.

  • function: A name of the function, that received an argument with a wrong value.

  • got: A value of argument that were gotten.

  • expected: An expected value of an argument.

FlowPDF::Exception::WrongFunctionArgumentValue()->new({ argument => 'user name', function => 'greetUser', got => 'HASH', expected => 'scalar' })->throw();

FlowPDF::Exception::EntityDoesNotExist

An exception, that could be used when something does not exist, but it should. Like key in hash.

Keys:

  • entity: An entity, that does not exist.

  • in: A place, where entity does not exist.

  • function: A name of the function in context of which entity does not exist.

FlowPDF::Exception::EntityDoesNotExist->new({ entity => 'key email', in => 'users array', function => 'newUser' })->throw();

FlowPDF::Exception::EntityAlreadyExists

An exception, that could be used when something exists, but it should not, like user with the same email.

Keys:

  • entity: An entity, that already exists.

  • in: A place, where entity already exists.

  • function: A name of the function in context of which entity already exists.

FlowPDF::Exception::EntityAlreadyExists->new({ entity => 'key email', in => 'users array', function => 'newUser' })->throw();

FlowPDF::Exception::RuntimeException

A generic runtime exception.

FlowPDF::Exception::RuntimeException->new("Error evaluating code.")->throw();

Exception handling in FlowPDF

We strongly recommend to use Try::Tiny for exceptions handling because eval \{} approach has a lot of flaws. One of them is the exception, that was raised during eval \{} is automatically being assigned to global variable $@.

There are too many things that could go wrong with one global variable.

Try::Tiny provides a mechanism that allows to raise exceptions that are lexical variables.

Try::Tiny is available in ec-perl.

For example:

try { ...; } catch { ...; } finally { ...; }

Using out-of-the-box exceptions

To use any of out of the box exceptions you need to import them as regular perl module, then create an exception object (see documentation for an exception that you want create), then throw and then catch. For example, we will be using FlowPDF::Exception::UnexpectedEmptyValue as example.

use strict; use warnings; use Try::Tiny; # 1. Import. use FlowPDF::Exception::UnexpectedEmptyValue; use FlowPDF::Log; try { dangerous(''); } catch { my ($e) = @_; # 3. Validate. if ($e->is('FlowPDF::Exception::UnexpectedEmptyValue')) { # 4. Handle. logInfo("Unexpected empty value caught: $e"); } }; sub dangerous { my ($arg) = @_; unless ($arg) { # 2. Create and throw. FlowPDF::Exception::UnexpectedEmptyValue->new({ where => '1st argument', expected => 'non-empty value' })->throw(); } }

Creating your own exceptions

To create your own exceptions for a plugin, you need to do the following things:

  • Inherit FlowPDF::Exception

  • Define exceptionCode method: exceptionCode method should return a line, that will be used as code for your exception. It could be:

sub exceptionCode { return 'CUST001'; }
  • Define render or template methods. You need to define only one of them. Template method should return sprintf template, which will be used during exception object creation. This template will be interpolated using parameters from new() method. This is simple way. Render method accepts all parameters, that were provided to new() method, but you have to return ready-to-use message. This method is more advanced way of exceptions creation and provides full control. Simple exception using render could be implemented like that:

package FlowPDF::Exception::WithRender; use base qw/FlowPDF::Exception/; use strict; use warnings; sub exceptionCode { return 'WTHRNDR01'; } sub render { my ($class, @params) = @_; my $message = "Following keys are wrong: " . join(', ', @params); return $message; } 1;