3 Exception::Lite - light weight exception handling class with smart
4 stack tracing, chaining, and localization support.
8 # --------------------------------------------------------
9 # making this module available to your code
10 # --------------------------------------------------------
12 #Note: there are NO automatic exports
14 use Exception::Lite qw(declareExceptionClass
20 # imports only: declareExceptionClass isException isChainable
21 use Exception::Lite qw(:common);
23 # imports all exportable methods listed above
24 use Exception::Lite qw(:all);
27 # --------------------------------------------------------
28 # declare an exception class
29 # --------------------------------------------------------
32 declareExceptionClass($sClass);
33 declareExceptionClass($sClass, $sSuperClass);
36 declareExceptionClass($sClass, $aFormatRule);
37 declareExceptionClass($sClass, $sSuperClass, $aFormatRule);
39 # with customized subclass
40 declareExceptionClass($sClass, $sSuperClass, 1);
41 declareExceptionClass($sClass, $aFormatRule, 1);
42 declareExceptionClass($sClass, $sSuperClass, $aFormatRule, 1);
44 # --------------------------------------------------------
46 # --------------------------------------------------------
48 die $sClass->new($sMsg, $prop1 => $val1, ...); #no format rule
49 die $sClass->new($prop1 => $val1, ...); #has format rule
53 $e = $sClass->new($sMsg, $prop1 => $val1, ...); #no format rule
54 $e = $sClass->new($prop1 => $val1, ...); #has format rule
58 # --------------------------------------------------------
59 # catch and test an exception
60 # --------------------------------------------------------
62 # Note: for an explanation of why we don't use if ($@)... here,
63 # see Catching and Rethrowing exceptions below
66 .... some code that may die here ...
71 if (isException($e, 'Class1')) {
73 } elsif (isExcption($e, 'Class2')) {
74 ... do something else ...
78 isException($e); # does $e have the above exception methods?
79 isException($e,$sClass) # does $e belong to $sClass or a subclass?
81 # --------------------------------------------------------
82 # getting information about an exception object
83 # --------------------------------------------------------
86 $e->getProperty($sName);
87 $e->isProperty($sName);
88 $e->replaceProperties($hOverride);
98 $e->getSubroutine($i);
101 $e->getPropagation();
105 # --------------------------------------------------------
106 # rethrowing exceptions
107 # --------------------------------------------------------
109 # using original properties and message
111 $@=$e; die; # pure Perl way (reset $@ in case wiped out)
113 die $e->rethrow(); # same thing, but a little less cryptic
116 # overriding original message/properties
118 die $e->rethrow(path=>$altpath, user=>$nameReplacingId);
121 # --------------------------------------------------------
122 # creation of chained exceptions (one triggered by another)
123 # (new exception with "memory" of what caused it and stack
124 # trace from point of cause to point of capture)
125 # --------------------------------------------------------
127 isChainable($e); # can $e be used as a chained exception?
129 die $sClass->new($e, $sMsg, $prop1 => $val1, ...);#no format rule
130 die $sClass->new($e, $prop1 => $val1, ...); #has format rule
132 # --------------------------------------------------------
133 # print out full message from an exception
134 # --------------------------------------------------------
136 print $e # print works
138 print "$e\n"; # double quotes work
139 my $sMsg=$e."\n"; print $sMsg; # . operator works
142 # --------------------------------------------------------
143 # global control variables (maybe set on the command line)
144 # --------------------------------------------------------
146 $Exception::Lite::STRINGIFY #set rule for stringifying messages
148 = 1; # message and file/line where it occured
149 = 2; # 1 + what called what (simplified stack trace)
150 = 3; # 2 + plus any chained exceptions and where message
151 # was caught, if propagated and rethrown
152 = 4; # 3 + arguments given to each call in stack trace
153 = coderef # custom formatting routine
155 $Exception::Lite::TAB # set indentation for stringified
156 # messages, particularly indentation for
157 # call parameters and chained exceptions
159 $Exception::Lite::FILTER
160 = 0 # see stack exactly as Perl does
161 = 1 # remove frames added by eval blocks
162 = coderef # custom filter - see getStackTrace for details
164 # --------------------------------------------------------
165 # controlling the stack trace from the command line
166 # --------------------------------------------------------
168 perl -mException::Lite=STRINGIFY=1,FILTER=0,TAB=4
169 perl -m'Exception::Lite qw(STRINGIFY=1 FILTER=0 TAB=4)'
171 # --------------------------------------------------------
172 # built in exception classes
173 # --------------------------------------------------------
175 # generic wrapper for converting exception strings and other
176 # non-Exception::Lite exceptions into exception objects
178 Exception::Class::Any->new($sMessageText);
180 To assist in debugging and testing, this package also includes
181 two methods that set handlers for die and warn. These methods
182 should I<only> be used temporarily during active debugging. They
183 should not be used in production software, least they interfere
184 with the way other programmers using your module wish to do their
185 debugging and testing.
187 # --------------------------------------------------------
188 # force all exceptions/warnings to use Exception::Lite to
189 # print out messages and stack traces
190 # --------------------------------------------------------
192 # $stringify is the value for EXCEPTION::Lite::STRINGIFY
193 # that you want to use locally to print out messages. It
194 # will have no effect outside of the die handler
196 Exception::Lite::onDie($stringify);
197 Exception::Lite::onWarn($stringify);
201 The C<Exception::Lite> class provides an easy and very light weight
202 way to generate context aware exceptions. It was developed because
203 the exception modules on CPAN as of December,2010 were heavy on
204 features I didn't care for and did not have the features I most
205 needed to test and debug code efficiently.
209 This module provides a light weight but powerful exception class
216 provides an uncluttered stack trace that clearly shows what
217 called what and what exception triggered what other exception.
218 It significantly improves on the readability of the stack trace
219 dumps provided by C<carp> and other exception modules on
220 CPAN (as of 12/2010). For further discussion and a sample, see
221 L</More intelligent stack trace>.
225 gives the user full control over the amount of debugging
226 information displayed when exceptions are thrown.
230 permits global changes to the amount of debugging information
231 displayed via the command line.
235 closely integrates exception classes, messages, and properties
236 so that they never get out of sync with one another. This in
237 turn eliminates redundant coding and helps reduce the cost of
238 writing,validating and maintaining a set of exceptions.
242 is easy to retrofit with native language support, even if this
243 need appears late in the development process.This makes it
244 suitable for use with agile development strategies.
248 act like strings in string context but are in fact objects with
249 a class hierarchy and properties.They can be thrown and rethrown
250 with standard Perl syntax. Like any object, they can be uniquely
251 identified in numeric context where they equal their reference
252 address (the value returned by C<Scalar::Util::refaddr()>.
256 does not interfere with signal handlers or the normal Perl syntax
257 and the assumptions of Perl operators.
261 can be easily extended and subclassed
265 =head2 Lightweight how?
267 Despite these features C<Exception::Lite> maintains its "lite"
274 using only core modules
278 generating tiny exception classes (30-45LOC per class).
282 eliminating excess baggage by customizing generated classes to
283 reflect the actual needs of exception message generation. For
284 instance an exception wrapped around a fixed string message would
285 omit code for message/property integration and would be little
286 more than a string tied to a stack trace and property hash.
290 storing only the minimum amount of stack trace data needed to
291 generate exception messages and avoiding holding onto references
292 from dead stack frames. (Note: some CPAN modules hold onto
293 actual variables from each frame, possibly interfering with
298 doing all its work, including class generation and utilities in
299 a single file that is less than half the size of the next smallest
300 similarly featured all-core exception class on CPAN (support for
301 both properties and a class heirarchy). C<Exception::Lite>
302 contains about 400 lines when developer comments are excluded). The
303 next smallest all core module is L<Exception::Base|Exception::Base>
304 which clocks in at just over 1000 lines after pod and developer
305 comments are excluded).
309 avoiding a heavy-weight base class. Code shared by
310 C<Exception::Lite> classes are stored in function calls that total
311 230 or so lines of code relying on nothing but core modules. This
312 is significantly less code than is needed by the two CPAN packages
313 with comparable features. The all core
314 L<Exception::Base|Exception::Base> class contains 700+ lines of
315 code. The base class of L<Exception::Class|Exception::Class> has
316 200 lines of its own but drags in two rather large non-core
317 modules as dependencies: L<Devel::StackTrace|Devel::StackTrace>
318 L<Class::Data::Inheritable|Class::Data::Inheritable>.
322 C<Exception::Lite> has more features (chaining, message/property
323 integration) but less code due to the following factors:
329 working with Perl syntax rather than trying to replace it.
333 using a light approach to OOP - exception classes have just enough
334 and no more OO features than are needed to be categorized by a
335 class, participate in a class heirarchy and to have properties.
339 respecting separation of concerns. C<Exception::Lite> focuses
340 on the core responsibility of an exception and leaves the bulk of
341 syntax creation (e.g. Try/Catch) to specialist modules like
342 L<Try::Tiny|Try::Tiny>. Other modules try to double as
343 comprehensive providers of exception related syntactic sugar.
347 not trying to be the only kind of exception that an application
354 =head2 Defining Exception Classes
356 C<Exception::Lite> provides two different ways to define messages.
357 The first way, without a format rule, lets you compose a freeform
358 message for each exception. The second way, with a format rule,
359 lets you closely integrate messages and properties and facilitates
360 localization of messages for any packages using your software.
362 =head3 Defining freeform messages
364 If you want to compose a free form message for each and every
365 exception, the class declaration is very simple:
367 declareExceptionClass($sClass);
368 declareExceptionClass($sClass, $sSuperClass);
370 # with customized subclass
371 declareExceptionClass($sClass, $sSuperClass, 1);
373 C<$sClass> is the name of the exception class.
375 C<$sSuperClass> is the name of the superclass, if there is one.
376 The superclass can be any class created by C<Exception::Lite>. It
377 can also be any role class, i.e. a class that has methods but no
378 object data of its own.
380 The downside of this simple exception class is that there is
381 absolutely no integration of your messages and any properties that
382 you assign to the exception. If you would like to see your property
383 values included in the message string,consider using a formatted
386 =head3 Defining formatted messages
388 If you wish to include property values in your messages, you need
389 to declare a formatted message class. To do this, you define a
390 format rule and pass it to the constructor:
392 $aFormatRule = ['Cannot copy %s to %s', qw(from to) ];
394 declareExceptionClass($sClass, $aFormatRule);
395 declareExceptionClass($sClass, $sSuperClass, $aFormatRule);
397 # with customized subclass
398 declareExceptionClass($sClass, $aFormatRule, 1);
399 declareExceptionClass($sClass, $sSuperClass, $aFormatRule, 1);
401 Format rules are nothing more than a sprintf message string
402 followed by a list of properties in the same order as the
403 placeholders in the message string. Later on when an exception
404 is generated, the values of the properties will replace the
405 property names. Some more examples of format rules:
408 $aFormatRule = ['Illegal argument <%s>: %s', qw(arg reason)];
409 declareExceptionClass('BadArg', $aFormatRule);
411 $aFormatRule = ['Cannot open file <%s>> %s', qw(file reason)];
412 declareExceptionClass('OpenFailed', $aFormatRule);
414 $sFormatRule = ['Too few %s, must be at least %s', qw(item min)];
415 declareExceptionClass('TooFewWidgets', $aFormatRule);
418 Later on when you throw an exception you can forget about the message
419 and set the properties, the class will do the rest of the work:
421 die BadArg->new(arg=>$sPassword, reason=>'Too few characters');
424 open(my $fh, '>', $sFile)
425 or die OpenFailed->new(file=>$sFile, reason=>$!);
427 And still later when you catch the exception, you have two kinds
428 of information for the price of one:
430 # if you catch BadArg
432 $e->getProperty('arg') # mine
433 $e->getProperty('reason') # too few characters
434 $e->getMessage() # Illegal argument <mine>: too few characters
437 # if you catch OpenFailed
439 $e->getProperty('file') # foo.txt
440 $e->getProperty('reason') # path not found
441 $e->getMessage() # Cannot open <foo.txt>: path not found
444 =head2 Creating and throwing exceptions
446 When it comes times to create an exception, you create and
447 throw it like this (C<$sClass> is a placeholder for the name of
448 your exception class);
451 die $sClass->new($sMsg, prop1 => $val1, ...); #no format rule
452 die $sClass->new(prop1 => $val1, ...); #has format rule
456 $e = $sClass->new($sMsg, prop1 => $val1, ...); #no format rule
457 $e = $sClass->new(prop1 => $val1, ...); #has format rule
464 # Freeform exceptions (caller composes message, has message
465 # parameter ($sMsg) before the list of properties)
467 close $fh or die UnexpectedException
468 ->new("Couldn't close file handle (huh?): $!");
470 die PropertySettingError("Couldn't set property"
471 , prop=>foo, value=>bar);
473 # Formatted exceptions (no $sMsg parameter)
475 if (length($sPassword) < 8) {
476 die BadArg->new(arg=>$sPassword, reason=>'Too few characters');
479 open(my $fh, '>', $sFile)
480 or die OpenFailed->new(file=>$sFile, reason=>$!);
482 In the above examples the order of the properties does not matter.
483 C<Exception::Lite> is using the property names, not the order of
484 the properties to find the right value to plug into the message
487 =head2 Catching and testing exceptions
489 In Perl there are two basic ways to work with exceptions:
493 * Java like syntax (requires non-core modules)
495 =head3 Catching exceptions the Java way
497 Java uses the following idiom to catch exceptions:
500 .... some code here ...
501 } catch (SomeExceptionClass e) {
502 ... error handling code here ...
503 } catch (SomeOtherExceptionClass e) {
504 ... error handling code here ...
506 ... cleanup code here ...
509 There are several CPAN modules that provide some sort of syntactic
510 sugar so that you can emulate java syntax. The one recommended
511 for C<Exception::Lite> users is L<Try::Tiny|Try::Tiny>.
512 L<Try::Tiny|Try::Tiny> is an elegant class that concerns itself
513 only with making it possible to use java-like syntax. It can be
514 used with any sort of exception.
516 Some of the other CPAN modules that provide java syntax also
517 require that you use their exception classes because the java like
518 syntax is part of the class definition rather than a pure
519 manipulation of Perl syntax.
522 =head3 Catching exceptions the Perl way
524 The most reliable and fastest way to catch an exception is to use
531 # save $@ before using it - it can easily be clobbered
534 ... do something with the exception ...
536 warn $e; #use $e as a string
537 warn $e->getMessage(); # use $e as an object
541 The C<eval> block ends with C<return 1;> to insure that successful
542 completion of the eval block never results in an undefined value.
543 In certain cases C<undef> is a valid return value for a statement,
544 We don't want to enter the C<do> block for any reason other than
547 C< eval/do > is both faster and more reliable than the C< eval/if>
548 which is commonly promoted in Perl programming tutorials:
555 It is faster because the C<do> block is executed if and only
556 if the eval fails. By contrast the C<if> must be evaluated both
557 in cases of succes and failure.
559 C< eval/do > is more reliable because the C<do> block is guaranteed
560 to be triggered by any die, even one that accidentally throws undef
561 or '' as the "exception". If an exception is thrown within the C<eval>
562 block, it will always evaluate to C<undef> therefore triggering the
565 On the other hand we can't guarentee that C<$@> will be defined
566 even if an exception is thrown. If C<$@> is C<0>, C<undef>, or an
567 empty string, the C<if> block will never be entered. This happens
568 more often then many programmers realize. When eval exits the
569 C< eval > block, it calls destructors of any C<my> variables. If
570 any of those has an C< eval > statement, then the value of C<$@> is
571 wiped clean or reset to the exception generated by the destructor.
573 Within the C<do> block, it is a good idea to save C<$@> immediately
574 into a variable before doing any additional work. Any subroutine
575 you call might also clobber it. Even built-in commands that don't
576 normally set C<$@> can because Perl lets a programmer override
577 built-ins with user defined routines and those user define routines
578 might set C<$@> even if the built-in does not.
580 =head3 Testing exceptions
582 Often when we catch an exception we want to ignore some, rethrow
583 others, and in still other cases, fix the problem. Thus we need a
584 way to tell what kind of exception we've caught. C<Exception::Lite>
585 provides the C<isException> method for this purpose. It can be
586 passed any exception, including scalar exceptions:
588 # true if this exception was generated by Exception::Line
592 # true if this exception belongs to $sClass. It may be a member
593 # of the class or a subclass. C<$sClass> may be any class, not
594 # just an Exception::Lite generated class. You can even use this
595 # method to test for string (scalar) exceptions:
597 isException($e,$sClass);
599 isException($e,'Excption::Class');
600 isException($e, 'BadArg');
603 And here is an example in action. It converts an exception to a
604 warning and determines how to do it by checing the class.
612 if (Exception::Lite::isException($e)) {
614 # get message w/o stack trace, "$e" would produce trace
615 warn $e->getMessage();
617 } elsif (Exception::Lite::isException('Exception::Class') {
619 # get message w/o stack trace, "$e" would produce trace
622 } elsif (Exception::Lite::isException($e,'')) {
628 =head2 Rethrowing exceptions
630 Perl doesn't have a C<rethrow> statement. To reliably rethrow an
631 exception, you must set C<$@> to the original exception (in case it
632 has been clobbered during the error handling process) and then call
633 C<die> without any arguments.
647 The above code will cause the exception's C<PROPAGATE> method to
648 record the file and line number where the exception is rethrown.
649 See C<getLine>, C<getFile>, and C<getPropagation> in the class
650 reference below for more information.
652 As this Perl syntax is not exactly screaming "I'm a rethrow",
653 C<Exception::Lite> provides an alternative and hopefully more
654 intuitive way of propagating an exception. There is no magic here,
655 it just does what perl would do had you used the normal syntax,
656 i.e. call the exception's C<PROPAGATE> method.
668 =head2 Chaining Messages
670 As an exception moves up the stack, its meaning may change. For
671 example, suppose a subroutine throws the message "File not open".
672 The immediate caller might be able to use that to try and open
673 a different file. On the other hand, if the message gets thrown
674 up the stack, the fact that a file failed to open might not
675 have any meaning at all. That higher level code only cares that
676 the data it needed wasn't available. When it notifies the user,
677 it isn't going to say "File not found", but "Can't run market
678 report: missing data feed.".
680 When the meaning of the exception changes, it is normal to throw
681 a new exception with a class and message that captures the new
682 meaning. However, if this is all we do, we lose the original
683 source of the problem.
685 Enter chaining. Chaining is the process of making one exception
686 "know" what other exception caused it. You can create a new
687 exception without losing track of the original source of the
690 To chain exceptions is simple: just create a new exception and
691 pass the caught exception as the first parameter to C<new>. So
692 long as the exception is a non-scalar, it will be interpreted
693 as a chained exception and not a property name or message text
694 (the normal first parameter of C<new>).
696 Chaining is efficient, especially if the chained exception is
697 another C<Exception::Lite> exception. It does not replicate
698 the stack trace. Rather the original stack trace is shorted to
699 include only the those fromes frome the time it was created to
700 the time it was chained.
702 Any non-scalar exception can be chained. To test whether or not
703 a caught exception is chainable, you can use the method
704 C<isChainable>. This method is really nothing more than
705 a check to see if the exception is a non-scalar, but it helps
706 to make your code more self documenting if you use that method
707 rather than C<if (ref($e))>.
709 If an exception isn't chainable, and you still want to chain
710 it, you can wrap the exception in an exception class. You
711 can use the built-in C<Exception::Class::Any> or any class of
714 #-----------------------------------------------------
715 # define some classes
716 #-----------------------------------------------------
719 declareExceptionClass('HouseholdDisaster');
722 declareExceptionClass('ProjectDelay'
723 , ['The project was delayed % days', qw(days)]);
725 #-----------------------------------------------------
726 # chain some exceptins
727 #-----------------------------------------------------
730 .... some code here ...
734 if (Exception::Lite::isChainable($e)) {
735 if (Exception::Lite::isException($e, 'FooErr') {
736 die 'SomeNoFormatException'->new($e, "Caught a foo");
738 die 'SomeFormattedException'->new($e, when => 'today');
740 } elsif ($e =~ /fire/) {
741 die 'Exception::Lite::Any'->new($e);
742 die 'SomeFormattedException'->new($e, when => 'today');
744 # rethrow it since we can't chain it
749 =head2 Reading Stack Traces
751 At its fullest level of detail, a stack trace looks something
754 Exception! Mayhem! and then ...
756 thrown at file Exception/Lite.t, line 307
757 in main::weKnowBetterThanYou, pid=24986, tid=1
758 @_=('ARRAY(0x83a8a90)'
762 ,'There will be no more talking to hoos who are not!'
763 ,'black bottom birdie'
764 ,'from the three billionth flower'
765 ,'Mrs Tucanella returns with uncles and cousins'
766 ,'sound off! sound off! come make yourself known!'
768 ,'Jo Jo the young lad'
769 ,'the whole world was saved by the smallest of all'
771 reached via file Exception/Lite.t, line 281
772 in main::notAWhatButAWho
774 reached via file Exception/Lite.t, line 334 in main::__ANON__
776 reached via file Exception/Lite.t, line 335 in <package: main>
780 Exception! Horton hears a hoo!
781 rethrown at file Exception/Lite.t, line 315
783 thrown at file Exception/Lite.t, line 316
784 in main::horton, pid=24986, tid=1
787 ,'a small speck of dust on a small clover'
788 ,'a person's a person no matter how small'
790 reached via file Exception/Lite.t, line 310 in main::hoo
796 reached via file Exception/Lite.t, line 303
797 in main::weKnowBetterThanYou
798 @_=('ARRAY(0x83a8a90)'
802 ,'There will be no more talking to hoos who are not!'
803 ,'black bottom birdie'
804 ,'from the three billionth flower'
805 ,'Mrs Tucanella returns with uncles and cousins'
806 ,'sound off! sound off! come make yourself known!'
808 ,'Jo Jo the young lad'
809 ,'the whole world was saved by the smallest of all'
817 lines begining with "thrown" indicate a line where a new exception
818 was thrown. If an exception was chained, there might be multiple
823 lines beginning with "reached via" indicate the path travelled
824 I<down> to the point where the exception was thrown. This is the
825 code that was excuted before the exception was triggered.
829 lines beginning with "rethrown at" indicate the path travelled
830 I<up> the stack by the exception I<after> it was geenerated. Each
831 line indicates a place where the exception was caught and rethrown.
835 lines introduced with "Triggered by" are exceptions that were
836 chained together. The original exception is the last of the
837 triggered exceptions. The original line is the "thrown" line
838 for the original exception.
842 C<@_> and <C@ARGV> below a line indicates what is left of the
843 parameters passed to a method, function or entry point routine.
844 In ideal circumstances they are the parameters passed to the
845 subroutine mentioned in the line immediately above C<@_>. In
846 reality, they can be overwritten or shifted away between the
847 point when the subroutine started and the line was reached.
849 Note: if you use L<Getopt::Long> to process C<@ARGV>, C<@ARGV>
850 will be empty reduced to an empty array. If this bothers you, you
851 can localize <@ARGV> before calling C<GetOptions>, like this:
856 GetOptions(\%hARGV,...);
861 pid is the process id where the code was running
865 tid is the thread id where the code was running
869 =head1 SPECIAL TOPICS
871 =head2 Localization of error messages
873 Rather than treat the error message and properties as entirely
874 separate entities, it gives you the option to define a format string
875 that will take your property values and insert them automatically
876 into your message. Thus when you generate an exception, you can
877 specify only the properties and have your message automatically
878 generated without any need to repeat the property values in messy
879 C<sprintf>'s that clutter up your program.
881 One can localize from the very beginning when one declares the
882 class or later on after the fact if you are dealing with legacy
883 software or developing on an agile module and only implementing
886 To localize from the get-go:
888 # myLookupSub returns the arguments to declareException
889 # e.g. ('CopyError', [ 'On ne peut pas copier de %s a %s'
892 declareExceptionClass( myLookupSub('CopyError', $ENV{LANG}) );
895 # .... later on, exception generation code doesn't need to
896 # know or care about the language. it just sets the properties
899 # error message depends on locale:
900 # en_US: 'Cannot copy A.txt to B.txt'
901 # fr_FR: 'On ne peut pas copier de A.txt a B.txt'
902 # de_DE: 'Kann nicht kopieren von A.txt nach B.txt'
904 die 'CopyError'->new(from => 'A.txt', to => 'B.txt');
907 Another alternative if you wish to localize from the get-go is
908 to pass a code reference instead of a format rule array. In this
909 case, C<Exception::Lite> will automatically pass the class name
910 to the subroutine and retrieve the value returned.
913 # anothherLookupSub has parameters ($sClass) and returns
914 # a format array, for example:
916 # %LOCALE_FORMAT_HASH = (
918 # en_US => ['Cannot copy %s to %s', qw(from to)]
919 # ,fr_FR => ['On ne peut pas copier de %s a %s', qw(from to)]
920 # ,de_DE => ['Kann nicht kopieren von %s nach %s''
926 # sub anotherLookupSub {
928 # my $sLocale = $ENV{LANG}
929 # return $LOCALE_FORMAT_HASH{$sClass}{$sLocale};
933 declareExceptionClass('CopyError', &anotherLookupSub);
934 declareExceptionClass('AddError', &anotherLookupSub);
937 # error message depends on locale:
938 # en_US: 'Cannot copy A.txt to B.txt'
939 # fr_FR: 'On ne peut pas copier de A.txt a B.txt'
940 # de_DE: 'Kann nicht kopieren von A.txt nach B.txt'
942 die CopyError->new(from => 'A.txt', to => 'B.txt');
943 die AddError->new(path => 'C.txt');
946 If you need to put in localization after the fact, perhaps for a
947 new user interface you are developing, the design pattern might
950 # in the code module you are retrofitting would be an exception
951 # that lived in a single language world.
953 declareExceptionClass('CopyError'
954 ['Cannot copy %s to %s', [qw(from to)]);
957 # in your user interface application.
959 if (isException($e, 'CopyError') && isLocale('fr_FR')) {
960 my $sFrom = $e->getProperty('from');
961 my $sTo = $e->getProperty('to');
962 warn sprintf('On ne peut pas copier de %s a %s', $sFrom,$sTo);
965 =head2 Controlling verbosity and stack tracing
967 You don't need to print out the fully verbose stack trace and in
968 fact, by default you won't. The default setting, prints out
969 only what called what. To make it easier to see what called what,
970 it leaves out all of the dumps of C<@_> and C<@ARGV>.
972 If you want more or less verbosity or even an entirely different
973 trace, C<Exception::Lite> is at your sevice. It provides a variety
974 of options for controlling the output of the exception:
976 * Adjusting the level of debugging information when an exception is
977 thrown by setting C<$Exception::Lite::STRINGIFY>
978 in the program or C<-mException::Lite=STRINGIFY=level> on the
979 command line. This can be set to either a verbosity level or to
980 an exception stringification routine of your own choosing.
982 * Control which stack frames are displayed by setting
983 C<$Exception::Lite::FILTER>. By default, only calls within named
984 and anonymous subroutines are displayed in the stack trace. Perl
985 sometimes creates frames for blocks of code within a subroutine.
986 These are omitted by default. If you want to see them, you can
987 turn filterin off. Alternatively you can set up an entirely
988 custon stack filtering rule by assigning a code reference to
989 C<$Exception::Lite::FILTER>.
991 * By default, exceptions store and print a subset of the data
992 available for each stack frame. If you would like to display
993 richer per-frame information, you can do that too. See below
996 =head3 Verbosity level
998 The built-in rules for displaying exceptions as strings offer five
1001 * 0: Just the error message
1003 * 1: the error message and the file/line number where it occured
1004 along with pid and tid.
1006 * 2: the error message and the calling sequence from the point where
1007 the exception was generated to the package or script entry point
1008 The calling sequence shows only file, line number and the name
1009 of the subroutine where the exception was generated. It is not
1010 cluttered with parameters, making it easy to scan.
1012 * 3: similar to 2, except that propagation and chained exceptions
1015 * 4: same as 3, except that the state of C<@_> or C<@ARGV> at the
1016 time the exception was thrown is also displayed. usually this
1017 is the parameters that were passed in, but it may include several
1018 leading C<undef> if C<shift> was used to process the parameter
1021 Here are some samples illustrating different level of debugging
1022 information and what happens when the filter is turned off
1024 #---------------------------------------------------
1025 #Sample exception STRINGIFY=0 running on thread 5
1026 #---------------------------------------------------
1028 Exception! Mayhem! and then ...
1030 #---------------------------------------------------
1031 #Sample exception STRINGIFY=1 running on thread 5
1032 #---------------------------------------------------
1034 Exception! Mayhem! and then ...
1035 at file Exception/Lite.t, line 307 in main::weKnowBetterThanYou, pid=24986, tid=5
1037 #---------------------------------------------------
1038 #Sample exception STRINGIFY=2 running on thread 4
1039 #---------------------------------------------------
1041 Exception! Mayhem! and then ...
1042 at file Exception/Lite.t, line 307 in main::weKnowBetterThanYou, pid=24986, tid=4
1043 via file Exception/Lite.t, line 281 in main::notAWhatButAWho
1044 via file Exception/Lite.t, line 373 in main::__ANON__
1045 via file Exception/Lite.t, line 374 in <package: main>
1047 #---------------------------------------------------
1048 #Sample exception STRINGIFY=3 running on thread 3
1049 #---------------------------------------------------
1051 Exception! Mayhem! and then ...
1053 thrown at file Exception/Lite.t, line 307 in main::weKnowBetterThanYou, pid=24986, tid=3
1054 reached via file Exception/Lite.t, line 281 in main::notAWhatButAWho
1055 reached via file Exception/Lite.t, line 362 in main::__ANON__
1056 reached via file Exception/Lite.t, line 363 in <package: main>
1059 Exception! Horton hears a hoo!
1060 rethrown at file Exception/Lite.t, line 315
1062 thrown at file Exception/Lite.t, line 316 in main::horton, pid=24986, tid=3
1063 reached via file Exception/Lite.t, line 310 in main::hoo
1064 reached via file Exception/Lite.t, line 303 in main::weKnowBetterThanYou
1066 #---------------------------------------------------
1067 #Sample exception STRINGIFY=3 running on thread 2
1068 #FILTER=OFF (see hidden eval frames)
1069 #---------------------------------------------------
1071 Exception! Mayhem! and then ...
1073 thrown at file Exception/Lite.t, line 307 in main::weKnowBetterThanYou, pid=24986, tid=2
1074 reached via file Exception/Lite.t, line 281 in main::notAWhatButAWho
1075 reached via file Exception/Lite.t, line 348 in (eval)
1076 reached via file Exception/Lite.t, line 348 in main::__ANON__
1077 reached via file Exception/Lite.t, line 350 in (eval)
1078 reached via file Exception/Lite.t, line 350 in <package: main>
1081 Exception! Horton hears a hoo!
1082 rethrown at file Exception/Lite.t, line 315
1084 thrown at file Exception/Lite.t, line 316 in main::horton, pid=24986, tid=2
1085 reached via file Exception/Lite.t, line 310 in (eval)
1086 reached via file Exception/Lite.t, line 315 in main::hoo
1087 reached via file Exception/Lite.t, line 303 in (eval)
1088 reached via file Exception/Lite.t, line 305 in main::weKnowBetterThanYou
1090 #---------------------------------------------------
1091 #Sample exception STRINGIFY=4 running on thread 1
1093 #---------------------------------------------------
1095 Exception! Mayhem! and then ...
1097 thrown at file Exception/Lite.t, line 307 in main::weKnowBetterThanYou, pid=24986, tid=1
1098 @_=('ARRAY(0x83a8a90)'
1100 ,'Wikerson brothers'
1102 ,'There will be no more talking to hoos who are not!'
1103 ,'black bottom birdie'
1104 ,'from the three billionth flower'
1105 ,'Mrs Tucanella returns with Wikerson uncles and cousins'
1106 ,'sound off! sound off! come make yourself known!'
1108 ,'Jo Jo the young lad'
1109 ,'the whole world was saved by the tiny Yopp! of the smallest of all'
1111 reached via file Exception/Lite.t, line 281 in main::notAWhatButAWho
1113 reached via file Exception/Lite.t, line 334 in main::__ANON__
1115 reached via file Exception/Lite.t, line 335 in <package: main>
1119 Exception! Horton hears a hoo!
1120 rethrown at file Exception/Lite.t, line 315
1122 thrown at file Exception/Lite.t, line 316 in main::horton, pid=24986, tid=1
1125 ,'a small speck of dust on a small clover'
1126 ,'a person's a person no matter how small'
1128 reached via file Exception/Lite.t, line 310 in main::hoo
1134 reached via file Exception/Lite.t, line 303 in main::weKnowBetterThanYou
1135 @_=('ARRAY(0x83a8a90)'
1137 ,'Wikerson brothers'
1139 ,'There will be no more talking to hoos who are not!'
1140 ,'black bottom birdie'
1141 ,'from the three billionth flower'
1142 ,'Mrs Tucanella returns with Wikerson uncles and cousins'
1143 ,'sound off! sound off! come make yourself known!'
1145 ,'Jo Jo the young lad'
1146 ,'the whole world was saved by the tiny Yopp! of the smallest of all'
1150 =head3 Custom stringification subroutines
1152 The custom stringification subroutine expects one parameter, the
1153 exception to be stringified. It returns the stringified form of
1154 the exception. Here is an example of a fairly silly custom
1155 stringification routine that just prints out the chained messages
1156 without any stack trace:
1158 $Exception::Lite::STRINGIFY = sub {
1159 my $e=$_[0]; # exception is sole input parameter
1162 $sMsg .= $e->getMessage() . "\n";
1163 $e= $e->getChained();
1165 return $sMsg; # return string repreentation of message
1168 =head3 Adding information to the stack trace
1170 By default, each frame of the stack trace contains only the file,
1171 line, containing subroutine, and the state of C<@_> at the time
1172 C<$sFile>,C<$iLine> was reached.
1174 If your custom subroutine needs more information about the stack
1175 than C<Exception::Lite> normally provides, you can change the
1176 contents of the stack trace by assigning a custom filter routine
1177 to C<$Exception::Lite::FILTER>.
1179 The arguments to this subroutine are:
1182 ($iFrame, $sFile, $iLine $sSub, $aArgs, $iSubFrame, $iLineFrame)
1186 * C<$sFile> is the file of the current line in that frame
1188 * C<$iLine> is the line number of current line in that frame
1190 * C<$sSub> is the name of the subroutine that contains C<$sFile> and
1193 * C<$aArgs> is an array that holds the stringified value of each
1194 member of @_ at the time the line at C<$sFile>, C<$sLine> was
1195 called. Usually, this is the parameters passed into C<$sSub>,
1198 * C<$iSubFrame> is the stack frame that provided the name of the sub
1199 and the contents of $aArgs.
1201 * C<$iLineFrame> is the stack frame that provided the file and line
1202 number for the frame.
1204 Please be aware that each line of the stack trace passed into the
1205 filter subroutine is a composite drawn from two different frames of
1206 the Perl stack trace, C<$iSubFrame> and C<$iLineFrame>. This
1207 composition is necessary because the Perl stack trace contains the
1208 subroutine that was called at C<$sFile>, C<$iLine> rather than the
1209 subroutine that I<contains> C<$sFile>,C<$iLine>.
1211 The subroutine returns 0 or any other false value if the stack frame
1212 should be omitted. It returns to 1 accept the default stack frame as
1213 is. If it accepts the stack frame but wants to insert extra data
1214 in the frame, it returns
1215 C<[$sFile,$iLine,$sSub,$aArgs, $extra1, $extra2, ...]>
1217 The extra data is always placed at the end after the C<$aArgs>
1220 =head3 Stack trace filtering
1222 To avoid noise, by default, intermediate frames that are associated
1223 with a block of code within a subroutine other than an anonymous
1224 sub (e.g. the frame created by C<eval {...} or do {...} >) are
1225 omitted from the stack trace.
1227 These omissions add to readability for most debugging purposes.
1228 In most cases one just wants to see which subroutine called which
1229 other subroutine. Frames created by eval blocks don't provide
1230 useful information for that purpose and simply clutter up the
1233 However, there are situations where one either wants more or less
1234 stack trace filtering. Stack filtering can turned on or off or
1235 customized by setting C<$Exception::Lite::FILTER> to any of the
1238 Normally the filtering rule is set at the start of the program or
1239 via the command line. It can also be set anywhere in code, with one
1240 caveat: an error handling block.
1246 Turns all filtering off so that you see each and every frame
1251 Turns on filtering of eval frames only (default)
1253 =item C<[ regex1, regex2, ... ]>
1255 A list of regexes. If the fully qualified subroutine name matches
1256 any one of these regular expressions it will be omitted from the
1261 A single regular expression. If the fully qualified subroutine name
1262 matches this regular expression, it will be omitted from the stack
1265 =item C<$codeReference>
1267 The address of a named or anonymous routine that returns a boolean
1268 value: true if the frame should be includeed, false if it should be
1269 omitted. For parameters and return value of this subroutine see
1270 L</Adding information to the stack trace>.
1275 If filtering strategies change and an exception is chained, some of
1276 its stack frames might be lost during the chaining process if the
1277 filtering strategy that was in effect when the exception was
1278 generated changes before it is chained to another exception.
1283 To declare a subclass with custom data and methods, use a three step
1290 choose an exception superclass. The choice of superclass follows
1291 the rule, "like gives birth to like". Exception superclasses that
1292 have formats must have a superclass that also takes a format.
1293 Exception subclasses that have no format, must use an exception.
1297 call C<declareExceptionClass> with its C<$bCustom> parameter set
1302 define a C<_new(...)> method (note the leading underscore _) and
1303 subclass specific methods in a block that sets the package to
1304 the subclass package.
1309 When the C<$bCustom> flag is set to true, it might be best to think
1310 of C<declareExceptionClass> as something like C<use base> or
1311 C<use parent> except that there is no implicit BEGIN block. Like
1312 both these methods it handles all of the setup details for the
1313 class so that you can focus on defining methods and functionality.
1315 Wnen C<Exception::Lite> sees the C<$bCustom> flag set to true, it
1316 assumes you plan on customizing the class. It will set up inhertance,
1317 and generate all the usual method definition for an C<Exception::Lite>
1318 class. However, on account of C<$bCustom> being true, it will add a
1319 few extra things so that and your custom code can play nicely
1326 a special hash reserved for your subclsses data. You can get
1327 access to this hash by calling C<_p_getSubclassData()>. You are
1328 free to add, change, or remove entries in the hash as needed.
1332 at the end of its C<new()> method, it calls
1333 C<< $sClass->_new($self) >>. This is why you must define a C<_new()>
1334 method in your subclass package block. The C<_new> method is
1335 responsible for doing additional setup of exception data. Since
1336 this method is called last it can count on all of the normally
1337 expected methods and data having been set up, including the
1338 stack trace and the message generated by the classes format rule
1343 For example, suppose we want to define a subclass that accepts
1346 #define a superclass that accepts formats
1348 declareExceptionClass('AnyError'
1349 , ['Unexpected exception: %s','exception']);
1352 # declare Exception subclass
1354 declareExceptionClass('TimedException', 'AnyError', $aFormatData,1);
1356 package TimedException;
1359 my $self = $_[0]; #exception object created by Exception::Lite
1361 # do additional setup of properties here
1362 my $timestamp=time();
1363 my $hMyData = $self->_p_getSubclassData();
1364 $hMyData->{when} = time();
1369 return $self->_p_getSubclassData()->{when};
1374 Now suppose we wish to extend our custom class further. There is
1375 no difference in the way we do things just because it is a subclass
1376 of a customized C<Exception::Lite> class:
1378 # extend TimedException further so that it
1380 # - adds two additional bits of data - the effective gid and uid
1381 # at the time the exception was thrown
1382 # - overrides getMessage() to include the time, egid, and euid
1384 declareExceptionClass('SecureException', 'TimedException'
1387 package TimedException;
1390 my $self = $_[0]; #exception object created by Exception::Lite
1392 # do additional setup of properties here
1393 my $timestamp=time();
1394 my $hMyData = $self->_p_getSubclassData();
1395 $hMyData->{euid} = $>;
1396 $hMyData->{egid} = $);
1401 return $self->_p_getSubclassData()->{euid};
1405 return $self->_p_getSubclassData()->{egid};
1409 my $sMsg = $self->SUPER::getMessage();
1410 return sprintf("%s at %s, euid=%s, guid=%s", $sMsg
1411 , $self->getWhen(), $self->getEuid(), $self->getGuid());
1415 =head2 Converting other exceptions into Exception::Lite exceptions
1417 If you decide that you prefer the stack traces of this package, you
1418 can temporarily force all exceptions to use the C<Exception::Lite>
1419 stack trace, even those not generated by your own code.
1421 There are two ways to do this:
1423 * production code: chaining/wrapping
1425 * active debugging: die/warn handlers
1428 =head3 Wrapping and chaining
1430 The preferred solution for production code is wrapping and/or
1431 chaining the exception. Any non-string exception, even one
1432 of a class not created by C<Exception::Lite> can be chained
1433 to an C<Exception::Lite> exception.
1435 To chain a string exception, you first need to wrap it in
1436 an exception class. For this purpose you can create a special
1437 purpose class or use the generic exception class provided by
1438 the C<Exception::Lite> module: C<Exception::Lite::Any>.
1440 If you don't want to chain the exception, you can also just
1441 rethrow the wrapped exception, as is. Some examples:
1443 #-----------------------------------------------------
1444 # define some classes
1445 #-----------------------------------------------------
1448 declareExceptionClass('HouseholdRepairNeeded');
1451 declareExceptionClass('ProjectDelay'
1452 , ['The project was delayed % days', qw(days)]);
1454 #-----------------------------------------------------
1455 # chain and/or wrap some exceptins
1456 #-----------------------------------------------------
1459 .... some code here ...
1464 if (Exception::Lite::isChainable($e)) {
1465 if ("$e" =~ /project/) {
1467 # chain formatted message
1468 die 'ProjectDelay'->new($e, days => 3);
1470 } elsif ("$e" =~ /water pipe exploded/) {
1472 # chain unformatted message
1473 die 'HouseholdRepairNeeded'->new($e, 'Call the plumber');
1476 } elsif ($e =~ 'repairman') { #exception is a string
1478 # wrapping a scalar exception so it has the stack trace
1479 # up to this point, but _no_ chaining
1481 # since the exception is a scalar, the constructor
1482 # of a no-format exception class will treat the first
1483 # parameter as a message rather than a chained exception
1485 die 'HouseholdRepairNeeded'->new($e);
1489 # if we do want to chain a string exception, we need to
1490 # wrap it first in an exception class:
1492 my $eWrapped = Exception::Lite::Any->new($e);
1493 die 'HouseholdRepairNeeded'
1494 ->new($eWrapped, "Call the repair guy");
1498 =head3 Die/Warn Handlers
1500 Die/Warn handlers provide a quick and dirty way to at Exception::Lite
1501 style stack traces to all warnings and exceptions. However,
1502 it should ONLY BE USED DURING ACTIVE DEBUGGING. They should never
1503 be used in production code. Setting these handlers
1504 can interfere with the debugging style and techiniques of other
1505 programmers and that is not nice.
1507 However, so long as you are actiely debugging, setting a die or
1508 warn handler can be quite useful, especially if a third party module
1509 is generating an exception or warning and you have no idea where it
1512 To set a die handler, you pass your desired stringify level or
1513 code reference to C<onDie>:
1515 Exception::Lite::onDie(4);
1517 This is roughly equivalent to:
1519 $SIG{__DIE__} = sub {
1520 $Exception::Lite::STRINGIFY=4;
1521 warn 'Exception::Lite::Any'->new('Unexpected death:'.$_[0])
1522 unless ($^S || Exception::Lite::isException($_[0]));
1525 To set a warning handler, you pass your desired stringify level or
1526 code reference to C<onWarn>:
1528 Exception::Lite::onWarn(4);
1530 This is roughly equivalent to:
1532 $SIG{__WARN__} = sub {
1533 $Exception::Lite::STRINGIFY=4;
1534 print STDERR 'Exception::Lite::Any'->new("Warning: $_[0]");
1537 Typically these handlers are placed at the top of a test script
1542 use Test::More tests => 25;
1544 use Exception::Lite;
1545 Exception::Lite::onDie(4);
1546 Exception::Lite::onWarn(3);
1548 ... actual testing code here ...
1552 =head1 WHY A NEW EXCEPTION CLASS
1554 Aren't there enough already? Well, no. This class differs from
1555 existing classes in several significant ways beyond "lite"-ness.
1557 =head2 Simplified integration of properties and messages
1559 C<Exception::Lite> simplifies the creation of exceptions by
1560 minimizing the amount of metadata that needs to be declared for
1561 each exception and by closely integrating exception properties
1562 and error messages. Though there are many exception modules
1563 that let you define message and properties for exceptions, in
1564 those other modules you have to manually maintain any connection
1565 between the two either in your code or in a custom subclass.
1567 In L<Exception::Class|Exception::Class>, for example, you have to
1568 do something like this:
1570 #... at the start of your code ...
1571 # notice how exception definition and message format
1572 # string constant are in two different places and need
1573 # to be manually coordinated by the programmer.
1575 use Exception::Class {
1576 'Exception::Copy::Mine' {
1577 fields => [qw(from to)];
1579 # ... lots of other exceptions here ...
1581 my $MSG_COPY='Could not copy A.txt to B.txt";
1583 ... later on when you throw the exception ...
1585 # notice the repetition in the use of exception
1586 # properties; the repetition is error prone and adds
1587 # unnecessary extra typing
1589 my $sMsg = sprintf($MSG_COPY, 'A.txt', 'B.txt');
1590 Exception::Copy::Mine->throw(error => $sMsg
1595 C<Exception::Lite> provides a succinct and easy to maintain
1596 method of declaring those same exceptions
1598 # the declaration puts the message format string and the
1599 # class declaration together for the programmer, thus
1600 # resulting in less maintenence work
1602 declareExceptionClass("Exception::Mine::Copy"
1603 , ["Could not copy %s to %s", qw(from, to) ]);
1606 .... some where else in your code ...
1609 # there is no need to explicitly call sprintf or
1610 # repetitively type variable names, nor even remember
1611 # the order of parameters in the format string or check
1612 # for undefined values. Both of these will produce
1613 # the same error message:
1614 # "Could not copy A.txt to B.txt"
1616 die "Exception::Mine:Copy"->new(from =>'A.txt', to=>'B.txt');
1617 die "Exception::Mine:Copy"->new(to =>'B.txt', from=>'A.txt');
1619 # and this will politely fill in 'undef' for the
1620 # property you leave out:
1621 # "Could not copy A.txt to <undef>"
1623 die "Exception::Mine::Copy"->new(from=>'A.txt');
1626 =head2 More intelligent stack trace
1628 The vast majority, if not all, of the exception modules on CPAN
1629 essentially reproduce Carp's presentation of the stack trace. They
1630 sometimes provide parameters to control the level of detail, but
1631 make only minimal efforts, if any, to improve on the quality of
1632 debugging information.
1634 C<Exception::Lite> improves on the traditional Perl stack trace
1635 provided by Carp in a number of ways.
1641 Error messages are shown in full and never truncated (a problem with
1646 The ability to see a list of what called what without the clutter
1647 of subroutine parameters.
1651 The ability to see the context of a line that fails rather than
1652 a pinhole snapshot of the line itself. Thus one sees
1653 "at file Foo.pm, line 13 in sub doTheFunkyFunk" rather
1654 than the contextless stack trace line displayed by nearly every,
1655 if not all Perl stacktraces, including C<Carp::croak>:
1656 "called foobar(...) at line 13 in Foo.pm".
1657 When context rather than line snapshots
1658 are provided, it is often enough simply to scan the list of what
1659 called what to see where the error occurred.
1663 Automatic filtering of stack frames that do not show the actual
1664 Flow from call to call. Perl internally creates stack frames for
1665 each eval block. Seeing these in the stack trace make it harder
1666 to scan the stack trace and see what called what.
1670 The automatic filtering can be turned off or, alternatively
1671 customized to include/exclude arbitrary stack frames.
1675 One can chain together exceptions and then print out what exception
1676 triggered what other exception. Sometimes what a low level module
1677 considers important about an exception is not what a higher level
1678 module considers important. When that happens, the programmer can
1679 create a new exception with a more relevant error message that
1680 "remembers" the exception that inspired it. If need be, one can
1681 see the entire history from origin to destination.
1685 The "traditional" stack trace smushes together all parameters into
1686 a single long line that is very hard to read. C<Exception::Lite>
1687 provides a much more readable parametr listing:
1693 They are displayed one per line so that they can be easily read
1694 and distinguished one from another
1698 The string value <i>and</i> the normal object representation is
1699 shown when an object's string conversion is overloaded. That way
1700 there can be no confusion about whether the actual object or a
1701 string was passed in as a parameter.
1705 It doesn't pretend that these are the parameters passed to the
1706 subroutine. It is impossible to recreate the actual values in
1707 the parameter list because the parameter list for any sub is
1708 just C<@_> and that can be modified when a programmer uses shift
1709 to process command line arguments. The most Perl can give (through
1710 its DB module) is the way C<@_> looked at the time the next frame
1711 in the stack was set up. Instead of positioning the parameters
1712 as if they were being passed to the subroutine, they are listed
1713 below the stacktrace line saying "thrown at in line X in
1714 subroutine Y". In reality, the "parameters" are the value of
1715 @_ passed to subroutine Y (or @ARGV if this is the entry point),
1716 or what was left of it when we got to line X.
1720 A visual hint that leading C<undef>s in C<@_> or C<@ARGV> may be
1721 the result of shifts rather than a heap of C<undef>s passed into
1722 the subroutine. This lets the programmer focus on the code, not
1723 on remembering the quirks of Perl stack tracing.
1727 =head1 CLASS REFERENCE
1729 =head2 Class factory methods
1731 =head3 C<declareExceptionClass>
1733 declareExceptionClass($sClass);
1734 declareExceptionClass($sClass, $sSuperclass);
1735 declareExceptionClass($sClass, $sSuperclass, $bCustom);
1737 declareExceptionClass($sClass, $aFormatRule);
1738 declareExceptionClass($sClass, $sSuperclass, $aFormatRule);
1739 declareExceptionClass($sClass, $sSuperclass, $aFormatRule
1742 Generates a lightweight class definition for an exception class. It
1743 returns the name of the created class, i.e. $sClass.
1749 The name of the class (package) to be created. Required.
1751 Any legal Perl package name may be used, so long as it hasn't
1752 already been used to define an exception or any other class.
1754 =item C<$sSuperclass>
1756 The name of the superclass of C<$sClass>. Optional.
1758 If missing or undefed, C<$sClass> will be be a base class
1759 whose only superclass is C<UNIVERSAL>, the root class of all Perl
1760 classes. There is no special "Exception::Base" class that all
1761 exceptions have to descend from, unless you want it that way
1762 and choose to define your set of exception classes that way.
1764 =item C<$aFormatRule>
1766 An array reference describing how to use properties to construct
1767 a message. Optional.
1769 If provided, the format rule is essential the same parameters as
1770 used by sprintf with one major exception: instead of using actual
1771 values as arguments, you use property names, like this:
1773 # insert value of 'from' property in place of first %s
1774 # insert value of 'to' property in place of first %s
1776 [ 'Cannot copy from %s to %s, 'from', 'to' ]
1778 When a format rule is provided, C<Exception::Lite> will auto-generate
1779 the message from the properties whenever the properties are set or
1780 changed. Regeneration is a lightweight process that selects property
1781 values from the hash and sends them to C<sprintf> for formatting.
1783 Later on, when you are creating exceptions, you simply pass in the
1784 property values. They can be listed in any order and extra properties
1785 that do not appear in the message string can also be provided. If
1786 for some reason the value of a property is unknown, you can assign it
1787 C<undef> and C<Exception::Lite> will politely insert a placeholder
1788 for the missing value. All of the following are valid:
1791 # These all generate "Cannot copy A.txt to B.txt"
1793 $sClass->new(from => 'A.txt', to => 'B.txt');
1794 $sClass->new(to => 'B.txt', from => 'A.txt');
1795 $sClass->new(to => 'B.txt', from => 'A.txt'
1796 , reason => 'source doesn't exist'
1799 $sClass->new(reason => 'source doesn't exist'
1801 , to => 'B.txt', from => 'A.txt'
1804 # These generate "Cannot copy A.txt to <undef>"
1806 $sClass->new(from => 'A.txt');
1807 $sClass->new(from => 'A.txt', to => 'B.txt');
1811 True if the caller intends to add custom methods and/or a custom
1812 constructor to the newly declared class. This will force the
1813 L<Excepton::Lite> to generate some extra methods and data so
1814 that the subclass can have its own private data area in the class.
1815 See L</Subclassing> for more information.
1820 =head2 Object construction methods
1824 # class configured for no generation from properties
1826 $sClass->new($sMsg);
1827 $sClass->new($sMsg,$prop1 => $val1, ....);
1829 $sClass->new($e, $sMsg);
1830 $sClass->new($e, $sMsg,$prop1 => $val1, ....);
1832 # class configured to generate messages from properties
1833 # using a per-class format string
1835 $sClass->new($prop1 => $val1, ....);
1836 $sClass->new($e, $prop1 => $val1, ....);
1839 Creates a new instance of exception class C<$sClass>. The exception
1840 may be independent or chained to the exception that triggered it.
1846 The exception that logically triggered this new exception.
1847 May be omitted or left undefined. If defined, the new exception is
1848 considered chained to C<$e>.
1852 The message text, for classes with no autogeneration from properties,
1853 that is, classes declared like
1855 declareExceptionClass($sClass);
1856 declareExceptionClass($sClass, $sSuperclass);
1858 In the constructor, C< $sClass->new($e) >>, the message defaults to
1859 the message of C<$e>. Otherwise the message is required for any
1860 class that id declared in the above two ways.
1862 =item $prop1 => $val1
1864 The first property name and its associated value. There can be
1865 as many repetitions of this as there are properties. All types
1866 of exception classes may have property lists.
1870 If you have chosen to have the message be completely independent
1873 declareExceptionClass('A');
1875 # unchained exception - print output "Hello"
1877 my $e1 = A->new("Hello", importance => 'small', risk => 'large');
1880 # chained exception - print output "Hello"
1882 my $e2 = A->new($e1,'Goodbye');
1884 $e2->getChained(); # returns $e1
1885 print $e1->getMessage(); # outputs "Goodbye"
1886 print $e1; # outputs "Goodbye"
1887 print $e2->getChained()->getMessage(); # outputs "Hello"
1890 If you have chosen to have the message autogenerated from properties
1891 your call to C<new> will look like this:
1893 $sFormat ='the importance is %s, but the risk is %s';
1894 declareExceptionClass('B', [ $sFormat, qw(importance risk)]);
1897 # unchained exception
1899 my $e1 = B->new(importance=>'small', risk=>'large');
1901 $e1->getChained(); # returns undef
1902 print "$e1\n"; # outputs "The importance is small, but the
1907 $e2 = B->new($e1, importance=>'yink', risk=>'hooboy');
1908 $e2->getChained(); # returns $e1
1909 "$e2" # evaluates to "The importance is yink, but
1910 # the risk is hooboy"
1911 $e2->getMessage() # same as "$e2"
1912 $e2->getChained()->getMessage(); # same as "$e1"
1916 =head2 Object methods
1918 =head3 C<getMessage>
1922 Returns the messsage, i.e. the value displayed when this exception
1923 is treated as a string. This is the value without line numbers
1924 stack trace or other information. It includes only the format
1925 string with the property values inserted.
1927 =head3 C<getProperty>
1929 $e->getProperty($sName);
1931 Returns the property value for the C<$sName> property.
1933 =head3 C<isProperty>
1935 $e->isProperty($sName)
1937 Returns true if the exception has the C<$sName> property, even if
1938 the value is undefined. (checks existance, not definition).
1944 Returns the process id of the process where the exception was
1947 =head3 C<getPackage>
1951 Returns the package contining the entry point of the process, i.e.
1952 the package identified at the top of the stack.
1957 Returns the thread where the exception was thrown.
1961 =head3 C<getStackTrace>
1963 $e->getStackTrace();
1965 Returns the stack trace from the point where the exception was
1966 thrown (frame 0) to the entry point (frame -1). The stack trace
1967 is structured as an array of arrays (AoA) where each member array
1968 represents a single lightweight frame with four data per frame:
1971 [1] the line number within the file
1972 [2] the subroutine where the exception was called. File and
1973 line number will be within this subroutine.
1974 [3] a comma delimited string containing string representations
1975 of the values that were stored in @_ at the time the
1976 exception was thrown. If shift was used to process the
1977 incoming subroutine arguments, @_ will usually contain
1978 several leading undefs.
1980 For more information about each component of a stack frame, please
1981 see the documentation below for the following methods:
1983 * C<getFile> - explains what to expect in [0] of stack frame
1985 * C<getLine> - explains what to expect in [1] of stack frame
1987 * C<getSubroutine> - explains what to expect in [2] of stack frame
1989 * C<getArgs> - explains what to expect in [3] of stack frame
1991 The frame closest to the thrown exception is numbered 0. In fact
1992 frame 0, stores information about the actual point where the exception
1996 =head3 C<getFrameCount>
1998 $e->getFrameCount();
2000 Returns the number of frames in the stack trace.
2004 $e->getFile(0); # gets frame where exception was thrown
2005 $e->getFile(-1); # gets entry point frame
2007 $e->getFile(); # short hand for $e->getFile(0)
2010 Without an argument, this method returns the name of the file where
2011 the exception was thrown. With an argument it returns the name of
2012 the file in the C<$i>th frame of the stack trace.
2014 Negative values of C<$i> will be counted from the entry point with
2015 C<-1> representing the entry point frame, C<-2> representing the
2016 first call made within the script and so on.
2020 $e->getLine(0); # gets frame where exception was thrown
2021 $e->getLine(-1); # gets entry point frame
2023 $e->getLine(); # short hand for $e->getLine(0)
2026 Without an argument, this method returns the line number where the
2027 exception was thrown. With an argument it returns the line number
2028 in the C<$i>th frame of the stack trace.
2030 Negative values of C<$i> will be counted from the entry point with
2031 C<-1> representing the entry point frame, C<-2> representing the
2032 first call made within the script and so on.
2034 =head3 C<getSubroutine>
2036 $e->getSubroutine(0); # gets frame where exception was thrown
2037 $e->getSubroutine(-1); # gets entry point frame
2039 $e->getSubroutine(); # short hand for $e->getSubroutine(0)
2040 $e->getSubroutine($i);
2042 Without an argument, this method returns the name of the subroutine
2043 where this exception was created via C<new(...)>. With an argument
2044 it returns the value of the subroutine (or package entry point) in
2045 the C<$i>th frame of the stack trace.
2047 Negative values of C<$i> will be counted from the entry point with
2048 C<-1> representing the entry point frame, C<-2> representing the
2049 first call made within the script and so on.
2051 Note: This is not the same value as returned by C<caller($i)>. C<caller> returns the name of the subroutine that was being called
2052 at the time of death rather than the containing subroutine.
2054 The subroutine name in array element [2] includes the package name
2055 so it will be 'MyPackage::Utils::doit' and not just 'doit'. In the
2056 entry point frame there is, of course, no containing subroutine so
2057 the value in this string is instead the package name embedded in
2058 the string "<package: packageName>".
2063 $e->getArgs(0); # gets frame where exception was thrown
2064 $e->getArgs(-1); # gets entry point frame
2066 $e->getArgs(); # short hand for $e->getArgs(0)
2069 Without an argument, this method returns the value of C<@_> (or
2070 C<@ARGV> for an entry point frame) at the time the exception was
2071 thrown. With an argument it returns the name of
2072 the file in the C<$i>th frame of the stack trace.
2074 Negative values of C<$i> will be counted from the entry point with
2075 C<-1> representing the entry point frame, C<-2> representing the
2076 first call made within the script and so on.
2078 @_, is the best approximation Perl provides for the arguments
2079 used to call the subroutine. At the start of the subroutine it does
2080 in fact reflect the parameters passed in, but frequently programmers
2081 will process this array with the C<shift> operator which will set
2082 leading arguments to C<undef>. The debugger does not cache the
2083 oiginal value of @_, so all you can get from its stack trace is the
2084 value at the time the exception was thrown, not the value when the
2085 subroutine was entered.
2087 =head3 C<getPropagation>
2089 $e->getPropagation();
2091 Returns an array reference with one element for each time this
2092 exception was caught and rethrown using either Perl's own rethrow
2093 syntax C<$@=$e; die;> or this packages: C<< die->rethrow() >>.
2095 Each element of the array contains a file and line number where
2096 the exception was rethrown:
2098 [0] file where exception was caught and rethrown
2099 [1] line number where the exception was caught and rethrown
2101 Note: do not confuse the stack trace with propagation. The stack
2102 trace is the sequence of calls that were made I<before> the
2103 exception was thrown. The propagation file and line numbers
2104 refer to where the exception was caught in an exception handling
2105 block I<after> the exception was thrown.
2107 Generally, bad data is the reason behind an exception. To see
2108 where the bad data came from, it is generally more useful to
2109 look at the stack and see what data was passed down to the point
2110 where the exception was generated than it is to look at where
2111 the exception was caught after the fact.
2113 =head3 C<getChained>
2115 my $eChained = $e->getChained();
2117 Returns the chained exception, or undef if the exception is not
2118 chained. Chained exceptions are created by inserting the triggering
2119 exception as the first parameter to C<new(...)>.
2121 # class level format
2122 MyException1->new(reason=>'blahblahblah'); #unchained
2123 MyException1->new($e, reason=>'blahblahblah'); #chained
2126 MyException1->new('blahblahblah'); #unchained
2127 MyException1->new($e, reason=>'blahblahblah'); #chained
2130 The chained exception can be a reference to any sort of data. It
2131 does not need to belong to the same class as the new exception,
2132 nor does it even have to belong to a class generated by
2133 C<Exception::Lite>. Its only restriction is that it may not be
2134 a scalar(string, number, ec). To see if an exception
2135 may be chained you can call C<Exception::Lite::isChainable()>:
2137 if (Exception::Lite::isChainable($e)) {
2138 die MyException1->new($e, reason=>'blahblahblah');
2141 # another alternative for string exceptions
2142 my $eWrapper=MyWrapperForStringExceptions->new($e);
2143 die MyException1->new($eWrapper, reason=>'blahblahblah');
2145 # another alternative for string exceptions
2146 die MyException1->new($eWrapper, reason=>"blahblahblah: $e");
2153 $e->rethrow($prop => $newValue); # format rule
2155 $e->rethrow($newMsg, $p1 => $newValue); # no format rule
2156 $e->rethrow(undef, $pl => $newValue); # no format rule
2157 $e->rethrow($sNewMsg); # no format rule
2160 Propagates the exception using the method (C<PROPAGATE>) as would
2161 be called were one to use Perl's native 'rethrow' syntax,
2164 The first form with no arguments simply rethrows the exception.
2165 The remain formats let one override property values and/or update
2166 the message. The argument list is the same as for C<new> except
2167 that exceptions with no or object level format strings may have
2168 an undefined message.
2170 For class format exceptions, the message will automatically be
2171 updated if any of the properties used to construct it have changed.
2173 For exception classes with no formatting, property and message
2174 changes are independent of each other. If C<$sMsg> is set to C<undef>
2175 the properties will be changed and the message will be left alone.
2176 If C<$sMsg> is provided, but no override properties are provided,
2177 the message will change but the properties will be left untouched.
2179 =head3 C<_p_getSubclassData>
2181 Method for internal use by custom subclasses. This method retrieves
2182 the data hash reserved for use by custom methods.
2187 =head2 Canned test modules
2189 Test modules for making sure your code generates the right
2190 exceptions. They work with any OOP solution, even C<Exception::Lite>
2192 * L<Test::Exception|Test::Exception> - works with any OOP solution
2194 * L<Test::Exception::LessClever|Test::Exception::LessClever> - works
2195 with any OOP solution
2197 =head2 Alternate OOP solutions
2199 =head3 L<Exception::Class|Exception::Class>
2201 This module has a fair number of non-core modules. There are several
2202 extension modules. Most are adapter classes that convert exceptions
2203 produced by popular CPAN modules into Exception::Class modules:
2205 * L<Exception::Class::Nested|Exception::Class::Nested> - changes
2206 the syntax for declaring exceptions.
2208 * L<MooseX::Error::Exception::Class|MooseX::Error::Exception::Class>
2209 - converts Moose exceptions to
2210 C<Exception::Class> instances.
2212 * L<HTTP::Exception|HTTP::Exception> - wrapper around HTTP exceptions
2214 * L<Mail::Log::Exceptions|Mail::Log::Exceptions> - wrapper around
2215 Mail::Log exceptions
2217 * L<Exception::Class::DBI|Exception::Class::DBI> - wrapper around
2220 * L<Error::Exception|Error::Exception> - prints out exception
2221 properties as part of exception stringification.
2223 It takes a heavy approach to OOP, requiring all properties to be
2224 predeclared. It also stores a lot of information about an exception,
2225 not all of which is likely to be important to the average user, e.g.
2226 pid, uid, guid and even the entire stack trace.
2228 There is no support for auto-generating messages based on
2231 For an extended discussion of C<Exception::Class>, see
2232 L<http://www.drdobbs.com/web-development/184416129>.
2234 =head3 L<Exception::Base|Exception::Base>
2236 A light weight version of L<Exception::Class|Exception::Class>.
2237 Uses only core modules but is fairly new and has no significant
2238 eco-system of extensions (yet).
2239 Like C<Exception::Class> properties must be explicitly declared and
2240 there is no support for autogenerating messages based on properties.
2243 =head3 L<Class::Throwable|Class::Throwable>
2245 Another light weight version of L<Exception::Class|Exception::Class>.
2246 Unlike C<Exception::Class> you can control the amount of system
2247 state and stack trace information stored at the time an exception
2250 =head2 Syntactic sugar solutions
2252 Syntactical sugar solutions allow java like try/catch blocks to
2253 replace the more awkward C<die>, C<eval/do>, and C<$@=$e; die>
2254 pattern. Take care in chosing these methods as they sometimes
2255 use coding strategies known to cause problems:
2261 overriding signal handlers - possible interference with your own
2262 code or third party module use of those handlers.
2266 source code filtering - can shift line numbers so that the reported
2267 line number and the actual line number may not be the same.
2271 closures - there is a apparently a problem with nested closures
2272 causing memory leaks in some versions of Perl (pre 5.8.4). This
2273 has been since fixed since 5.8.4.
2277 Modules providing syntactic sugar include:
2279 * L<Try::Catch|Try::Catch>
2281 * L<Try::Tiny|Try::Tiny>
2285 * L<Exception::Caught|Exception::Caught>
2287 * L<Exception::SEH|Exception::SEH>
2289 * C<Exception|Exception>
2291 * L<Exception::Class::TryCatch|Exception::Class::TryCatch> - extension of L<Exception::Class|Exception::Class>
2293 * L<Exception::Class::TCF|Exception::Class::TCF> - extension of L<Exception::Class|Exception::Class>
2298 No subroutines are exported by default. See the start of the synopsis
2299 for optional exports.
2304 Elizabeth Grace Frank-Backman
2308 Copyright (c) 2011 Elizabeth Grace Frank-Backman.
2309 All rights reserved.
2313 This program is free software; you can redistribute it and/or
2314 modify it under the same terms as Perl itself.