1Exception::Class(3) User Contributed Perl Documentation Exception::Class(3)
2
3
4
6 Exception::Class - A module that allows you to declare real exception
7 classes in Perl
8
10 use Exception::Class
11 ( 'MyException',
12
13 'AnotherException' =>
14 { isa => 'MyException' },
15
16 'YetAnotherException' =>
17 { isa => 'AnotherException',
18 description => 'These exceptions are related to IPC' },
19
20 'ExceptionWithFields' =>
21 { isa => 'YetAnotherException',
22 fields => [ 'grandiosity', 'quixotic' ],
23 alias => 'throw_fields',
24 },
25 );
26
27 # try
28 eval { MyException->throw( error => 'I feel funny.' ) };
29
30 my $e;
31 # catch
32 if ( $e = Exception::Class->caught('MyException') )
33 {
34 warn $e->error, "\n", $e->trace->as_string, "\n";
35 warn join ' ', $e->euid, $e->egid, $e->uid, $e->gid, $e->pid, $e->time;
36
37 exit;
38 }
39 elsif ( $e = Exception::Class->caught('ExceptionWithFields') )
40 {
41 $e->quixotic ? do_something_wacky() : do_something_sane();
42 }
43 else
44 {
45 $e = Exception::Class->caught();
46 ref $e ? $e->rethrow : die $e;
47 }
48
49 # use an alias - without parens subroutine name is checked at
50 # compile time
51 throw_fields error => "No strawberry", grandiosity => "quite a bit";
52
54 Exception::Class allows you to declare exception hierarchies in your
55 modules in a "Java-esque" manner.
56
57 It features a simple interface allowing programmers to 'declare' excep‐
58 tion classes at compile time. It also has a base exception class,
59 Exception::Class::Base, that can be easily extended.
60
61 It is designed to make structured exception handling simpler and better
62 by encouraging people to use hierarchies of exceptions in their appli‐
63 cations, as opposed to a single catch-all exception class.
64
65 This module does not implement any try/catch syntax. Please see the
66 "OTHER EXCEPTION MODULES (try/catch syntax)" section for more informa‐
67 tion on how to get this syntax.
68
70 Importing "Exception::Class" allows you to automagically create "Excep‐
71 tion::Class::Base" subclasses. You can also create subclasses via the
72 traditional means of defining your own subclass with @ISA. These two
73 methods may be easily combined, so that you could subclass an exception
74 class defined via the automagic import, if you desired this.
75
76 The syntax for the magic declarations is as follows:
77
78 'MANDATORY CLASS NAME' => \%optional_hashref
79
80 The hashref may contain the following options:
81
82 * isa
83 This is the class's parent class. If this isn't provided then the
84 class name in $Exception::Class::BASE_EXC_CLASS is assumed to be
85 the parent (see below).
86
87 This parameter lets you create arbitrarily deep class hierarchies.
88 This can be any other "Exception::Class::Base" subclass in your
89 declaration or a subclass loaded from a module.
90
91 To change the default exception class you will need to change the
92 value of $Exception::Class::BASE_EXC_CLASS before calling
93 "import()". To do this simply do something like this:
94
95 BEGIN { $Exception::Class::BASE_EXC_CLASS = 'SomeExceptionClass'; }
96
97 If anyone can come up with a more elegant way to do this please let
98 me know.
99
100 CAVEAT: If you want to automagically subclass an "Excep‐
101 tion::Class::Base" subclass loaded from a file, then you must com‐
102 pile the class (via use or require or some other magic) before you
103 import "Exception::Class" or you'll get a compile time error.
104
105 * fields
106 This allows you to define additional attributes for your exception
107 class. Any field you define can be passed to the "throw()" or
108 "new()" methods as additional parameters for the constructor. In
109 addition, your exception object will have an accessor method for
110 the fields you define.
111
112 This parameter can be either a scalar (for a single field) or an
113 array reference if you need to define multiple fields.
114
115 Fields will be inherited by subclasses.
116
117 * alias
118 Specifying an alias causes this class to create a subroutine of the
119 specified name in the caller's namespace. Calling this subroutine
120 is equivalent to calling "<class>->throw(@_)" for the given excep‐
121 tion class.
122
123 Besides convenience, using aliases also allows for additional com‐
124 pile time checking. If the alias is called without parentheses, as
125 in "throw_fields "an error occurred"", then Perl checks for the
126 existence of the "throw_fields()" subroutine at compile time. If
127 instead you do "ExceptionWithFields->throw(...)", then Perl checks
128 the class name at runtime, meaning that typos may sneak through.
129
130 * description
131 Each exception class has a description method that returns a fixed
132 string. This should describe the exception class (as opposed to
133 any particular exception object). This may be useful for debugging
134 if you start catching exceptions you weren't expecting (particu‐
135 larly if someone forgot to document them) and you don't understand
136 the error messages.
137
138 The "Exception::Class" magic attempts to detect circular class hierar‐
139 chies and will die if it finds one. It also detects missing links in a
140 chain, for example if you declare Bar to be a subclass of Foo and never
141 declare Foo.
142
144 "Exception::Class" provides some syntactic sugar for catching excep‐
145 tions in a safe manner:
146
147 eval { ... }
148
149 if ( my $e = Exception::Class->caught('My::Error') )
150 {
151 cleanup();
152 do_something_with_exception($e);
153 }
154
155 The "caught()" method takes a class name and returns an exception
156 object if the last thrown exception is of the given class, or a sub‐
157 class of that class. If it is not given any arguments, it simply
158 returns $@.
159
160 You should always make a copy of the exception object, rather than
161 using $@ directly. This is necessary because if your "cleanup()" func‐
162 tion uses "eval", or calls something which uses it, then $@ is over‐
163 written. Copying the exception preserves it for the call to "do_some‐
164 thing_with_exception()".
165
166 Exception objects also provide a caught method so you can write:
167
168 if ( my $e = My::Error->caught() )
169 {
170 cleanup();
171 do_something_with_exception($e);
172 }
173
174 Uncatchable Exceptions
175
176 Internally, the "caught()" method will call "isa()" on the exception
177 object. You could make an exception "uncatchable" by overriding
178 "isa()" in that class like this:
179
180 package Exception::Uncatchable;
181
182 sub isa { shift->rethrow }
183
184 Of course, this only works if you always call "Excep‐
185 tion::Class->caught()" after an "eval".
186
188 * Trace($boolean)
189 Each "Exception::Class::Base" subclass can be set individually to
190 include a a stracktrace when the "as_string" method is called. The
191 default is to not include a stacktrace. Calling this method with a
192 value changes this behavior. It always returns the current value
193 (after any change is applied).
194
195 This value is inherited by any subclasses. However, if this value
196 is set for a subclass, it will thereafter be independent of the
197 value in "Exception::Class::Base".
198
199 This is a class method, not an object method.
200
201 * NoRefs($boolean)
202 When a "Devel::StackTrace" object is created, it walks through the
203 stack and stores the arguments which were passed to each subroutine
204 on the stack. If any of these arguments are references, then that
205 means that the "Devel::StackTrace" ends up increasing the refcount
206 of these references, delaying their destruction.
207
208 Since "Exception::Class::Base" uses "Devel::StackTrace" internally,
209 this method provides a way to tell "Devel::StackTrace" not to store
210 these references. Instead, "Devel::StackTrace" replaces references
211 with their stringified representation.
212
213 This method defaults to true. As with "Trace()", it is inherited
214 by subclasses but setting it in a subclass makes it independent
215 thereafter.
216
217 * RespectOverload($boolean)
218 When a "Devel::StackTrace" object stringifies, by default it
219 ignores stringification overloading on any objects being dealt
220 with.
221
222 Since "Exception::Class::Base" uses "Devel::StackTrace" internally,
223 this method provides a way to tell "Devel::StackTrace" to respect
224 overloading.
225
226 This method defaults to false. As with "Trace()", it is inherited
227 by subclasses but setting it in a subclass makes it independent
228 thereafter.
229
230 * Fields
231 This method returns the extra fields defined for the given class,
232 as an array.
233
234 * throw( $message )
235 * throw( message => $message )
236 * throw( error => $error )
237 This method creates a new object with the given error message. If
238 no error message is given, $! is used. It then die's with this
239 object as its argument.
240
241 This method also takes a "show_trace" parameter which indicates
242 whether or not the particular exception object being created should
243 show a stacktrace when its "as_string()" method is called. This
244 overrides the value of "Trace()" for this class if it is given.
245
246 The frames included in the trace can be controlled by the
247 "ignore_class" and "ignore_package" parameters. These are passed
248 directly to Devel::Stacktrace's constructor. See "Devel::Stack‐
249 trace" for more details.
250
251 If only a single value is given to the constructor it is assumed to
252 be the message parameter.
253
254 Additional keys corresponding to the fields defined for the partic‐
255 ular exception subclass will also be accepted.
256
257 * new
258 This method takes the same parameters as "throw()", but instead of
259 dying simply returns a new exception object.
260
261 This method is always called when constructing a new exception
262 object via the "throw()" method.
263
264 * description
265 Returns the description for the given "Exception::Class::Base" sub‐
266 class. The "Exception::Class::Base" class's description is
267 "Generic exception" (this may change in the future). This is also
268 an object method.
269
271 * rethrow
272 Simply dies with the object as its sole argument. It's just syn‐
273 tactic sugar. This does not change any of the object's attribute
274 values. However, it will cause "caller()" to report the die as
275 coming from within the "Exception::Class::Base" class rather than
276 where rethrow was called.
277
278 Of course, you always have access to the original stacktrace for
279 the exception object.
280
281 * message
282 * error
283 Returns the error/message associated with the exception.
284
285 * pid
286 Returns the pid at the time the exception was thrown.
287
288 * uid
289 Returns the real user id at the time the exception was thrown.
290
291 * gid
292 Returns the real group id at the time the exception was thrown.
293
294 * euid
295 Returns the effective user id at the time the exception was thrown.
296
297 * egid
298 Returns the effective group id at the time the exception was
299 thrown.
300
301 * time
302 Returns the time in seconds since the epoch at the time the excep‐
303 tion was thrown.
304
305 * package
306 Returns the package from which the exception was thrown.
307
308 * file
309 Returns the file within which the exception was thrown.
310
311 * line
312 Returns the line where the exception was thrown.
313
314 * trace
315 Returns the trace object associated with the object.
316
317 * show_trace($boolean)
318 This method can be used to set whether or not a strack trace is
319 included when the as_string method is called or the object is
320 stringified.
321
322 * as_string
323 Returns a string form of the error message (something like what
324 you'd expect from die). If the class or object is set to show
325 traces then then the full trace is also included. The result looks
326 like "Carp::confess()".
327
328 * full_message
329 Called by the "as_string()" method to get the message. By default,
330 this is the same as calling the "message()" method, but may be
331 overridden by a subclass. See below for details.
332
334 The "Exception::Class::Base" object is overloaded so that stringifica‐
335 tion produces a normal error message. It just calls the as_string
336 method described above. This means that you can just "print $@" after
337 an "eval" and not worry about whether or not its an actual object. It
338 also means an application or module could do this:
339
340 $SIG{__DIE__} = sub { Exception::Class::Base->throw( error => join '', @_ ); };
341
342 and this would probably not break anything (unless someone was expect‐
343 ing a different type of exception object from "die()").
344
346 By default, the "as_string()" method simply returns the value "message"
347 or "error" param plus a stack trace, if the class's "Trace()" method
348 returns a true value or "show_trace" was set when creating the excep‐
349 tion.
350
351 However, once you add new fields to a subclass, you may want to include
352 those fields in the stringified error.
353
354 Inside the "as_string()" method, the message (non-stack trace) portion
355 of the error is generated by calling the "full_message()" method. This
356 can be easily overridden. For example:
357
358 sub full_message
359 {
360 my $self = shift;
361
362 my $msg = $self->message;
363
364 $msg .= " and foo was " . $self->foo;
365
366 return $msg;
367 }
368
370 If you're creating a complex system that throws lots of different types
371 of exceptions, consider putting all the exception declarations in one
372 place. For an app called Foo you might make a "Foo::Exceptions" module
373 and use that in all your code. This module could just contain the code
374 to make "Exception::Class" do its automagic class creation. Doing this
375 allows you to more easily see what exceptions you have, and makes it
376 easier to keep track of them.
377
378 This might look something like this:
379
380 package Foo::Bar::Exceptions;
381
382 use Exception::Class ( Foo::Bar::Exception::Senses =>
383 { description => 'sense-related exception' },
384
385 Foo::Bar::Exception::Smell =>
386 { isa => 'Foo::Bar::Exception::Senses',
387 fields => 'odor',
388 description => 'stinky!' },
389
390 Foo::Bar::Exception::Taste =>
391 { isa => 'Foo::Bar::Exception::Senses',
392 fields => [ 'taste', 'bitterness' ],
393 description => 'like, gag me with a spoon!' },
394
395 ... );
396
397 You may want to create a real module to subclass "Excep‐
398 tion::Class::Base" as well, particularly if you want your exceptions to
399 have more methods.
400
401 Subclassing Exception::Class::Base
402
403 As part of your usage of "Exception::Class", you may want to create
404 your own base exception class which subclasses "Excep‐
405 tion::Class::Base". You should feel free to subclass any of the meth‐
406 ods documented above. For example, you may want to subclass "new()" to
407 add additional information to your exception objects.
408
410 The "Exception::Class" method offers one function, "Classes()", which
411 is not exported. This method returns a list of the classes that have
412 been created by calling the "Exception::Class" import() method. Note
413 that this is all the subclasses that have been created, so it may
414 include subclasses created by things like CPAN modules, etc. Also note
415 that if you simply define a subclass via the normal Perl method of set‐
416 ting @ISA or "use base", then your subclass will not be included.
417
419 If you are interested in adding try/catch/finally syntactic sugar to
420 your code then I recommend you check out U. Arun Kumar's "Error.pm"
421 module, which implements this syntax. It also includes its own base
422 exception class, "Error::Simple".
423
424 If you would prefer to use the "Exception::Class::Base" class included
425 with this module, you'll have to add this to your code somewhere:
426
427 push @Exception::Class::Base::ISA, 'Error'
428 unless Exception::Class::Base->isa('Error');
429
430 It's a hack but apparently it works.
431
433 Dave Rolsky, <autarch@urth.org>
434
436 Devel::StackTrace - used by this module to create stack traces
437
438 Error.pm - implements try/catch in Perl. Also provides an exception
439 base class.
440
441 Test::Exception - a module that helps you test exception based code.
442
443 Numerous other modules/frameworks seem to have their own exception
444 classes (SPOPS and Template Toolkit, to name two) but none of these
445 seem to be designed for use outside of these packages.
446
447
448
449perl v5.8.8 2006-01-14 Exception::Class(3)