no such file to load -- openssl (RuntimeError)

I was trying to deploy an older Rails 2.2.2 app to a new server and when I started up the application, I ran into the following error:
in `require_frameworks': no such file to load -- openssl (RuntimeError)
Hmm...my app doesn't even use SSL. Whatever...(think this is because capistrano is involved?) To fix this, I installed openssl by running
sudo apt-get install libopenssl-ruby1.8
Success!

Oh yeah! I got married!

It's been awhile since I updated this and big things have happened since. Cutting to the chase: On June 20th, 2009 I married the lady of my dreams, Patcharee Phongsvirajati. The wedding ceremonies took place at our houses and the reception was held at Foxchase Manor. Check out some photos taken by a few of the many photographers: Photography by Mac Pham, my cousin: Photography by the Pros: Photography by Cau Duc, my uncle:

Google App Engine adds Java support (Review)

Last night Google announced Java support on Google App Engine. After a bit of toying around, here are my findings. The Eclipse plugin is pretty slick. Deploying and build is simple. The dev server that you spin up locally looks to be jetty under the hood. Objects intended for storage are JDO annotated and after compiling, you run the .class files through the DataNucleus Enhancer which adds additional metadata so Google can map it to BigTable. The Eclipse plugin automatically performs this step for you after compiling. The examples provide a bunch of ant macros to help facilitate building/deploying. One issue that I had was that the project was building with Java 1.6 and I would get an error after compiling:
Caused by: java.lang.UnsupportedClassVersionError: Bad version number in .class file

Even though they say they support Java 1.5 and 1.6, I guess this doesn’t work on the Java 1.6 for the Mac. Switching the build to 1.5 allows the DataNucleus Enhancer to run successfully. Even though they are using JPA, some features have not yet been implemented or supported ( see http://code.google.com/appengine/docs/java/datastore/usingjpa.html#Unsupported_Features_of_JPA) Overall, I like what I see so far and think this would be great for quick prototypes of web apps/services. Going through the tutorial, my awesome Guestbook application has been created and deployed.

Custom field names in Rails error messages

The defaults in Rails with ActiveRecord is beautiful when you are just getting started and are created everything for the first time. But once you get into it and your database schema becomes a little more solidified, the things that would have been easy to do by relying on the conventions of Rails require a little bit more work. In my case, I had a form where there was a database column named "num_guests", representing the number of guests. When the field fails to pass validation, the error messages is something like
Num guests is not a number
Not quite the text that we want. It would be better if it said
Number of guests is not a number
After doing a little bit of digging, I found the human_attribute_name method. You can override this method in your model class to provide alternative names for fields. To change our error message, I did the following
class Reservation < ActiveRecord::Base
  ...
  validates_presence_of :num_guests
  ...
  HUMAN_ATTRIBUTES = {
      :num_guests    => "Number of guests"
  }
  
  def self.human_attribute_name(attr)
      HUMAN_ATTRIBUTES[attr.to_sym] || super
  end
end
Since Rails 2.2, this method is used to support internationalization (i18n). Looking at it, it reminds me of Java's Resource Bundles and Spring MVC's error messages. Messages are defined based off a key and there's a chain of look ups that get applied to resolve an error's message. Although, I don't see myself doing any i18n work in the near-term, it is cool that we have that option now in Rails.

Recognizing talent (at the metro)

After reading about the violinist playing in the metro (which happened awhile ago), I think we are, at many times, too preoccupied with ourselves and the things that are happening in our lives when we should be taking a moment or a step back to recognize the great things that are happening right in front of us. Do you think you would be able to recognize extraordinary talent when it is staring you in the face? Video for viewing pleasure:

Checkboxes in Stripes and Spring MVC

When building dynamic web sites with lots of javascript UI components being created on the client, understanding how the web framework you're using will process the request and what must be done to update fields accordingly is even more important. Specifically, checkboxes have always been a pain to deal with. The gotcha with checkboxes are if a checkbox isn't checked, the request doesn't send the parameter so it requires some additional checks to detect that the user deselected something that was there to update the field accordingly. I've been playing around with the Stripes framework and ran into this issue. With Stripes, you can render a checkbox using their JSP tag:
<stripes:checkbox checked="true" name="property1" value="yes"/>
<stripes:checkbox checked="true" name="property2" value="no"/>
When the "checked" value is equal to "value" value, Stripes will render the checkbox as checked. So with the code shown, two checkboxes will be shown with the first checked and the second unchecked. If a user reverses this by unchecking the first, checking the second, and submit the form, the HTTP request will only see that property2=no. Before the form was submitted, "property1" had a value of "yes". Now, "property1" won't even appear in the request parameters, so we have to do special handling to check for the absent of the parameter to update "property1" to whatever value it should be when it is not checked. In Spring MVC with form binding, checkboxes are dealt with a little differently. Using Spring MVC's form JSP tag, you can do:
<form:checkbox path="property1" value="yes"/>
  <form:checkbox path="property2" value="no"/>
Assuming your command bean is named "person", this will generate the following HTML:
<input name="person.property1" type="checkbox" value="yes"/>
        <input type="hidden" value="1" name="_person.property1"/>
        <input name="person.property2" type="checkbox" value="no"/>
        <input type="hidden" value="1" name="_person.property2"/>
As noted by the docs,
What you might not expect to see is the additional hidden field after each checkbox. When a checkbox in an HTML page is not checked, its value will not be sent to the server as part of the HTTP request parameters once the form is submitted, so we need a workaround for this quirk in HTML in order for Spring form data binding to work. The checkbox tag follows the existing Spring convention of including a hidden parameter prefixed by an underscore ("_") for each checkbox. By doing this, you are effectively telling Spring that “the checkbox was visible in the form and I want my object to which the form data will be bound to reflect the state of the checkbox no matter what”.
Spring MVC also provides a "checkboxes" tag which allows you to render a list of checkbox boxes without having to wrap the "checkbox" tag around a JSTL forEach. Hopefully, that gives you some insight into how to work with checkboxes in Stripes and Spring MVC.

IBM to buy Sun? Yay for developers!

There's buzz going around that IBM is in talks to buy Sun. Brian Aker, Director of Technology for MySQL at Sun, gives some insights into what he thinks will happen if this deal goes through. Many have concerns that there's a huge culture clash and IBM will just gobble up all the great things MySQL and Sun have produced. All valid concerns. However, if IBM can maintain the developer community relationship that Sun and MySQL have built I think developers may have a lot to look forward to. Especially, government contractors. First thing that popped into my mind when I read this was
Sweet! No more heavy-weight Oracle development. The government will allow devs to use MySQL now!
After all, it's backed by Big Blue. And nobody ever got fired for choosing IBM. Right? Installing Oracle on a laptop still gives me nightmares. *shudders*

Parallels Desktop vs VMWare Fusion

Ever since I got my Macbook, I've used Parallels with my Book Camp partition to run Windows side-by-side with OSX. I had heard that there was this other option of using VMWare Fusion but never really bothered to look into it. This was true until this weekend. It had been a couple of days since I recently upgraded to 4gb of ram. I actually had not started up Parallels in awhile but I wanted to test something in the dreaded Internet Explorer so I started up Parallels. I was presented with the following message:
Windows could not start because the following file is missing or corrupt:
system32hal.dll.
Please re-install a copy of the above file.
Uh, what? Must be a fluke! So, let's try this again.
Windows could not start because the following file is missing or corrupt:
system32ntoskrnl.dll.
Please re-install a copy of the above file.
Uh-oh. This doesn't look good. After googling a bit, it turns out Parallels does some pretty bad things like modify essential Windows boot up files to get Boot Camp to work with Parallels. They even modify boot.ini! So, I think what happened to me was that Parallels crashed at some point and corrupted/deleted these essential Windows files rendering my Windows partition unbootable. This is what you call a deal breaker. If your software's purpose is to allow other operating systems to run, rendering said operating system unusable is a big no no. So, I've been using Fusion for a day or two now, feature for feature pretty much has everything Parallels had. Even the user interface is fairly similar, they just call things a little different. For example, what Parallels calls Coherence, Fusion calls Unity. Performance is about the same but I don't really play games or anything other than startup Internet Explorer when running Windows. Best of all, Fusion doesn't seem to do terrible things like modify Windows boot up files. Fusion beats Parallels hands down.

Setup Apache on Mac OSX Leopard

I've had my Macbook for a little over a year now. However, I just recently found out Leopard comes with apache (apache2 to be specific) already installed. To verify this is true, open up Terminal and type
>> apachectl -V
Server version: Apache/2.2.9 (Unix)
Server built:   Sep 19 2008 10:58:54
Server's Module Magic Number: 20051115:15
Server loaded:  APR 1.2.7, APR-Util 1.2.7
Compiled using: APR 1.2.7, APR-Util 1.2.7
Architecture:   64-bit
Server MPM:     Prefork
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/prefork"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_FLOCK_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=128
 -D HTTPD_ROOT="/usr"
 -D SUEXEC_BIN="/usr/bin/suexec"
 -D DEFAULT_PIDLOG="/private/var/run/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_LOCKFILE="/private/var/run/accept.lock"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="/private/etc/apache2/mime.types"
 -D SERVER_CONFIG_FILE="/private/etc/apache2/httpd.conf"
To start up apache, you can do it a couple of ways. Type sudo apachectl -k start or
  1. Go to System Preferences
  2. Click on Sharing
  3. Check the box that says Web Sharing
You can go to http://localhost or the URL provided in the Web Sharing screen to confirm apache is running and is able to serve up requests. There is also a ~/Sites directory in your home folder. Apache is already setup to serve up files from this directory under http://localhost/~[username] where [username] is your user account name. Any files here will be render for example ~/Sites/index.html is accessible from the browser via http://localhost/~[username]/index.html. One note to get this to work. Out of the box, all requests to /Sites result in a Forbidden 403 error. To resolve this issue, modify the conf file specified above as SERVER_CONFIG_FILE (/private/etc/apache2/httpd.conf in my case) from
<Directory />
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Deny from all
</Directory>
to
<Directory />
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Allow from all
</Directory>
Restart apache (sudo apachectl -k restart) and try going to http://localhost/~[username] again.