You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 9 Next »

Templating and Markup

Why do I get a SAXParseException when I use an HTML entity, such as   in my template?

Tapestry uses a standard SAX parser to read your templates. This means that your templates must be well formed: open and close tags must balance, attribute values must be quoted, and entities must be declared. The easiest way to accomplish this is to add a DOCTYPE to your the top of your template:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

Part of the DOCTYPE is the declaration of entities such as &nbsp;.

Alternately, you can simply use the numeric version: &#160; This is the exact same character and will render identically in the browser.

Why do some images in my page show up as broken links?

You have to be careful when using relative URLs inside page templates; the base URL may not always be what you expect. For example, inside your ViewUser.tml file, you may have:

  <img class="icon" src="icons/admin.png"/>${user.name} has Administrative access

This makes sense; ViewUser.tml is in the web context, as is the icons folder. The default URL for this page will be /viewuser 1

However, most likely, the ViewUser page has a page activation context to identify which user is to be displayed:

public class ViewUser

  @Property
  @PageActivationContext
  private User user;

  . . .

With a page activation context, the URL for the page will incorporate the id of the User object, something like /viewuser/37371. This is why the relative URLs to the admin.png image is broken: the base path is relative to the page's URL, not to the page template 2 .

One solution would be to predict what the page URL will be, and adjust the path for that:

  <img class="icon" src="../icons/admin.png"/>${user.name} has Administrative access

But this has its own problems; the page activation context may vary in length at different times, or the template in question may be a component used across many different pages, making it difficult to predict what the correct relative URL would be.

The best solution for this situation, one that will be sure to work in all pages and all components, is to make use of the context: binding prefix:

  <img class="icon" src="${context:icons/admin.png}"/>${user.name} has Administrative access

The src attribute of the <img> tag will now be bound to a dynamically computed value: the location of the image file relative to the
web application context. This is especially important for components that may be used on different pages.

What's the difference between id and t:id?

You might occasionally see something like the following in a template:

<t:zone id="status" t:id="statusZone">

Why two ids? Why are they different?

The t:id attribute is the Tapestry component id. This id is unique within its immediate container. This is the id you might use
to inject the component into your page class:

  @InjectComponent
  private Zone statusZone;

The other id is the client id, a unique id for the rendered element within the client-side DOM. JavaScript that needs to access the element uses this id. For example:

  $('status').hide();

In many components, the id attribute is an informal parameter; a value from the template that is blindly echoed into the output document. In other cases, the component itself has an id attribute. Often, in the latter case, the Tapestry component id is the default value for the client id.

Why do my images and stylesheets end up with a weird URLs like /assets/eea17aee26bc0cae/ctx/layout/layout.css?

Tapestry doesn't rely on the servlet container to serve up your static assets (images, stylesheets, flash movies, etc.). Instead, if builds a URL that Tapestry processed itself.

The content that is sent to the browser will be GZIP compressed (if the client supports compression). In addition, Tapestry will set a far-future expires header on the content. This means that the browser will not ask for the file again, greatly reducing network traffic.

The wierd hex string is a random application version number. A new one is chosen every time the application starts up.

This is necessary so that, if an asset changes in place, browsers will download the new version. Because the application version number has changed, it represents a new asset to browsers, who will download the new version, even if the old version was previously downloaded (remember the far future expires header).

By the time your application is ready for production, you should manage the application version number directly:

AppModule.java (partial)
	public static void contributeApplicationDefaults(
			MappedConfiguration<String, String> configuration) {
		configuration.add(SymbolConstants.APPLICATION_VERSION, "1.7.5");
	}

You should be careful to change the application version number for each new deployment of your application; otherwise returning users may be stuck
with old versions of assets that have changed in the interrum.


  1. Assuming that class ViewUser is in the root-package.pages package.
  2. In fact, the page template may not even be in the web context, it may be stored on the classpath, as component templates are.

  • No labels