1. Rails
  2. Grails
  3. Trails
  4. AppFuse
  5. Django
  6. Seaside

What I’d like to try:

  • Install the tool and any supporting infrastructure
  • Generate/create a CRUD phone book app (name, street, city, state, zip, phone)
  • Start and run the app
  • Add an email field
  • See it show up in the app

Summary (from the experiences below):

  1. Rails is easy to spark a simple app to life, owing in part to InstantRails.
  2. Grails is easy to spark to life a simple app, but it takes more grunt work.
  3. Java EE (Trails and AppFuse) is harder and more work than Rails/Grails/Django.
  4. Django is easy to spark a simple app to life.  It doesn’t appear to have anything comparable to Rails migrations, but its CRUD starter-app has more functionality than Rails.
  5. Seaside is elegant. So is Smalltalk.  I need more syntactic sugar. I can get past unusual if-statements, but I’m not going to use (word) messages for array subscripting.


  1. The Ruby + Rails guys really understand packaging and reduction of barriers to entry, in addition to the oft-cited promotion.
  2. InstantGrails and InstantDjango would enable more developers to quickly become more familiar with these frameworks.
  3. Even the easy starter tools for Java EE frameworks take too much effort to attract developers from small ASP or PHP shops.
  4. I started off expecting Rails to be a clear winner.  I was impressed by Django.

<hr /><p> Rails (May 4, 2007)</p><ol><li>Download http://rubyforge.org/frs/download.php/18843/InstantRails-1.7-win.zip</li><li>Unzip into C:</li><li>Run: C:\InstantRails\InstantRails.exe</li><li>Add C:\InstantRails\mysql\bin;C:\InstantRails\ruby\bin to PATH</li><li>mysql -u root <ul><li>create database addressbook_development;</li><li>quit;</li></ul></li><li>Run: rails addressbook</li><li>cd addressbook</li><li>Run: ruby script\generate model Address</li><li>Run: ruby script\generate controller Address</li><li>Add “scaffold :address” to C:\addressbook\app\controllers\address_controller.rb</li><li>Edit C:\addressbook\db\migrate\001_create_addresses.rb adding this Ruby code to the create_table bvlock</li><li>Run: rake db:migrate</li><li>Run: ruby script/server</li><li>Browse to http://localhost:3000/address/list and test the CRUD</li><li>Run: ruby script/generate migration add_email_field</li><li>Edit C:\addressbook\db\migrate\002_add_email_field.rb , adding “add_column :addresses, :email, :string, :limit => 80” to self.up and “remove_column :addresses, :email” to self.down</li><li>Run rake db:migrate</li><li>Browse to http://localhost:3000/address/list and test the CRUD</li></ol><p>Note: It appears to me that Rails development activities can all be run as a ‘portable app’ from a flash drive.</p><p><hr /></p><p>Grails (May 6, 2007)</p><ol><li>Download http://build.canoo.com/grails/artifacts/grails-bin-0.5.5-SNAPSHOT.zip</li><li>Unzip to C:\ and rename grails-0.5 to grails</li><li>Download JDK 6u1 from http://java.sun.com/javase/downloads/index.jsp</li><li>Run the JDK install</li><li>Add environment variable GRAILS_HOME=C:\grails</li><li>Add “C:\grails\bin;C:\ant\bin” to PATH</li><li>Download Ant 1.7 from http://ant.apache.org/bindownload.cgi</li><li>Extract Ant to C:\ and rename to C:\ant.  [Note: If there is an InstantGrails that is comparable to InstantRails, somebody please tell me.]</li><li>Add environment variable ANT_HOME=C:\ant</li><li>Set environment variable JAVA_HOME to C:\Program Files\java\jdk1.6.0_01</li><li>Open a Command prompt in C:\ and run “grails” and you get a message that you can use “grails help” for help.  Try it.  Get “Error executing script Help: String index out of range: 1” and a Java runtime exception.  Great.</li><li>Run “grails create-app”.  Oops. That throws the same error.</li><li>On a whim, “mkdir grails_apps” and “cd grails_apps”</li><li>Run “grails create-app addressbook”. Bingo!  I’m guessing that the grails developers aren’t big on Windows, or perhaps they have a philosophical  objection to letting me create an app directory at the root level. I’m betting that they can’t be bothered to deal with a current directory ending with a backslash.</li><li>cd addressbook</li><li>grails create-domain-class Address</li><li>Edit C:\grails_apps\addressbook\grails-app\domain\Address.groovy and add this Groovy code inside the class</li><li>Run “grails create-controller Address”</li><li>Edit C:\grails_apps\addressbook\grails-app\controllers\AddressController.java and replace “def index = {}” with “def scaffold = Address”</li><li>Run grails run-app</li><li>Browse to http://localhost:8080/addressbook/address and test the CRUD <ol><li>How odd!  It sequences the columns as Zip, Phone, Street, Name, State, City. It is neither the order I defined them nor alphabetic, or any other sequence I can discern.</li></ol></li><li>Edit  C:\grails_apps\addressbook\grails-app\domain\Address.groovy and add “String email”</li><li>Stop and restart the app (may not be necessary). <ol><li>Oops! We lost all the old data.  Oh. That’s right, it uses an in-memory database by default.</li></ol></li><li>Download and install MySQL “Windows Essentials” from http://dev.mysql.com/downloads/mysql/5.0.html#win32</li><li>mysql -u root <ul><li>create database addressbook_development;</li><li>quit;</li></ul></li><li>Edit C:\grails_apps\addressbook\grails-app\conf\DevelopmentDataSource.groovy and make it look like this Groovy code:</li><li>Download the MySQL JDBC driver from http://www.mysql.com/products/connector/j/</li><li>Extract mysql-connector-java-5.0.5-bin.jar to C:\grails_apps\addressbook\lib</li><li>Stop and restart the app (necessary).</li></ol><p>Note: It appears to me that grails development activities can NOT be run as a ‘portable app’ from a flash drive.  Also, I didn’t find evidence of anything like Rails’ migrations.  Yes, Grails can automatically alter your database structure to match your domain model, but if you need to do anything more than add/drop database entities, you’ll have to write and sequence your updates, and you’ll own repeating the process against your production database.</p><hr /><p> Trails (May 7, 2007)</p><ol><li>Download JDK 6u1 from http://java.sun.com/javase/downloads/index.jsp</li><li>Run the JDK install</li><li>Add “C:\ant\bin” to PATH</li><li>Download Ant 1.7 from http://ant.apache.org/bindownload.cgi</li><li>Extract Ant to C:\ and rename to C:\ant.  [Note: If there is an InstantTrails that is comparable to InstantRails, somebody please tell me.]</li><li>Add environment variable ANT_HOME=C:\ant</li><li>Set environment variable JAVA_HOME to C:\Program Files\java\jdk1.6.0_01</li><li>Download Maven from http://maven.apache.org/download.html</li><li>Extract Maven to C:\ and rename it to c:\maven</li><li>Add c:\maven\bin to your PATH.</li><li>Download http://www.reverse.net/pub/apache/tomcat/tomcat-6/v6.0.10/bin/apache-tomcat-6.0.10.exe</li><li>Install the downloaded Tomcat</li><li>mvn archetype:create -DarchetypeGroupId=org.trailsframework -DarchetypeArtifactId=trails-archetype -DremoteRepositories=http://snapshots.repository.codehaus.org -DarchetypeVersion=1.0-SNAPSHOT -DgroupId=addressbook -DartifactId=addressbook</li><li>cd addressbook</li><li>mvn tomcat:run</li><li>Error message: <ol><li>Reason: POM 'org.codehaus.mojo:tomcat-maven-plugin' not found in repository: Unable to download the artifact from any rep repository    org.codehaus.mojo:tomcat-maven-plugin:pom:1.0-SNAPSHOT</li><li>Note: This is based on the instructions at http://www.trailsframework.org/Quick+Start at 9:58 PM (Eastern Daylight Time) on May 6, 2007.  It says they just changed things around a lot, so it looks to me like they haven’t finished with their changes.  Maybe I’ll try again another day.</li></ol></li></ol><p>Trying to work around the problem:</p><ol><li>Create folder C:\maven\repository</li><li>Edit c:\maven\conf\settings.xml and point localRepository to C:/maven/repository. Also define ibiblio as a mirror.</li><li>Fiddle with settings.xml until the following works: <ul><li>mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeVersion=1.0</li><li>Note: See http://repo1.maven.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart</li><li>Somewhere in there I added ibiblio as a mirror (in the maven settings.xml)</li><li>mvn archetype:create -DarchetypeGroupId=org.trailsframework -DarchetypeArtifactId=trails-archetype -DremoteRepositories=http://snapshots.repository.codehaus.org -DarchetypeVersion=1.0-SNAPSHOT -DgroupId=com.kleinfelter.demo1 -DartifactId=addressbook</li><li>Edit c:\code\addressbook\pom.xml and change the version on tomcat-maven-plugin to “1.0-alpha-1”</li><li>Note: I found the version from http://repository.codehaus.org/org/codehaus/mojo/tomcat-maven-plugin</li></ul></li><li>Add this XML to your project’s pom.xml, just before the “<build>” line.</li><li>Add a repository to pom.xml for tapernate at http://www.carmanconsulting.com/mvn/</li><li>Download tapestry-spring-1.0.0 from http://howardlewisship.com/downloads/tapestry-javaforge/</li><li>Install tapestry-spring via: mvn install:install-file -DgroupId=com.javaforge.tapestry -DartifactId=tapestry-spring -Dversion=1.0.0 -Dpackaging=jar -Dfile=tapestry-spring-1.0.0.jar</li><li>mvn tomcat:run</li><li>Boom! It starts tomcat, but when I browse to http://localhost:8080/, it dies with <ul><li>javax.servlet.ServletException: Unable to construct service tapernate.MergeReattachPropertyPersistenceStrategy: Unable to construct service hivemind…</li></ul></li></ol><p>I’m sure this all works for someone, but this is hardly making development easy.  I can see why the Grails team is proud of its work; by comparison, it is far better than this.</p><p><hr /> </p>AppFuse with Candy (May 17, 2007) <ol><li>Download and install Java EE 5 SDK Update 2 from http://java.sun.com/javaee/downloads/index.jsp
 Tell it not to start (not sure how I did this; may have disabled the Service)</li><li>Download Eclipse SDK 3.2.2 from http://www.eclipse.org/downloads/ and extract to C:</li><li>Add jdk\bin to your PATH</li><li>Download and install Windows Essentials from http://dev.mysql.com/downloads/mysql/5.0.html#downloads.  Install to C:\MySQL
 Data files in C:\mysql-databases
 Root password = password</li><li>Start Eclipse, set C:\Code as your default workspace, add
 http://commonclipse.sourceforge.net.as an update site, run update, select all available except Eclipse 3.2.1 patches</li><li>Window/Preferences/Java/Commonclipse. Select the General tab. Uncheck Append super in hashCode() and Append super in equals(). Click OK. </li><li> Window/Show View/Console</li><li>In the Package Explorer pane (left side), right-click and
  New/Project/New AppFuse project, name it HelloAppFuse, Struts 2 Basic, group =com.kleinfelter</li><li>Wait. Wait some more.</li><li>Edit pom.xml, and set jdbc.password to password</li><li>Right-click the project in Package Explorer/Run As/Maven Build… (the one with …) <ul><li>In the "Goals:" text box, enter jetty:run-war</li><li>Click Run</li></ul></li><li>Browse to http://localhost:8080/</li><li>Save this code as C:\code\HelloAppFuse\src\main\java\com\kleinfelter\model\Address.java (upper-case A)</li><li>Right-click the source code, and select Generate Getters and Setters</li><li>Select Address.java in Package Explorer, right-click/Source/"Generate hashCode() and equals()" and DE-select id.</li><li>Right-click the source/Commonclipse/"Generate toString()"</li><li>Edit src/main/resources/hibernate.cfg.xml for the basic archetypes and add after the other mapping rows: <ul><li><mapping class="com.kleinfelter.model.Address"/></li></ul></li><li>Create src/main/webapp/WEB-INF/applicationContext.xml containing this code</li><li>Create C:\code\HelloAppFuse\src\main\java\com\kleinfelter\webapp\action<a href=”/files/addressAction.java” title=”address action class”>AddressAction.java  containing this code</a></li><li>Create a src/main/webapp/WEB-INF/pages/addressList.jsp containing this code</li><li>Edit src/main/resources/struts.xml and append this code after the row with "<!– Add additional actions here –>":</li><li>Edit src/main/resources/ApplicationResources.properties and append these properties</li><li>Create a src/main/webapp/WEB-INF/pages/addressForm.jsp containing this code</li><li>Browse to http://localhost:8080/addresses.html (login is mraible/tomcat)</li><li>I still need to add the email field… This one has worn me out!</li></ol><hr /><p>Django</p><ol><li>Install Python 2.5.1 from http://www.python.org/download/</li><li>Download Django 0.96 from http://www.djangoproject.com/download/ , extract it into a temp directory, cd to the directory, run python setup.py install <ul><li>Make sure your PATH includes C:\python;C:\Python\Lib\site-packages\django\bin</li></ul></li><li>Download and install MySQL “Windows Essentials” from http://dev.mysql.com/downloads/mysql/5.0.html#win32 . Check your my.ini to verify that “default-storage-engine=INNODB” is in the “[mysqld]” section.</li><li>mysql -u root <ul><li>CREATE DATABASE addressbook_development CHARACTER SET utf8;</li><li>quit;</li></ul></li><li>Download and run mysql for python (win32 exe edition) from http://sourceforge.net/project/showfiles.php?group_id=22307</li><li>“cd c:\code” and run “django-admin.py startproject addressbook”</li><li>“cd addressbook” and run “python manage.py startapp address”</li><li>Edit settings.py and make it resemble this code</li><li>Edit addressbook/address/models.py to contain this</li><li>Add to INSTALLED_APPS in addressbook/settings.py: ‘addressbook.address’ and ‘django.contrib.admin</li><li>Edit your mysite/urls.py file and uncomment the line below “Uncomment this for admin:”.</li><li>python manage.py syncdb <ul><li>Admin user=admin, password=password</li></ul></li><li>python manage.py runserver</li><li>Browse to http://localhost:8000/admin/</li><li>Test out the CRUD <ul><li>Hey! It enforces the length=2 on state!</li><li>The basic CRUD is pretty nice, with admin login, shortcuts, history.</li></ul></li><li>Edit addressbook/address/models.py and add: ‘    email = models.CharField(maxlength=80)’</li><li>I’d like to see “python manage.py syncdb” add the new column, but it doesn’t.  You have two choices: either write and run your own SQL script to do so (‘alter table address_address add column email char(80);’) or you could: <ul><li>python manage.py dumpdata address > temp.json</li><li>python manage.py reset address</li><li>python manage.py loaddata temp.json</li></ul></li><li>Test CRUD with the new field.</li></ol><p><hr /> </p> <p>Seaside</p><p>This exercise is not really Seaside’s forte.  Smalltalkers aren’t really into relational databases, preferring object databases </p><ol><li>Download http://wwwmaster.postgresql.org/download/mirrors-ftp?file=%2Fbinary%2Fv8.2.4%2Fwin32%2Fpostgresql-8.2.4-1.zip</li><li>Create your database (“addressbook-development”) via PostgreSQL’s GUI tools.</li><li>Go into pg_hba.conf and change the authentication method from md5 to password</li><li>Download and install Seaside 2.7 via Squeak’s “world menu”/open/squeakmap, navigate to Seaside 2.7, right-click, and install. <ol><li>Tell it Debug and then Proceed on the redefining Cache error.</li><li>Config user=admin/password</li></ol></li><li>Download and install Postgress Client 1.0 via Squeak’s “world menu”/open/squeakmap, navigate to PostgresSQL Client, right-click, and install. <ol><li>Windows Service Account = kevin on local machine domain</li><li>DB user = admin/password</li></ol></li><li>Download and install Glorp 0.3.138 via Squeak’s “world menu”/open/squeakmap, navigate to Glorp port, right-click, and install.</li><li>After you load Glorp, edit PGConnection class>>buildDefaultConnectionArgs and point it to your postgres server and database.</li><li>Evaluate (“do it”) “WAKom startOn: 9090” in a Squeak workspace window, and browse to http://localhost:9090/seaside/config <ol><li>Add “addressbook” as an application.</li></ol></li></ol><p>I'm unlikely to finish this one. There is too much construction required.  For starters, if I want it to work with MySQL, I'll have to write the database driver.  You get your choice of databases, so long as your choice is PostgreSQL.</p><p>Seaside is elegant. So is Smalltalk.  I need more syntactic sugar. I can get past unusual if-statements, but I’m not going to use (word) messages for array subscripting. I like minimalism in theory; in practice, I really like common array subscripting, whether via [] or () or even (. and .) (which I used for Pascal on the DEC-10).  I like the convenience if-modifiers and the unless-statement.  I don’t need them.  I like them.  I think in English.  I think that if I were a mathematician I might like Smalltalk better.  I like its concepts, but I don’t like practicing with those concepts.</p><p>Note: http://www.squeaksource.com/MagritteGlorp.html might be interesting for a follow-up test.</p>