Google Wave: Why I care.
The Internet has been buzzing lately about Google’s new application, Wave. Though it is still under a limited preview, everyone seems to be talking about it. I have heard everything from the evangelicals touting this as a sign of the coming singularity, to people just not getting it or thinking it too complicated to understand.
For most people, Google Wave indeed will not make much sense. At least not yet. However, for the developers and engineers out there though and the people who work remotely or just on teams, there is something more to be seen in its future. When I look at Google Wave, I see the ability to email out a requirement document for a project to a whole team. The ability to change and modify it as the project grows and shrinks (as it always does). The ability to keep track of the changes, much in the way one would do with a wiki. The ability to add someone to an existing conversation and for them to be able to easily use that history and the comments along with it to understand why changes are being made.
In short, I see a complete change in how a project team works.
There is nothing truly revolutionary here. With the use of IM clients, a project management tool like Base Camp, a wiki and an E-mail client, you could do this today. Why would you want to though? Keeping track of these disparate systems is possible, but if there is a better way, I would take it. Wave gives you a way to do all of these things succinctly.
For me, Google Wave is more than some preview software. It is a preview of the next phase in the web’s evolution. It may not be the final draft of what is to come, but it shows us that there is a better way to communicate than E-mail really provides us. We do not need to be slaves to one off messages. Chained by the droves of responses and replies.
What Wave has to offer may not seem immediately obvious to you. That is okay. Its benefits are not short term ones. Until it can act as an e-mail client as well, so that people can more easily transition into it, adoption will be slow. However, it is an open protocol, just as E-mail itself is. Which means we will hopefully see more servers out there in the coming months and years.
Google may have started this thing we now know as Wave, but I by no means think it is anywhere near finished.
Error handling in PHP, or how we won the war.
One of my biggest gripes about PHP in comparison to other modern object-oriented languages is the relatively poor state of error handling. The mix and match style of triggered errors and exceptions is unbefitting of a modern language, especially one that is ready for the enterprise. Most modern languages deal with errors strictly through the throwing of exceptions, because it allows for a more robust method of triggering a response from the system. This is because a thrown exception, can be caught. In PHP though, a triggered error cannot.
At least not technically.
Lucky for us there is a way to make PHP behave a little more civilly than it does by default. Through some clever uses of the error and exception handlers, we can make PHP just a little more robust.
Our Exception
First we start with our exception object. Personally, I’m a fan of explicit exception naming, so that I can more easily catch very particular exceptions. For this example we will use one that I will cleverly name PhpException.
class PhpException extends Exception {}
In this case we will not be modifying what the Exception object does, only giving it a new name to reference by. If you’re new to exceptions, then trust me, this will make your life easier down the road when you’re catching an exception from a method that that can fail in a couple different ways. Being able to single out one exception type that you know how to better handle is much preferred than catching everything and maybe covering up a real problem.
The error handler
In short what the error handler is, is a function or class method that you define as the recipient of any php error that is triggered in the system. This is by far the most common way for php native function to trigger their errors. The error handler is the first thing to happen after the triggered error. It is given a list of the message, the error code, the file it occurred in and on what line. From there, as long as you do not return a boolean false, it will not follow the normal error pattern. In our case, what we want to do is provide some new options. So, we will wrap this error in our new PhpException class.
function handleError( $code, $message, $file, $line, $context )
{
// Silencing a statement with @ causes this to be 0.
// Let's be respectful and not throw errors if silenced.
if ( ini_get( 'error_reporting' ) == 0 ) {
return true;
}
$msgTpl = 'PHP Error (%u): %s in: %s:%u'
$message = sprintf( $msgTpl, $code, $message, $file, $line );
throw new PhpException( $message );
}
set_error_handler( 'handleError' );
At it’s core, this is a very simple method of converting a triggered error into an exception. It first checks to see if error reporting is off, due to a silence. If that is the case, it exits early, since we can ignore that error. Otherwise, it just turns the error to an exception object and throws it. With this done, we can now catch the uncatchable.
try {
trigger_error( "You can't catch me!", E_USER_ERROR );
} catch ( PhpException $e ) {
// Oh yes I can!
}
In the most basic of ways, we have made PHP errors catchable exceptions. This is an extremely desirable behavior. The only errors that will not be caught by this are compiler and parse errors. We’ll get to parse errors later though.
Speaking of error types, what is wrong with the above example?
We are catching too much. Some of the error types that are thrown are warnings and we do not want them stopping a code run like an exception will do. This is easy to fix though. What we’ll do is create a list of the two error type and check what kind we have then act accordingly. For this, I am going to turn our error handler function into and EventHandler class, as it will give us some more flexibility later in the examples.
class EventHandler
{
const MSG_TPL = 'PHP Error (%u): %s in: %s:%u';
protected $warningLevels = array (
E_WARNING,
E_NOTICE,
E_CORE_WARNING,
E_COMPILE_WARNING,
E_USER_WARNING,
E_USER_NOTICE,
E_STRICT,
);
protected $fatalLevels = array (
E_ERROR,
E_PARSE,
E_CORE_ERROR,
E_COMPILE_ERROR,
E_USER_ERROR,
E_RECOVERABLE_ERROR,
);
public static function start()
{
$handler = new EventHandler;
set_error_handler( array ( $handler, 'handleError' ) );
}
public function handleError( $code, $message, $file, $line, $context )
{
// Silencing a statement with @ causes this to be 0.
// Let's be respectful.
if ( ini_get( 'error_reporting' ) == 0 ) {
return true;
}
$message = sprintf( self::MSG_TPL, $code, $message, $file, $line );
if ( in_array( $code, $this->warningLevels ) ) {
error_log( $message );
if ( ini_get( 'display_errors' ) ) {
echo '<p>Warning! ' . $message . '</p>';
}
return true;
}
if ( in_array( $code, $this->fatalLevels ) ) {
throw new PhpException( $message );
}
return true;
}
}
EventHandler::start();
What you’ll notice here is that we now have an object to encapsulate our logic and we now distinguish between warning and fatal level errors. In this case, a warning will still write to the PHP error log as the default behavior would do and if display errors is on (like it should NOT be in your production environment) then it will also print that error to the screen. Aside from that, it works identically. Error is caused, if it is fatal, it becomes an exception.
What to do with those exceptions.
Well, we’ve turned all of our fatal errors into catchable exceptions, but what do we do with those now? In some cases we will know what to do and will catch them. In others, we may not anticipate them or we may not know how to handle them and will need to cause a 500 Internal Server error to occur. This is where the exception handler comes in.
Like its brother the error handler, the exception handler is designed to catch exceptions for you automatically. The difference between the two is that errors are caught immediately, an exception will travel back up the call stack until it reaches the point you started you code in. At that point the exception handler will kick in and go all last action hero for you. The idea is, this will handle any failure logic you need, which can be as simple as logging the message in a certain way, as complex as showing a super pretty 500 error page or perhaps a little of both.
Let’s add a couple methods to our EventHandler class.
public function handleException( $exception )
{
header( 'Status: 500 Internal Server Error' );
$this->sendNotice( $exception->getMessage() );
$this->printError( $exception->getMessage() );
exit;
}
protected function sendNotice( $message )
{
$to = 'me@myemail.com';
$subject = 'An error occurred on your website.';
$from = 'errors@mywebsite.com';
$message = wordwrap( $message, 70 );
$headers = "From: %s\r\nReply-To: %s\r\nX-Mailer: PHP/%s";
$headers = sprintf( $headers, $from, $from, PHP_VERSION );
mail( $to, $subject, $message, $headers );
}
protected function printError( $message )
{
// Clear the output buffer. Yes you should have started this
// at some point to avoid fragments of unwanted
// data on your page. See ob_start().
ob_clean();
// Load a template.
echo "<h3>An error has occurred.!!</h3>";
echo "<p>Thank you, come again.</p>";
if ( ini_get( 'display_errors' ) ) {
echo "<p>" . $message . "</p>";
}
}
In this case I have chosen to e-mail out that an error occurred to myself and print a message to the user indicating that there was a problem. For the printError() part I usually pull in a full page template, in the site’s style, but for this example I am keeping it as brief as possible.
To enable this code, just add this line to the bottom of the start() method of the EventHandler class we’ve been making.
set_exception_handler( array ( $handler, 'handleException' ) );
Depending on how complicated your code gets for handling the exception, you may also want to consider wrapping the logic in that method in a try catch block that catches all exceptions. The reason being is that if you are generating a template and a secondary exception is thrown, you will see the dreaded “exception thrown without a stack trace on line 0” error. By wrapping that logic in a try-catch block you can catch it and have a simpler fail over available. Usually mine is just log it, and die(). As in that case I want to be as simple and brief as possible.
A brief example:
public function handleException( $exception )
{
header( 'Status: 500 Internal Server Error' );
try {
$this->sendNotice( $exception->getMessage() );
$this->printError( $exception->getMessage() );
} catch ( Exception $e ) {
$tpl = 'Something really bad happened. An exception was thrown '
. 'in the exception handler. Message: %s, File: %s, Line %u';
error_log( sprintf( $tpl,
$e->getMessage(),
$e->getFile(),
$e->getLine() ) );
}
exit;
}
You can of course do much more than that. Hopefully this was enough to get you thinking about some new possibilities though.
Parse Errors
There is one last type of error that you can catch, that is otherwise harder to see. That is the parse error. This happens when a file you include has a syntax error in it. Usually you’ll see a generic message and a message in your error log. This means you may miss it if some bad code hits your production site.
Luckily PHP has a way to add a shutdown function that will run even when the PHP is crashing. Add this to your EventHandler class.
public function start()
{
....
register_shutdown_function( array ( $handler, 'handleShutdown' ) );
}
public function handleShutdown()
{
if ( !$error = error_get_last() ) {
return;
}
$message = 'Uncaught ' . sprintf( SELF::MSG_TPL,
$error['type'],
$error['message'],
$error['file'],
$error['line'] );
$this->sendNotice( $exception->getMessage() );
$this->printError( $exception->getMessage() );
}
Now we can add a custom message and even a pretty 500 page if we so choose. No more white screens of death for your visitors, just because you forgot something. It happens, we all make mistakes. The point is to have events like these set up to make it less apparent or at least less horrible to our visitors.
Conclusion
The most important feature your can add to any application or framework is a robust way to handle when something goes wrong. Something always will and the better the experience is for your visitors, the more likely it is that they will come back. On the same note, the better your error reporting, the easier time you will have finding and fixing those errors when they occur.
There are all sorts of ways that you can extend what I’ve shown you. The error handling routines I have written for the framework I maintain provide all sorts of other useful information for my company and my team. Of course that goes outside of the scope of this article, I just hope that this gets you thinking on ways to make your own systems the best they can be.
How do you handle errors in your projects?
Media Server, meet the Acer easyStore H340

When I first started thinking about building a server to house my growing collection of digital videos, my needs seemed simple enough. I needed a low-power computer to house a few tera-byte drives in. The computer needed to be able to run as a DLNA server, so as to stream video to my Playstation 3. On top of that, I wanted something relatively low maintenance. I love to play with new toys as much as the next bloke, however in this case, I need something that I can leave on and forget about.
My first thoughts led me to building a simple Linux server. However, as I started looking into cases and motherboards my needs jumped from, simple media server to ESX server. Why? Because that would be a really fun toy. However, it is not practical and does not meet my number one need. That it be low maintenance. Even if it could house a media server as well as a webserver and act as a router and all sorts of other fun things.
So I shelved the idea for a while. Brewed over it. I thought I about getting a Drobo, for little while, but the more I read on those, the less simple they seemed. Maybe simple if you’re talking about a backup system plugged in via USB to your computer. But plug it in via the network and run server processes on it. All I could see was a big sign saying, “this way be dragons.” Once again, simple.
Fortuitously enough, during one of my readings I stumbled on the name “Windows Home Server” (WHS). I had seen mention of this before. However hadn’t really thought much about it, since my brain was in Linux mode. However Linux = dragons in this case. Linux was giving me so many fun options and toys, that it would never be a fully working media server. It would instead be a toy that remained in a half-installed state most of the time because I would be playing with it endlessly.
That is after all what I do.
Windows Home Server
When it comes the Microsoft’s Windows Home Server (WHS), there are currently two major players in that arena.
HP has their Media Smart EX/LX series, which on first glance seemed really great, however they just did not seem to meet my hard disk needs. The EX seemed expandable, but would require I replace the hard disk that comes with it. Also, while they claim it is upgradable to 9-terabytes of storage space, that is utilizing the USB and ESATA ports on the back for external storage. In the end though, the EX just seemed to be too expensive for what it was. At about $599, I’d still need to spend a few hundred on four 1-terabyte drives to fill the thing.
The LX model is cool little machine. Sporting an Intel Atom processor, it definitely is a low power, low profile machine. However it seems to be suited best as the PC equivalent of a Time Machine backup server. It has very little storage capacity at 640 gigabytes and no real ability to expand. Overall, it just was not what I was looking for. There is only one other major competitor in the WHS market at the moment and that would be Acer.
The Acer Aspire Easystore H340 immediately struck a chord in me as it not only has a nice case, but has some decent technical specs. It sports the Intel Atom processor, similarly to the Media Smart LX, so it definitely fits into the low power category. However in this case, that is good, as I do not plan to do any data crunching on this machine. I just need it to not run up my power bill too badly if I leave it on. By default it comes equipped with 2 gigabytes of ram and a 1 tera-byte drive. Similar to the Media Smart EX it also has three free drive bays to fill. Unlike the HP equivalent though, I would not need to replace the drive it comes with in order to meet the system maximum capacity. On top of that it was available on New Egg for $399 with a free 1-terabyte Western Digital Green SATA drive.
So for two hundred dollars less I get two terabytes of drive space and I only need to buy two more to fill it. Which is exactly what I did. So, for under $600 shipped I got a 4-terabyte Windows Home Server. Things keep getting better.
Installation Experience
The drives themselves were a breeze to install. No tools needed, as all the drive bays are hot-swappable. The system just accepted them and automatically formatted them into its main drive array.
As the system is a headless computer, you only need two cables to get it going, the power cable and an ethernet cable. All configuration is done via the installation DVD on a separate Windows PC. This is key, you must run it from Windows, no exceptions. So if you only have a Mac, unless you’re sporting Windows under Parallels or Bootcamp, you won’t be able to set up the system. Once it is setup though, all configuration is done through Remote Desktop.
Setup itself consists of finding the system on the network, which it does auto-magically. Updating the server installation to the newest versions, creating your administrator password and finally giving the server a name. Once this is done you will find yourself under the main console screen. From here I recommend you create a user for yourself to use. For the most part though, you are done and ready to go here. I went the extra step of logging into the server via remote desktop and giving it a static IP address. I did this largely so that I can easily find it when I’m connecting from my Macbook Pro, as you will not be able to use the server name by default like you do with a Windows computer.
The whole setup process took at most an hour and that was simply due to the updates the system did in the beginning.
By default you need to do little more than copy your music, movies and pictures into the appropriately named shares and they will show up for most DLNA or UPNP enabled devices. This includes iTunes, Windows Media Player 11 and WinAMP on your computer and in my case, my Playstation 3 as well. An XBOX 360 will work as well, however it does not support nearly as many video formats as the PS3.
For your own reference, there is a great community over at Home Server Plus, with all sorts of advice and ideas on what to do with a WHS box.
Overall, I couldn’t be happier with my new media server. It is simple, robust and can easily stay out of the way of my normal computing, while still enabling me to do more with my media collection.