PermaLink AppFuse w/ PostgreSQL and Tapestry01/25/2005

In my continuing search for a nice wizard to set up a skeletal J2EE app a la MS Studio's "projects", I decided to try Matt Raible's AppFuse.  It's painless if you use Matt's preferred development environment (Tomcat/MySQL/Struts/Hibernate/Spring).  Once you start veering off the beaten path...
Some quick notes that probably should be included in the Quickstart for Appfuse in case you want to use a different database:
- in the lib directory, there is a file that points to all the database types and their jar files.  The file actually points to all the different jar files that AppFuse uses.  It's a nice directory structure in the lib subdirectory since each version of a jar is in a different subdirectory; you can use this to test out different versions of various jar files in your application w/o committing to it.  The negative is that when the .war file is generated via AppFuse, *all* the jar files in the lib directory are included in the WEB-INF/lib directory, though I'm sure this should be an easy workaround by modifying the build.xml to only include jar files your project actually uses
- in the file, be sure to update the following items if you want to use a non-MySQL database:
- this set of settings only has to be set if you are using MySQL because it's the only database that lets you create databases using JDBC:
- when installing tomcat, set the password for the admin user to admin; if you use a different password, remember to change the file
- don't change; despite the name, this file is generated by build.xml

- make sure you do a recursive search on "appfuse" to make sure the appgen/rename process got everything

Of course, I just *had* to go try to use HypersonicSQL since I just wanted a simple test application and didn't need a high powered database for a test application.  Hibernate doesn't work that well w/ HypersonicSQL.  Hibernate generates table names w/o quotes (which HypersonicSQL for some reason then decides to uppercase), then it generates SQL statements naming the tables using quotes and the table names are in lowercase so HypersonicSQL can't find the table :-P

The next database I tried was PostgreSQL since PostgresSQL 8.0 had just come out so I was hoping it'd fix some of the quirks mentioned in the AppFuse Wiki.  Sadly, you still can't create a database via JDBC.  Automatically creating a database is one nice thing an EJB container can do which Hibernate can't do.  On Matt's Wiki, he mentions that you have to change the Hibernate generator-class to "increment" instead of "native" or the dbunit tests fail; this is disappointing since PostgreSQL is more SQL compliant than MySQL, but luckily this is in all the AppFuse code already.

After switching to PostgreSQL, some of the unit test emit weird errors like this but all the tests pass:
uh oh, user 'badusername' not found...
ERROR: duplicate key violates unique constraint "app_user_pkey"

Other useful ant commands:
ant db-create - creates a database using JDBC (quick way to find out if your JDBC drivers are in the right place)
ant db-prep - generates the DDL for your database into the file
ant setup-tomcat - sets up tomcat by copying the transaction manager and the JDBC driver over to the right place and copying the application's configuration xml file over to tomcat
ant test-all - runs all unit tests

I do wish the build.xml were broken down into more pieces so you can concentrate on the pieces you have to use.  It currently has a bunch of targets for testing, packaging up the original AppFuse distribution, creating documentation, hooking into Tomcat, substituting in various web frameworks (Tapestry, Spring, etc.), Wiki gathering, etc.  The testing targets can probably be moved into the test subdirectory.  The Tomcat specific targets can be moved into a separate tomcat.xml file so people can contribute version for other containers like JBoss, Geronimo, etc.

Also, some of the files should be put into a conf directory to indicate that they should be modified or at least reviewed.  E.g.,,, app-settings.xml.  Files that are imported or used by build.xml directly (e.g., compile-jsp.xml, properties.xml) should go into another subdirectory so that they don't clutter the top level directory.

Next up is trying to switch web UI frameworks.  If you switch to Tapestry or one of the other UI layer other than the default of struts, be aware that the rename utility on the AppFuse site that lets you change all the "org.appfuse" packages to something else may not get all the files.  In the Tapestry case, the web/web-inf/tapestry.application file didn't get the rename done to it so you have to do the rename by hand or Tomcat will complain that "org.appfuse.webapp.action.BaseEngine" couldn't be found.  Also, all the *.page files in the web/pages/ directory have references to "org.appfuse" that have to be changed to your own package; this should be pretty obvious because Tapestry will point you to the pages that it can't find classes on instead of displaying the typical Java exception stack

I'm not sure if it can be done, but what would be nice is if there were separate build.xml files for each of the different frameworks that Matt integrated so all the war files can be built at once or separately w/o running the "install-tapestry" target from the top level of your application; that way, testing of all the frameworks can be integrated as well as allow an easy way for you to build versions of your applications for multiple frameworks at once to do your own comparisons.

After all that, I finally got the web application to show up at the url: http://localhost:8080/mytestapp

and found my first bug.  If you add a user (either as admin or by signing up) w/ a duplicate username or email address, you get a SQL exception dump instead of a nice error message, which again makes me wonder if people use PostgreSQL w/ Hibernate because this cryptic error that it prints out should probably be fixed in the Hibernate plugin for PostgreSQL (why isn't it calling getNextException and dumping that instead?):

ERROR [http-8080-Processor23] JDBCExceptionReporter.logExceptions(58) | Batch entry 0 insert into user_role (username, role_name) values (user4, tomcat) was aborted.  Call getNextException to see the cause.

The fix in the AppFuse Wiki is to disable Hibernate's batch processing so you can see the errors which doesn't seem like the right thing to do because your app may have SQL exceptions in the field (if it escapes testing) and you'd like to get the real exception message :-P

Comments :v
No comments.
Start Pages
RSS News Feed RSS Comments Feed CoComment Integrated
The BlogRoll
June 2024
Contact Me
About Ken
Full-stack developer (consultant) working with .Net, Java, Android, Javascript (jQuery, Meteor.js, AngularJS), Lotus Domino