Monday, 29 December 2008

Seaside 2.9: Exception Handling

Ok, I promised well over a month ago to start documenting some of the new bells and whistles in the Seaside 2.9 Alpha series. I thought I'd start things off with a discussion of the new exception handling mechanism.

Have you ever wanted to customize the look of Seaside's error pages? Want to send yourself an email whenever an exception is raised? Maybe save a copy of the image on errors so you can look at the stack later? It has been possible for ages to implement a custom error handling class for your Seaside application but the process was not necessarily obvious and you were limited to catching subclasses of Warning and Error. In the upcoming Seaside release, we have cleaned up the exception handling code to really simplify the error handlers that come with Seaside and to make your custom handlers simpler and more flexible.

Basic Usage

To create your own exception handler, the first question is what class to use as your superclass. If you are just interested in customizing the appearance of error pages or performing some additional action when an error occurs, you probably want to subclass WAErrorHandler. If your requirements are more complex, you may want to subclass WAExceptionHandler directly (see Advanced Usage below).

Subclassing WAErrorHandler

WAErrorHandler is already configured to handle Error and Warning and is a good starting point if you don't need to drastically change the error handling behaviour. In your custom subclass, you can implement #handleError: and #handleWarning: to define the behaviour you want in each case. The methods take the exception (either an Error or Warning respectively) as a parameter and should ultimately either resume the exception or return an instance of WAResponse. By default, both methods call #handleDefault: so you can provide common implementation there.

For example, assuming you had defined a routine to notify yourself of errors by email, you could provide an implementation like this:

handleError: anError
self notifyMeOfError: anError.
^ WAResponse new
internalError;
contentType: WAMimeType textPlain;
nextPutAll: 'Eek! An error occurred but I have been notified.';
yourself

Returning an HTML Response

You could of course provide an HTML response but you would want to make sure your HTML is valid (and that means a head, a title, a body, etc.):


handleError: anError
^ WAResponse new
internalError;
nextPutAll: '<html>
<head><title>Error!</title></head>
<body><p>An error occurred</p></body>
</html>';
yourself

If you want to use the Canvas API, you can subclass WAHtmlErrorHandler instead. Just implement #titleForException: and #contentForException:on: (it gets passed the exception and a canvas) and you're done.

Using Your Exception Handler

Once you have written your exception handler, you need to configure your application to use it. Open your web browser and navigate to the Seaside configuration page for your application. There you will find a preference called 'Exception Handler' and you should be able to choose your new class from the list.

Alternatively, from a workspace, execute something like:

(WAAdmin defaultDispatcher entryPointAt: 'myapp')
preferenceAt: #exceptionHandler put: MyHandlerClass

Advanced Usage

If your needs are more complex than the above, you may want to subclass WAExceptionHandler directly. An exception handler needs to do two things:

  1. choose which exceptions to handle
  2. define how to handle them

Selecting Exceptions

The easiest way to select which exceptions to handle is to implement #exceptionSelector on the class-side of your new handler (note: in Seaside 2.9a1 this method is named #exceptionsToCatch). Your #exceptionSelector method should return either an ExceptionSet or a subclass of Exception. You probably want to continue handling the exceptions handled by your superclass so your implementation might look like:

exceptionSelector
^ super exceptionSelector, MyCustomError

If your needs are somehow more complex, look at implementing #handles: and #, yourself on either the class- or instance-side, as appropriate (note: these two methods do not exist in Seaside 2.9a1).

Handling Exceptions

When an exception is signaled and your handler indicates (via #handles:) that it wishes to handle the exception, #handleException: is called and passed the signaled exception. To define your exception handling behaviour, simply implement #handleException: on the instance-side of your handler. Note that the same handler instance is used throughout a single HTTP request even if multiple exceptions are signaled.

The #handleException: method is expected to return a WAResponse object. It may also choose to resume the exception, cause the Request Context stored in its requestContext instance variable to return a response (by using #redirectTo: for example), or otherwise avoid returning at all; but if it returns, it should return a response.

Internal Errors

WAExceptionHandler also provides a class-side method called #internalError:context:. This method creates a new instance of the handler and calls #internalError:, which should generate a very simple error message. This method is used whenever the exception handling mechanism itself signals an error as well as any other place in the system where we cannot be certain that a more complex error handler will succeed. This method should not do anything that has potential to raise further errors.

Setting Up an Exception Handler

Exception handling for Seaside applications is set up by WAExceptionFilter (more information on filters in a later post) and you do not need to do anything else if you are using WAApplication and WASession. If you are implementing your own request handler, however, and want to use the exception handling mechanism, you will need to set up an exception handler yourself.

Although you could do everything yourself, the easiest thing is to call #handleExceptionsDuring:context: on your handler class, passing it the block you want wrapped in the exception handler and the current WARequestContext object. You can look at RRRssHandler for an example.

Examples

The Seaside distribution includes a few exception handlers that you can look at for examples of usage. Beware of WADebugErrorHandler and WAWalkbackErrorHandler, though, as they do crazy things to get debugging to work the way we want in Squeak; although they are well commented and may be interesting to look at, they are probably not good examples of general usage. The Seaside-Squeak-Email package includes WAEmailErrorHandler, an abstract class that can be subclassed and used to send an email whenever an error occurs.

Monday, 15 December 2008

Christmas giving

I just stumbled across this site: http://www.nochristmasgiftsthisyear.com/

As it happens, I've been reducing my Christmas gift giving over the past few years anyway, agreeing with more and more people just to forgo the exercise. I love giving gifts (really) but have been finding searching them out, selecting them, and buying them increasingly stressful. At the same time, when people ask me what I want or need, I have a hard time coming up with anything much and the same seems to hold true for everyone else. In order to perpetuate mass consumerism, this situation seems to have brought about the proliferation of gift cards. I don't have a problem with gift cards per se (they've been around in the form of gift certificates for ever), but the fact that I can now buy gift cards for a hundred different stores at the Safeway checkout counter makes me feel like things have gone too far.

Sure, I remember many childhood years, waking up with eager anticipation of gifts to come–at least one of them usually big and/or expensive. There were even a couple of years there, not too long ago, when Christmas seemed to have lost its luster and I just couldn't eke much enjoyment out of it.

But things have mellowed again and Christmas has been reborn. Now it's about cooking "Christmas" dinner (weeks in advance to fit everyone's schedule) with friends. It's about brisk walks down brightly-decorated streets and the smell of a wood fire (where still permitted by law). It's about spending time with family. And sure, sometimes it's still about giving gifts but the joy is back (on both sides) because it's now about an occasional gift that you didn't even expect. One of the most meaningful gifts I received was an album of family recipes and baby photos. In fact, I think that's when I realized that my perception of Christmas had changed.

I don't know if it's just the result of aging or if society is actually start to push back against consumerism-for-its-own-sake but it feels good. And if you still feel you need to get me a gift, try something consumable: wine, herbs, spices, oils. It's so nice to get a bottle of wine I've never tried and would never have bought. And if I don't like it, at least it's gone instead of staring at me for the rest of time from a dusty shelf or the back of a closet.

Thursday, 11 December 2008

The will of the people

Steven had a post about the recent Canadian political events wherein he concludes:
So best I can tell, when the Governor General does allow the opposition to take power without an election there is noise, controversy and eventually change so it cannot happen again. And when the Governor General does not give power to the opposition then history seems to just continue along. I guess I must have missed McArthur's convention.
Perhaps this is nitpicking, but we're not talking about the Governor General giving power to the opposition; we're talking about the Governor General giving power to a new coalition, one with the support of the majority of parliament.

Now I agree that the Governor General has this option but certainly no obligation to choose it. On the other hand, I still can't fathom why we would want another election right now: Canadians elected 308 MPs to represent them and if the majority of them want a change in parliament then that is the will of the people, particularly this soon after an election. The incessant cries of Canadians who seem to think they live in an the US and therefore elected the Prime Minister are driving me nuts.

I also disagree that the Governor General has lost her authority to act against the will of the Prime Minister. By convention, she normally follows the advice of the Prime Minister, but, at least as far as I'm concerned, this is only in his role as the head of parliament. The Prime Minister in Canada is not a political office; he does not have any special privileges and should not; the Governor General is bowing to the will of the people (as represented by their elected MPs in parliament), not to the Prime Minister.

The Governor General has a tenuous position in that being seen to oppose the will of the people would likely result in a swift call to remove what has become a largely ceremonial position. However, I also think we have a history of intelligent, reasonable, and competent Governor Generals and I'm glad the position is still not technically powerless. In this case, I think calling a timeout is a reasonable decision, allowing both sides a chance to back down. If the non-confidence vote goes ahead in the new year, though, I'd hope she won't waste our time and money with another election.

Tuesday, 28 October 2008

One, Two, cha-cha-cha

We just got back from our first dance class: Cha-Cha and Waltz. It was lots of fun, ours shoes don't look too stepped on, and we definitely weren't the worst couple in the class. What more could you ask for?

I've been wanting to take ballroom lessons for years (at least since my first friend got married). We just need to practice enough to let muscle memory kick in; I think there's some worry from my better half that I'll be scheduling nightly drills so I'll have to control myself.

Sunday, 26 October 2008

Notebook Shopping

So I'm in the market for a new laptop. This kind of annoys me because I don't actually want a laptop. Expensive, barely upgradeable, tiny keyboards, and (worst of the all) the temptation to sit awkwardly in front of the television with the thing precariously balanced on your knee, cooking and radiating your organs and destroying your body through poor ergonomics. But I'm traveling a fair bit, doing consulting, and there are occasions where a laptop is, if not essential, at least very very useful.

So here I am looking around at the options and, while I've been telling friends and colleagues for years to buy Mac laptops if they can afford them, I now find myself unsure. I was intending to get a MacBook Pro in September in order to get the free iPod Touch but decided to wait for the new Macs to be announced. I was underwhelmed: there's really not much new there despite the heavy sales pitch and I don't like the new look. Even with the education discount, the cheapest MacBook Pro would cost me over $2400 after tax.

The problem is that I really like Mac OS X and I really like that the freeware people write for it actually looks good (unlike for Linux or Windows, at least in general). I discovered over the last 9 months that, for the things I do, I can manage fine with Windows. And as a major plus, I don't spend hours endlessly "tweaking" my system like I do with Linux. Sure, every time Apple releases a software update, Mac owners everywhere cower in fear wondering what will be broken, but I'm still happier in OS X than in any other operating system.

I'm looking around at Dells and Compaqs and I can get a laptop that would probably serve my needs just fine for $700 or so plus tax. That makes the MacBook Pro something like three times as expensive! If Apple would sell me a copy of OS X to run on a PC, I would buy it in a flash but $1500 is a hefty tax to pay for it. Even refurbished old-model MacBook Pros are selling for $1449 plus tax but that's still double.

Now I just read Jeff Atwood's post about netbooks. Netbooks are an emerging category of small ultra-portable computers basically designed for running a web browser, checking email, and maybe doing some word processing. Their specs seem to be in the range of 1.5GHz processor, 1GB RAM, 160GB hard drive, and a 7"-9" screen. Aside from the screen, that's better than the computer I'm writing this post on. And the price? Under $500. Jeff says:
They still have a way to go, of course, but the $299 or $199 no-compromises, go-anywhere, zero-monthly-contract-fees web browser in the palm of your hand -- with the requisite 9" or larger screen -- is almost upon us. I guess I hadn't been paying enough attention, because that's a shocker to me.
And that's exactly how I feel. I've heard people talking about Netbooks for a while but hadn't really realized how far they'd come. I'm still considering this new laptop my primary machine so I can't handle the small screen but if I had a desktop computer I would seriously consider getting one of these (with an external keyboard) to cover those "useful-to-have-a-laptop" situations.

The social pressure to display an Apple logo is intense (do you have any idea what percentage of people at computer conferences have Macs?) and I would probably spend $200 or $300 more for the privelege. If I can find something with a comparably beautiful screen, though, I think I may have to make do without the metallic finish.


Monday, 13 October 2008

Framing

After reading this article, I ordered a copy of George Lakoff's Don't Think of an Elephant. The book examines the use of language to "frame" arguments to your advantage. Take, for example, the phrase "tax relief". If there is relief to be had, tax is obviously a burden. How can anybody expect to succeed in arguing against something called "tax relief"? If you enter into the debate without reframing the issue, you lose.

Lakoff draws his examples largely from the context of the US political system and he makes no effort to conceal his Democratic leanings. Certainly not unbiased, the book is in fact a call to arms for Democrats, who Lakoff claims are decades behind Republicans in their understanding of these issues. All this means I take his words with a grain of salt.

Nonetheless, the discussion of mental framing and its effects fits with my observations of the world and seems broadly relevant. His analysis of the progressive and conservative movements themselves and their origins was also intriguing: I have no idea how accurate these theories are but I was able to look at conservative policy in a new light.

I was annoyed throughout by his repetition, both within and between chapters. In a few cases, I discovered several-paragraph-long sections that were taken almost verbatim from an earlier chapter. I discovered part way through that the book is a collection of essays and I have the impression they were thrown together quickly to get the book published in time for the last US election. This is partly to blame for the repetition but I think Lakoff is also overapplying one of his own messages: that mental frames are adopted through repetition.

That said, the book is short (100-and-some pages), cheap ($8 on Amazon), interesting, and a quick read so I recommend picking up a copy even if you only make it through the first two chapters.

Don't toss that margarine!

I grew up with butter. As a result, margarine just always seemed weird, even before the trans-fat scare (which, apparently, is no longer an issue with margarine).

Well, as of a couple of weeks ago, I have a reason to keep margarine in my fridge again: it takes tree sap out of clothing! Really. Rub margarine thoroughly into the clothing and use dish detergent to wash it out (no need to let it sit). Then run the clothes through the washing machine and you should have nothing but a pine-fresh scent remaining. It worked for me.