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):
- Rails is easy to spark a simple app to life, owing in part to InstantRails.
- Grails is easy to spark to life a simple app, but it takes more grunt work.
- Java EE (Trails and AppFuse) is harder and more work than Rails/Grails/Django.
- 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.
- 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.
Conclusions:
- The Ruby + Rails guys really understand packaging and reduction of barriers to entry, in addition to the oft-cited promotion.
- InstantGrails and InstantDjango would enable more developers to quickly become more familiar with these frameworks.
- Even the easy starter tools for Java EE frameworks take too much effort to attract developers from small ASP or PHP shops.
- 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
User=admin/password
admin-port=4848
HTTP-port=9090
HTTPS-port=9191
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
Transactional
Data files in C:\mysql-databases
Root password = password</li><li>Start Eclipse, set C:\Code as your default workspace, add
http://candy4appfuse.sf.net/site
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>