Tips
These tips are for v3.14 to v3.20.
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.
Startup Options.
During development, 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.
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.
Live web class reloading. Tapestry 5 automatically does live reloading of template files as you modify them. To enable live reloading of Java classes too (this only applies to the web-tier classes), modify the Tomcat config: Locate the server's deploy/jboss-web.deployer/context.xml eg. jboss-4.2.2.GA/server/default/deploy/jboss-web.deployer/context.xml. Edit it, replacing this:
-
<Context cookies="true" crossContext="true">
-
<Context cookies="true" crossContext="true" reloadable="true">
After each modification, the reloading may be delayed a couple of seconds. If you're too quick to use the page you might get a HTTP Status 404 error (page not found), but if you hit the browser Reload/Refresh button a second or two later you will usually succeed.
Caution: Do not make this change in production. The application will slow as you make more and more changes but this is often a worthwhile trade-off during development. Eventually the JVM may run out of memory - you may have to combat this by increasing the Perm Gen memory and heap size. The reason for this is explained in PermGen space . The way to increase it is described below in other startup options.
For more information, see Live Class and Template Reloading.
Reload the entire app without restarting. To make JBoss reload the entire application (ie. the whole EAR) there is no need to restart JBoss or even to copy any files around. Instead, just run the Ant target touch-exploded-ear in JumpStart's build.xml file. On Unix-based systems you could alternatively do it from the command line with touch exploded/jumpstart.ear/META-INF/application.xml. JBoss will detect the change in a couple of seconds and hot deploy the whole app. You can see it happening in the log.
Business Tests. JumpStart includes an automated suite of tests to confirm the business layer is operating correctly and reporting all possible exceptions correctly. The test suite is found at business/src/test/java/jumpstart/business/BusinessTestSuite.
To run the business tests, first make sure JumpStart is running in JBoss, then either
- run them interactively (right-click on BusinessTestSuite and choose Run As > JUnit Test); or
- run the Ant task test-business in the build.xml file
Problems? Eclipse might not be ready for junit - see Could not create task or type of type: junit.
Logging SQL and Hibernate. To log SQL statements, modify the JBoss server's conf/jboss-log4j.xml to include
-
<category name="org.hibernate.SQL">
<priority value="DEBUG"/>
</category>
Alternatively, to log everything Hibernate's doing, including SQL statements, schema export, transactions, etc., try
-
<category name="org.hibernate">
<priority value="DEBUG"/>
</category>
For finer control of Hibernate logging, see the section on Logging here.
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:
-
<category name="org.hibernate">
<priority value="DEBUG"/>
<appender-ref ref="HIBERNATE"/>
</category>
The new log will appear in the server's log/ directory when the first entry is written to it.
Debugging and single-stepping. To single-step through the code you'll need to be running JBoss in debug mode. There are a couple of ways to do it:
- Start JBoss in debug mode
We'll use port 8787 in this explanation, but it's OK to use any free port.
Earlier, we described setting JAVA_OPTS to get various startup options. To run JBoss in debug, include this in the JAVA_OPTS:
-
-Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y
So if, for example, you also wanted the options described earlier, you'd set JAVA_OPTS to:
-
-XX:MaxNewSize=96m -XX:MaxPermSize=96m -Xms128m -Xmx128m -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y
In Windows, another way to turn on debug is to locate the run.bat file in the JBoss bin/ directory and edit it, removing the rem from the line that reads:
-
rem set JAVA_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y %JAVA_OPTS%
-
Listening for transport dt_socket at address: 8787
In Eclipse, right-click on your project and choose Debug As > Debug... and the Debug window will appear.
- Right-click on Remote Java Application and choose New.
- Set the Port to 8787.
- Enable Allow termination of remote VM.
- Click on Debug.
JBoss will now resume startup, and in Eclipse you can now set breakpoints on any Java in the project - web and business.
- Use JBossIDE plug-in for Eclipse
This plug-in lets you control a JBoss server directly from Eclipse. It is available via Eclipse's update facility (Help > Software Updates > Find and Install...). The update site is http://download.jboss.org/jbosside/updates/stable . (OS X users check here.)
When configuring a server in JBossIDE, you can set system properties in the section called VM arguments. To use the settings described earlier, you'd put this into the VM arguments:
-
-XX:MaxNewSize=96m -XX:MaxPermSize=96m -Xms128m -Xmx128m
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 3 onwards of Installation.
Default database. By default, JumpStart uses the data source whose JNDI name is DefaultDS and JBoss has DefaultDS configured to be a Hypersonic SQL database. See hsqldb-ds.xml in your server's deploy/ directory.
Creating/updating 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 (jumpstart.ear/jumpstart.jar/META-INF/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 and schema. Some changes, like switching a field from nullable=false to nullable=true, don't seem to propagate to the database schema, 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 Creating/updating 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.
Hypersonic Database Manager. JumpStart's default database type is JBoss's Hypersonic. A handy way to open the Hypersonic Database Manager is by pointing your web browser at http://localhost:8080/jmx-console/, click on database=localDB,service=Hypersonic, find the section labelled void startDatabaseManager() and click on Invoke. In a few moments a Java GUI called HSQL Database Manager will start up.
Using MySQL vs HSQLDB vs 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 MySQL or HSQLDB you may have to add some logic to the class JBossExceptionInterpreter.java 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 business tests.
Switching database brands. See the notes above on MySQL vs HSQLDB vs others. To switch database brands:
- Database driver You won't need to do anything to work with HSQLDB or MySQL because JBoss provides the HSQLDB driver and JumpStart includes the MySQL driver (mysql-connector-java.jar).
- Data source definition To add a data source definition to JBoss create a new file similar to 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).
- JBossExceptionInterpreter.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.
Packaging an EAR. Run the Ant target all in the build.xml file, then refresh the project. It creates a jumpstart.ear in enterprise/target/package/ which you can then deploy by dropping into any JBoss deploy/ directory.
No JBoss.
A couple of alternatives to consider:
(1) No app server - just the lightweight
JBoss Embeddable EJB 3.0 container.
It strays from the final EJB3 API in a couple of places (JBoss has work to do)
so you would have to temporarily modify JumpStart in a couple of places.
Verify the mods with the business tests.
(2) JBoss MC (MicroContainer). This looks set to replace the Embeddable container above,
with work on it having resumed in mid-2007, but I have not seen release dates.
(3) A different EJB3 app server, eg.
GlassFish.
In theory this would this would be possible
with just 4 modifications:
- JBossExceptionInterpreter.java - create a new class like it - for example, GlassFishExceptionInterpreter. JBossExceptionInterpreter is tailored to interpreting the JBoss/Hibernate exceptions that bleed out of the persistence layer. It's a class that we shouldn't need, but it seems the EJB3 spec didn't identify and standardise all possible persistence exceptions so vendor-specific exceptions bleed out. Will this be fixed in EJB 3.1???
- BaseSvc.java - simple change - replace its JBossExceptionInterpreter references (see above).
- SessionLayerExceptionInterpreter.java - simple change - replace its JBossExceptionInterpreter references (see above).
- Persistence.xml - simple change - modify a few lines that are in there for Hibernate's benefit. JBoss uses Hibernate for EJB3 Persistence but other app servers might not, eg. GlassFish, uses TopLink Essentials. Hopefully EJB 3.1 will move this bit of config to somewhere outside the EAR.