GWT Server-side Internationalization With Hermes

I recently made a post on my company’s blog about a new open source project I just released called Hermes. Here is a short excerpt:

Greetings interwebs! My name is Matt Bertolini and I am an engineer here at Travel Tripper. I thought it was about time I made an appearance on our tech blog. I want to talk about a new project I have recently finished and am sharing with the world.

A Little Backstory

Our application, RezTrip, is in the process of being internationalized. Since it is a GWT based application, we chose to use the GWT static string internationalization features. Unfortunately, these features only work on the GWT client-side and we have lots of other client-facing strings that need to be internationalized (client emails, legacy HTML pages, etc.).

The gwt-i18n-server Library

A quick Google search on the subject of “server-side GWT i18n” found a library called gwt-i18n-server. This library gives the server-side support for the GWT static string i18n interfaces and properties files. We quickly incorporated the library into RezTrip and found it was pretty buggy. Worse yet, development on the library had stagnated and hadn’t been updated in over a year. This is where I come in. Not satisfied with admitting defeat and implementing a separate i18n system just for server-side content, I decided to fork the gwt-i18n-server library and fix the bugs.

To read the rest of the story, click here.

PHP: Time To Break With the Past

A few weeks ago the Python Software Foundation released version 3.0 of the Python programming language. This was a big deal because version 3.0 broke backwards compatibility with the widely popular 2.x line of the language. Obviously, making the decision to break backwards compatibility was an extremely difficult one to make and many people have mixed feelings on the subject. My opinion on it is that the break is a good thing. The changes made to the language make it better and the way the organization is making the transition is smart.

But this post is not about Python, but another programming language: PHP. Unlike the Python Software Foundation, the PHP group have made some poor decisions about their language and I believe it is hurting the language and will ultimately lead to their downfall. I think it is time for PHP to do exactly what Python did and break backwards compatibility.

Now I don’t claim to be an expert in the inner workings of the PHP organization but I am a user of the language. I program all of my web sites in PHP and I have written a few applications in full object orientated PHP 5. I can say that trying to write a OO PHP app wasn’t the greatest experience and that is directly related to the deficiencies of the language. Here are a few things I think that the PHP group should do in the next version of the language to make it a more viable, competitive programming language.

Get Rid of Old Stuff

One of the first things that needs to be done to clean up PHP is to get rid of all of the duplicate functions and old libraries that continue to hang around from PHP 4 and below. For example, there are currently two different libraries for connecting to MySQL databases plus the PHP data objects library that also supports MySQL. There is no need for three separate ways to connect to the same database. The language is also riddled with functions that do the exact same thing. For example the die() function and the exit() perform the same action. The documentation even says that they are same. There is no reason to keep both of them around. PHP needs to clean up all of the redundant functions in the language and focus on making the core functions better.

Add Real Namespace Support

PHP is adding namespace support in the upcoming version 5.3. Unfortunately, rather than use a normal, sensible delimiter that many other languages use, such as the period (.) or double colon (::), the PHP group has decided to use the backslash (\), most commonly known as the directory separator in MS Windows. If you combine that with any sort of auto-loading, your asking for confusion. The developers need to wake up, admit their wrong, and overload one of their reserved characters to give us some proper namespace support.

Real Constructor and Function Overloading

While PHP 5 gave us much improved support for object oriented programming constructs, they dropped the ball in the area of polymorphism, especially constructor and function overloading. Its time to get rid of those stupid magic methods __get() and __set() and give developers real function overloading support. Storing all of your private instance variables in an array is not a clean, easy to read approach to storing data in objects.

Better Type Hinting Support

PHP is a dynamically typed language and I don’t mind that one bit. But even with a dynamically typed language, there still is a difference between a string and a boolean value. Type hinting goes a long way in making sure that the data you pass into a function is of the correct type but I think it needs a bit more to be truly useful. PHP needs to enable type hinting for the primitive types as well as custom object types and arrays.

Built in Documentation Support

This is sort of a want to have feature that I think all languages should have. I know that there are plug-ins and external programs that give you Javadoc like support (I use phpDocumentor) but having it built in would make it so much easier to generate documentation. Its not a deal breaker but it would be great to have.

Single Extension Repository

One of the great parts about PHP is the large number of high quality plugins and modules that you can download and instantly expand the PHP language to support all sorts of technologies and systems. The problem is that they are housing in two different extension repositories: PECL and PEAR. While they use the same package structure there really isn’t any reason that I can tell to have two. To me it just creates confusion for newcomers and inexperienced developers. Lets drop the separate repositories and and create one uniform repository to house all of those great extensions.

So that is my short list on things that need to be fixed in PHP for it to continue to compete against languages like Java, C# and Python. Feel free to disagree and comment below. If you have a suggestion for other features that should be added/changed/removed, let me know. I welcome a good discussion. 🙂

LAME MP3 Encoder for Windows Download

For those of you who use the LAME MP3 Encoder to rip CDs to MP3 (like me), the LAME project recently released version 3.98.2 of the encoder. Since the LAME project does not release compiled binaries, I thought I would compile the encoder and stick it on my site for all to download. I know from experience that finding the latest version of the encoder compiled for windows can sometimes be hard so I thought I would help the cause. The zip file below contains both lame.exe and lame_enc.dll. It was compiled with Visual Studio 2008 on Windows Vista. Please let me know if you have any issues with the files or if you find a newer version of LAME was released (so I can update my files).

Update 2010-10-03: I have updated the LAME library to 3.98.4. It was compiled with Visual Studio 2008 on Windows 7.

LAME MP3 Encoder (Win32)

Apple Notebook Event Reaction

Yesterday Apple had a small event in California to unveil their new notebook line. Apple announced a new Macbook, Macbook Pro, and Macbook Air. I was especially interested in the announcements because I am in the market for a new Mac and I was leaning towards a laptop.

Nvidia Graphics

One of the larger announcements made at the event was how the new notebooks were going to include the new Nvidia mobile chipset and graphics chip. The new chipset should give a nice speed boost for many high end graphics applications (like the new Photoshop CS4) and allow for more gaming capabilities on the Mac platform. While I welcome the new chipset I am not going to be doing much graphics work on my laptop so I am not that interested.

Aluminum Enclosure

Another big announcement made was about the new manufacturing process for the notebooks. All three of the notebooks are now being made using a unibody construction technique. They made the cases out of solid aluminum to make them stronger and more durable. I really like the new aluminum cases and I am all for a stronger, durable laptop. I am glad I waited to buy a new mac because these cases are much nicer than the plastic ones of the previous generation.

Glass Trackpad

One feature I am going to have to try before I buy is the new mouse trackpad. I have been wishing Apple add a right-click button on their laptops (or all Apple computers for that matter) for a long time. But instead of adding a button, they decided to take away mouse buttons all together. Apple made the entire trackpad a button and made the it even larger to support multi-touch gestures like they have on the iPhone. I have an iPhone and iPod touch and I like the touch gestures but I don’t know how well they will work on a notebook. I plan on going to an Apple store to try out the new trackpad before I make any decisions on the notebook.

24 Inch Cinema Display

Another announcement they made was a brand new 24 inch monitor with a built in web cam, microphone, and USB hub. It’s a very nice monitor but it is still much more expensive then other monitors of the same side. I don’t think a web cam is worth an extra 200-300 bucks.

Disappointments

I was disappointed with the lack of Blu-Ray support for any of Apple’s computers. I could care less if they put the drives in the computers but I at least want the ability to play them if I put my own drive in. Steve Jobs said that they are holding off until licensing issues are resolved and demand picks up. While I agree that Sony needs to ease up on some of these absurd licensing and DRM restrictions but I don’t think Blu-Ray will take off until a company like Apple makes it easy.

I was also disappointed with the lack of a real price cut. Apple did technically reduce the cost of the laptops but that is only for an under powered machine with the old plastic case. The new notebooks with all the great features are still rather expensive and I think that is a mistake. But I can’t say that I am surprised since Apple never has any really affordable products.

Final Thoughts

Overall I am pleased with the new notebooks. As I said earlier, I am definitely going to try before I buy any notebook so I guess I am off to an Apple store this weekend.

Simple Backup Script using Windows Script Host and JScript

At work, I do my development on my local hard disk. I do this mainly for speed. But in between CVS check-ins I need to make sure I don’t lose any data. The company gives us all network drives that they keep backed up so I decided I would backup my local data to the network drive every night. I didn’t want to do this every day before I left work so I decided to write a script to automate the process. I had a few goals for this script to accomplish:

  1. Back up all the data in my local folder to a designated folder on my network drive.
  2. Keep each days backup in a separate folder labeled with the date of the backup.
  3. Automatically check the backup directory for backups older than a specified amount of days. I wanted to keep 5 days of backups at a time.

So I started to write a simple batch script to accomplish my goals. I always try to start with the simplest language to solve my problem. There is no reason to write a full blown application for a such a simple task. As I was writing the batch script the backing up part was easy to write but I couldn’t quite get my automatic deletion of older backups to work the way I wanted to. So I decided to abandon the batch script and move up to the next level. I examined the tools I could use and I decided to utilize another scripting technology built into Windows: the Windows Script Host or WSH.

There are two types of languages you can use to write WSH scripts: VBScript and JScript. VBScript is a simple scripting language based on Visual Basic and JScript is the same but based on JavaScript. I am familiar with both Visual Basic and JavaScript so I had a choice to make. I decided to use JScript because I like the syntax style better than Visual Basic.

So I hopped onto MSDN and read up on WSH and JScript syntax and a few hours later, had a finished script. I was pleasantly surprised at the power that the WSH and how easy it was to develop the script. Below is the script:

/*
 * Local to Network Drive Backup Script
 * Version 1.0.2 -- 2008-10-22
 * Written by Matt Bertolini
 *
 * Copyright (c) 2008 Matt Bertolini
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

// Variables to customize
var appName = "Local to Network Drive Backup Script";
var appVersion = "1.0.2";
var appVersionDate = "2008-10-22";
var sourceDir = "C:\\path\\to\\files\\to\\backup";
var backupDir = "C:\\path\\to\\backup\\folder";
var numDaysSaved = 5;

// Editing below this line is not recommended.

// Windows Script Host objects
var out = WScript.StdOut;
var fso = WScript.CreateObject("Scripting.FileSystemObject");
var WshShell = WScript.CreateObject("WScript.Shell");
var currentDateObj = new Date();

// Event log constants
var LOG_EVENT_SUCCESS = 0;
var LOG_EVENT_ERROR = 1;
var LOG_EVENT_WARNING = 2;
var LOG_EVENT_INFORMATION = 4;
var LOG_EVENT_AUDIT_SUCCESS = 8;
var LOG_EVENT_AUDIT_FAILURE = 16;

// Display script information to console.
out.WriteLine("===============================================================================");
out.WriteLine("\n  " + appName + "\n");
out.WriteLine("  Version " + appVersion + " -- " + appVersionDate);
out.WriteLine("  Written by Matt Bertolini\n");
out.WriteLine("  Script Directory: " + WScript.ScriptFullName);
out.WriteLine("  Backing up files for date: " + dateToIsoString(currentDateObj));
out.WriteLine("  Number of days to keep backups: " + numDaysSaved);
out.WriteLine("  Directory being backed up: " + sourceDir);
out.WriteLine("  Backing up to directory: " + backupDir);
out.WriteLine("\n===============================================================================\n");

// Execute script functions.
backupFolder(sourceDir, backupDir);
deleteOldBackups(backupDir, numDaysSaved);

WScript.Quit(0);

function deleteOldBackups(backupDir, numDaysSaved)
{
	// Create folder object for backup directory
	var backupDirObj = fso.GetFolder(backupDir);

	var fc = new Enumerator(backupDirObj.SubFolders);
	for(; !fc.atEnd(); fc.moveNext())
	{
		var folderName = fc.item().Name;
		var cutoffDateObj = new Date();
		cutoffDateObj.setDate(currentDateObj.getDate() - numDaysSaved);
		if(fc.item().DateCreated < cutoffDateObj)
		{
			out.Write("Deleting backup " + folderName + "... ");
			fso.DeleteFolder(fc.item(), true);
			out.WriteLine("done");
			WshShell.LogEvent(LOG_EVENT_SUCCESS, appName + " - Old backup " + folderName + " deleted successfully.");
		}
	}
}

function backupFolder(sourceDir, backupDir)
{
	try
	{
		if(fso.FolderExists(backupDir) == false)
		{
			out.Write("Backup folder does not exist. Creating folder...");
			fso.CreateFolder(backupDir);
			out.WriteLine("done");
		}
	}
	catch(e)
	{
		out.WriteLine("Could not create backup folder.");
		WshShell.LogEvent(LOG_EVENT_ERROR, appName + " - Could not create backup folder -- " + e);
	}

	try
	{
		out.Write("Creating folder for today\'s backup...");
		backupDir = backupDir + "\\" + dateToIsoString(currentDateObj);
		fso.CreateFolder(backupDir);
		out.WriteLine("done");
		out.Write("Backing up files...");
		fso.CopyFolder(sourceDir, backupDir);
		out.WriteLine("done");
		WshShell.LogEvent(LOG_EVENT_SUCCESS, appName + " - " + "Backup successful.");
	}
	catch(e)
	{
		out.WriteLine("Backup failed.");
		WshShell.LogEvent(LOG_EVENT_ERROR, appName + " - Backup failed -- " + e);
	}
}

function dateToIsoString(dateObj)
{
	var yearStr = dateObj.getYear().toString();
	var monthStr = (dateObj.getMonth() + 1).toString();
	var dayStr = dateObj.getDate().toString();
	if(monthStr.length == 1)
	{
		monthStr = "0" + monthStr;
	}
	if(dayStr.length == 1)
	{
		dayStr = "0" + dayStr;
	}
	return yearStr + "-" + monthStr + "-" + dayStr;
}

Next, I wrote a small batch file to call the Windows Script Host with the parameters that I wanted. Here is the batch file:

@echo off
cls
setlocal
title Local to Network Drive Backup Script
call cscript.exe //nologo backup.js
endlocal
cls
exit

Now for the best part. I am releasing the script under the MIT License so everyone is free to use and modify the script. All you have to do is keep the license at the top. Now I know the script is not perfect so if you find any bugs or have any suggestions on how to improve it, comment in this post and I will see what I can do.

Update 1 – 2008-10-02

I found a small bug in the ISO date formatting function so I have updated the script and bumped the version up to 1.0.1.

Update 2 – 2008-10-22

I have updated the script to version 1.0.2 by adding some more logging features (to the Windows Event Viewer) and to fix a bug with the deletion of old backups).

Apple WWDC 2008 Keynote Reaction and Reflection

I have now had more than a day to digest all of the information that came out of Steve Jobs’ keynote speech at the Worldwide Developers Conference in San Francisco on Monday. I have broken down my reaction into sections based on the different parts of the keynote speech.

iPhone 2.0 Software Update

The first part of the keynote was devoted to the upcoming iPhone 2.0 software update. This update was originally announced in March along with the software development kit. This part of the speech was probably the most boring part for me since most of the information was already discussed in March. They made the speech even more painful buy bringing up numerous developers to demo and talk about the applications they had written for the iPhone.  While I don’t mind a quick demo or two, the number of demos they had was a bit excessive.  By the fourth or fifth I was pretty tired of the whole exercise and wanted something different.

Mobile Me

After the iPhone app demos, Apple introduced Mobile Me. This is a service that allows you to keep your email, calendar, and contacts on a central server have all of that data pushed to all your computers and mobile devices (like your *ahem* iPhone). All of this data stays up to date on all of your computers and devices. If you update a calendar appointment on your computer, your iPhone is updated automatically.  This has been around for many years in the business world. Apple even bills Mobile Me as “Exchange for the rest of us”. Apple has also made a set of pretty cool AJAX web applications for email, calendar, and address book so you don’t even have to use a desktop client if you don’t want to or can’t. I really like the idea of having all of your data up to date on your devices.  It has been something I have wanted to do myself for a long time.  While this server is very appealing to me, the price is not.  It is $99 USD a year.  I much rather host a server on my own network and perform the same services that Mobile Me does for free. We will see if I can do that or not.

iPhone 3G

The final announcement that was made I am extremely excited about but kinda figured it was coming. On July 11 Apple will be releasing the second version of the iPhone, named iPhone 3G. The 3G refers to the HSDPA modem now included that will allow for much faster data and Internet access. The main reason I held out on buying the original iPhone (and got an iPod Touch) was due to the slow data transfer speeds via EDGE. So I am definitely going to be purchasing this new iPhone. The best part is Apple dropped the price to $199 USD for the 8GB model and $299 USD for the 16 GB model (I’m sold on the 16GB so I can hold all the cool new apps). One annoying rumor I’ve heard is that Apple won’t be selling the new iPhone on their web site as they have done in the past. That means I am going to have to camp out in front of my local AT&T store to get one.

Mac OS 10.6 “Snow Leopard”

While they didn’t really talk about it at the keynote, they did mention that the next version of Mac OS X, or 10.6, will be called “Snow Leopard” and the developers there were going to get some more information on it during the week. Apple did post a small page on their web site and it seems that they are really going to focus on stability and making 64 bit a requirement. Rumors are saying that this next release might be Intel Mac only which finally gives me an excuse to buy a new Mac.

There you have it; my reaction to the WWDC keynote. Looking forward to what Apple has up its sleeve for Macworld San Francisco in January.