Tips
These tips are for v4.2.n.
Some other excellent resources are
the Tapestry 5.0 How-To Page,
and the Tapestry User
mailing list
which is archived and searchable at
gmane, and
nabble.
Also, the book Tapestry 5: Building Web Applications by Alexander Kolesnikov,
although it is getting a bit out of date.
EDITING .tml FILES
Any HTML editor will do. In Eclipse, associate .tml files with the HTML editor:
- choose Window > Preferences > General > Editors > File Associations (or in OS X, choose Eclipse > Preferences > General > Editors > File Associations), and
- in File type, add *.tml.
- in Associated Editors, add HTML Editor, Web Page Editor, Web Browser, and Text Editor,
- click OK.
- choose Window > Preferences > General > Content Types (or in OS X, choose Eclipse > Preferences > General > Content Types), and
- in Content types, choose Text > HTML,
- in File associations, add *.tml.
- click OK.
THE DATABASE
JumpStart session beans specify to use a persistence unit called jumpstart.
The persistence.xml file maps jumpstart to 1 or 2 data sources. Their JNDI names are java:/JumpStartDS and java:/JumpStartDSUnmanaged.
By default, OpenEJB overrides the JNDI names to its own which use the Hypersonic database in OpenEJB's data/hsqldb/ directory. This is handy.
To override this behaviour, supply an openejb.xml configuration file. You can see this being done in the integration tests.
When running in JBoss, a jumpstart-ds.xml configuration file maps the JNDI names to a database. The file goes in the server's deploy/ directory.
VIEWING AND EDITING DATA
Hypersonic provides a handy GUI tool for viewing the database and executing SQL requests, the HSQL Database Manager. To use it:
- Set the hsqldb.jar.dir and hsqldb.data.dir properties in the project's data_util.properties file.
- Run the target start-database-manager of build.xml.
- In a few moments the HSQL Database Manager will start up.
- Point your web browser at the JMX console, eg. http://localhost:8080/jmx-console/.
- Click on database=localDB,service=Hypersonic.
- Find the section labelled void startDatabaseManager().
- Click on Invoke.
- In a few moments the HSQL Database Manager will start up. Note that it will start on the machine that JBoss is running.
LOGGING SQL AND HIBERNATE
Logging is configured by log4j.properties in business/src/dev/conf/.
-
log4j.category.org.hibernate.SQL=DEBUG
-
log4j.category.org.hibernate=DEBUG
You will also have to change the logging threshold of the CONSOLE appender from INFO to DEBUG. Alternatively, to avoid cluttering up the console log, create a new appender definition called, say, HIBERNATE, by copying one of the appender definitions called FILE (look for appender name="FILE"). Then define your new category like this:
-
log4j.category.org.hibernate=DEBUG, HIBERNATE
UNIT TESTS
JumpStart has a simple unit test suite in the business tier. Its name is BusinessUnitTestSuite. You can run it as a JUnit Test in Eclipse, or in Ant.
Run with Ant
- Run the Ant target clean-compile-test in the project's build.xml file.
- If you get an error about JAVA_HOME, read this. Use a JDK 1.5 tools.jar.
Run as JUnit Test in Eclipse
- Here are the instructions for unit test in eclipse
DEPLOYMENT SERVERS
JumpStart is usually developed in Eclipse with an in-line Jetty server...
- Jetty 5.1 with HSQLDB.
- Web serving is provided by Jetty.
- Application serving is not provided - so we added OpenEJB.
- Persistence is not provided - so we added Hibernate.
- Database is not provided - so we use OpenEJB's embedded HSQLDB.
- JBoss 4 with HSQLDB or MySQL.
- Web serving is provided by JBoss's embedded Tomcat.
- Application serving is provided by JBoss's embedded EJB3 implementation.
- Persistence is provided by JBoss's embedded Hibernate.
- Database is provided by JBoss's embedded HSQLDB, but you can point the datasource to an existing MySQL DB instead if you wish.
- Glassfish 2.1 with Derby.
- Web serving is provided by Glassfish's embedded Tomcat.
- Application serving is provided by Glassfish's embedded EJB3 implementation.
- Persistence could be handled by Glassfish's embedded TopLink except that JumpStart has a small dependency on Hibernate, so we add Hibernate (see Prepare Glassfish 2.1 for JumpStart).
- Database is provided by Glassfish's embedded Derby.
- Tomcat 5.5 or 6.0 with HSQLDB.
- Web serving is provided by Tomcat.
- Application serving is not provided - so we add OpenEJB (see Prepare Tomcat 5.5.x or 6.0.x for JumpStart).
- Persistence is not provided - so we add Hibernate (see Prepare Tomcat 5.5.x or 6.0.x for JumpStart).
- Database is provided by Tomcat's embedded HSQLDB.
The package has to be a little bit different depending on the type of server we're deploying to.
- EAR or WAR? For JBoss and Glassfish the package is an EAR; for Tomcat the package is a WAR in "collapsed EAR" format.
- The persistence.xml file is chosen from the files in business/src/main/resources/persistence-descriptor/.
- The web.xml file is chosen from the files in web/src/main/java/jumpstart/web/WEB-INF/.
- JNDIServicesLocator.
- BusinessServicesLocator.
- BaseTest.
INTEGRATION TESTS
JumpStart's integration test suite confirms the business layer is operating correctly and reporting all possible exceptions correctly.
Its name is BusinessIntegrationTestSuite.
A good place to start with the integration tests is to run and/or debug them in Eclipse. This uses embedded OpenEJB and an in-memory HSQLDB.
- Here are the instructions for integration test with embedded OpenEJB and an HSQLDB database.
- Here are the instructions for integration test with remote JBoss 4.2 and an HSQLDB or MySQL database.
- Here are the instructions for integration test with remote Glassfish 2.1 and a Derby database.
- Here are the instructions for integration test with remote Tomcat 5.5 or 6.0 and an HSQLDB database.
CREATING A FRESH PROJECT
Choose a project name, root package name, etc., then edit the values in tools/tools.properties .
Run the Ant target create-fresh-project in the tools/tools.xml file.
A new project will have been created with an Index page, Login page, the User and UserPassword entities
and a few pages to maintain them.
Then do much the same as you did from Step 5 onwards of Installation.
ALTERING THE DATABASE SCHEMA
The schema is defined by the classes containing the @Entity annotation.
By default, JumpStart will automatically create/update the database schema
to match. That includes creating tables and constraints when necessary.
This behaviour is controlled by the
hibernate.hbm2ddl.auto
property in persistence.xml.
Unfortunately, you can't just override the behaviour at runtime eg. with some settings in a properties file in the conf/ directory. It seems that either JBoss/Hibernate (or the EJB3 spec?) requires the Hibernate settings to be specified in persistence.xml, and the EJB3 spec requires persistence.xml to be inside the ear file. Hopefully this situation will change soon.
REBUILDING THE DATABASE SCHEMA
Some changes don't seem to propagate to the database schema, for example switching a field from nullable=false to nullable=true.
So at times you may decide to rebuild the schema.
- Backup the data This is optional, but the next step will delete all your data. The initial JumpStart data is re-loadable in step 4.
- Drop the tables Use JumpStart's drop_tables.sql script, or modify it to suit. If your database is JBoss's Hypersonic, use the HSQL Database Manager
- Create the tables Either run the ant target touch-exploded-ear in JumpStart's build.xml, or restart the JBoss server. See Altering the database schema above for details.
- Restore the data or re-load the initial data If you backed up the data in step 1, then you can restore it now. Alternatively, re-load the initial data with JumpStart's initial_data.sql script.
HSQLDB VS. MySQL AND OTHERS
JumpStart has been tested with HSQLDB and MySQL. HSQLDB is very convenient but,
in general, MySQL returns better exception information for JumpStart to work with.
For example, a simple duplicate key situation in HSQLDB can result
in a "failed JDBC batch" and no further information. JumpStart does its best to
cope with this.
To use a database type other than HSQLDB or MySQL you may have to add some logic to the class HibernateExceptionInterpreter in business/src/main/java/jumpstart/business/commons/interpreter/. It's a custom class responsible for interpreting vague exceptions like "constraint violation" into specific JumpStart exceptions. After modifying it, verify it is operating correctly with your database by running the integration tests.
SWITCHING DATABASE PRODUCTS
See the notes above on MySQL vs HSQLDB vs others.
To switch database brands:
- Database driver To work with MySQL first uncomment any references to mysql-connector-java.jar in the project's build.xml files. Then run the target all in the top-level build.xml.
- Data source definition To add a data source definition to JBoss create a new file similar to jumpstart-hsqldb-ds.xml in your exploded/ directory or the server's deploy/ directory or any other directory being scanned by JBoss. See here.
- persistence.xml Modify jumpstart.ear/jumpstart.jar/META-INF/persistence.xml - specify the data source name in the tag jta-data-source (eg. java:/DefaultDS), and specify the database type in the property hibernate.dialect in persistence.xml (jumpstart.ear/jumpstart.jar/META-INF/persistence.xml).
- HibernateExceptionInterpreter.java As discussed above, if you use a database type other than HSQLDB or MySQL then you may need to add some logic to this custom class.
JBOSS STARTUP OPTIONS
Here are some useful startup options to use for running JBoss.
In Windows:
- set JAVA_OPTS=-Dtapestry.production-mode=false -Dtapestry.compress-whitespace=false -XX:MaxNewSize=96m -XX:MaxPermSize=96m -Xms128m -Xmx128m
- run.bat -Djboss.bind.address=0.0.0.0
In tcsh (the default shell in OS X Terminal):
- setenv JAVA_OPTS '-Dtapestry.production-mode=false -Dtapestry.compress-whitespace=false -XX:MaxNewSize=96m -XX:MaxPermSize=96m -Xms128m -Xmx128m -Djava.net.preferIPv4Stack=true'
- run.sh -Djboss.bind.address=0.0.0.0
Their purpose is:
- Production mode: -Dtapestry.production-mode=false tells the Tapestry ExceptionReport page to display full details of the exception, which is great during development. When set to true (which is the default since T5.0.10), Tapestry's ExceptionReport page will display an abbreviated report so as to avoid disclosing details of your application's internals.
- Compress whitespace: -Dtapestry.compress-whitespace=false tells Tapestry not to compress whitespace as it generates a page from a template. Makes the generated page source much easier to read eg. when you tell your browser to display the page source.
- Increase Java heap size: -Xms128m -Xmx128m gives JBoss more memory for its heap, avoiding "out of memory" errors.
- Increase Perm Gen memory: -XX:MaxNewSize=96m -XX:MaxPermSize=96m gives the Tomcat server inside JBoss more Perm Gen memory. If you encounter Perm Gen memory errors as you make mods to the app then consider raising this higher.
- Prefer IPv4: -Djava.net.preferIPv4Stack=true may speed up JBoss startup on some Unixes (clustered AIX?) or other operating systems that have IPv6 enabled by default.
- Enabling remote access:
-Djboss.bind.address=0.0.0.0
is a quick way to enable remote access to JumpStart from another computer.
Starting with JBoss 4.2.0, remote access is turned off by default.
JBoss does this by binding all its services to localhost (127.0.0.1).
A quick way to enable remote access is to bind JBoss to all available network interfaces (0.0.0.0),
which is what JBoss used to do.
Not for JAVA_OPTS: -Dbind.address must be specified as a parameter to run.bat or run.sh and not in JAVA_OPTS because it won't work.
Security risk: Be aware of the security risk of this setting - it exposes various parts of JBoss including the jmx-console to remote access. Depending on your needs you may still need to secure JBoss properly.
Clustering is not affected: the clustering address is specified by a different system property, bind.address, eg. run.sh -Djboss.bind.address=10.10.10.1 -Dbind.address=10.10.10.2 . Not for JAVA_OPTS: Do not try specifying -Djboss.bind.address or -Dbind.address in JAVA_OPTS (see next item) because it won't work. They must be specified as parameters to the run.bat or run.sh.