Appendix A. Frequently Asked Questions

This section contains a few Q's and A's gleemed from the Tapestry forums at SourceForge.

Q: java.lang.NoSuchMethodError gets thrown when I attempt to use Tapestry with Tomcat. How do I fix this?
Q: Can Tapestry be used to create a Portal application?
Q: One more time. What's this business about rewinding things for forms?
Q: How do I specify the CSS class used for a Tapestry component?
Q: I get the StaleSession page when I submit a form on my home page. Why?
Q: What happended to the ILifecycle interface?

Q: java.lang.NoSuchMethodError gets thrown when I attempt to use Tapestry with Tomcat. How do I fix this?

A: Tomcat ships with version 1.0 of the JAXP (Java API for XML Processing) framework. Tapestry is coded against version 1.1. You must replace the jaxp.jar in Tomcat with the javax.xml.jaxp.jar from Tapestry. Simply delete the old file and copy the new one into the Tomcat distribution.

In addition you must replace parser.jar (which contains an XML parser) with org.apache.crimson.jar, Sun's default XML parser.

Q:Can Tapestry be used to create a Portal application?

A: Of course it can!

This question came up pretty frequently on the SourceForge forum, so I put together a mini-portal application as one of the tutorials. This sounded out some limitations in the framework: the Porlet component dynamically combines components from multiple pages (using the Block and InsertBlock components).

Q: One more time. What's this business about rewinding things for forms?

A: This is one of the big stumbling blocks for some users of Tapestry. The way Tapestry deals with forms is very complex, with a reason: it allows for incredibly dynamic pages.

In tradional web applilcations, the developer is responsible for naming each form element, as well as writing a servlet to handle the request cycle when the form is submitted. That turns into a lot of code to extract name parameters from the HttpServletRequest, convert them from Strings to other datatypes, and push the values into appropriate business objects.

This works fine as far as it goes ... but the developer has an advantage that the Tapestry framework doesn't have: the exact name, type and number of form elements is known during development.

By contrast, Tapestry has to figure this all out on the fly. In addition, Tapestry forms can wrap around Foreach components ... that means the same TextField component may be responsible for updating a property of a whole slew of objects. On top of that, the use of Conditional, Block and InsertBlock components mean that the exact set of components involved may be determined dynamically.

Note

An example of this is the Tapestry Inspector Logging View. A single PropertySelection is wrapped by a ListEdit which iterates throught a list of the possible categories.

Categories may be added at any time (in fact, that's another function of the page).

Now, it's natural to envision Tapestry dynamically walking through its components and HTML templates to render the form seen in the user's web browser. The mental leap required is that the initial renderring process has to be run again in order to figure out which components are involved in processing the submission, and how. That's the rewind phase.

Just as with the initial render, Tapestry must work through just the right set of components, in just the right order, taking into account Conditional and Foreach components. You must also factor in that Tapestry is assigning the names used for the HTML form elements, which must also be "rediscovered" so that the right HTTP parameter can be combined with the correct component and assigned to the appropriate business object property.

Sure, this is overkill when you have a simple form to enter the user's name. But doesn't it give you a warm feeling to know that when you do create your killer dynamic form, the very same code you've come to know and trust will be waiting to handle it, just as easily?

Q: How do I specify the CSS class used for a Tapestry component?

A: Most Tapestry components support informal parameters. These are used to specify additional HTML attributes for the tag generated by the component.

You can set the value for such informal parameters in the component specification, or in the HTML template.

Q: I get the StaleSession page when I submit a form on my home page. Why?

A: Tapestry applications run in a stateless mode initially. That is, they don't create a HttpSession. This continues until the application has some specific server-side state, at which point the HttpSession is created.

By default, Forms (as well as Actions) are stateful; they require that an active HttpSession exists. If there isn't an active session, they throw a StaleSessionException. However, you can bind the stateful parameter of these components to Boolean.FALSE to remove this check.

This check makes sense once there's server side state; it detects when an HttpSession has expired from lack of use. It's better than seeing an anomolous NullPointerException, which is quite likely when all state is lost.

Q:What happended to the ILifecycle interface?

A: Prior to release 1.0.5, there was an interface, ILifecycle, that could optionally be implemented by components so that they could be informed about the lifecycle of the page which contains them, especially knowing when the page was detached from the engine (so that the components could reset thier state accordingly).

By release 1.0.5, this has become somewhat awkward. Firstly, several non-component objects needed similar notification and there wasn't a way to cleanly accomplish this. Secondly, a finer grained approach was desired, as different objects had different notification requirements.

For release 1.05, the interface was replaced by a more standard approach; well defined JavaBeans events. These are described in the Page Events section of this document.

The ILifecycle interface will be completely removed in release 1.1.0. In the meantime, its deprecated, which will generate some warnings in your code if you create classes which implement the interface.