Component Libraries

Tapestry has a very advanced concept of a component library. A component library contains both Tapestry components and Tapestry pages (not to mention engine services).

Referencing Library Components

Before a component library may be used, it must be listed in the application specification. Often, an application specification is only needed so that it may list the libraries used by the application. Libraries are identified using the <library> element.

The <library> element provides an id for the library, which is used to reference components (and pages) within the library. It also provides a path to the library's specification. This is a complete path for a .library file on the classpath. For example:

Example 3.1. Referencing a Component Library

<application name="Example Application">
      
  <library id="contrib" specification-path="/org/apache/tapestry/contrib/Contrib.library"/>
  	
</application>

In this example, Contrib.library defines a set of components, and those component can be accessed using contrib: as a prefix. In an HTML template, this might appear as:

	
<span jwcid="palette@contrib:Palette" . . . />

This example defines a component with id palette. The component will be an instance of the Palette component, supplied within the contrib component library. If an application uses multiple libraries, they will each have their own prefix. Unlike JSPs and JSP tag libraries, the prefix is set once, in the application specification, and is used consistently in all HTML templates and specifications within the application.

The same syntax may be used in page and component specifications:

<component id="palette" type="contrib:Palette">
  . . .
</component>

Library component search path

Previously, we described the search path for components and pages within the application. The rules are somewhat different for components and pages within a library.

Tapestry searches for library component specifications in the following places:

  • As specified in a <component-type> element (with the library specification)

  • In the same package folder as the library specification

The search for page specifications is identical: as defined in the library specification, or in the same package folder.

Using Private Assets

Often, a component must be packaged up with images, stylesheets or other resources (collectively termed "assets") that are needed at runtime. A reference to such an asset can be created using the <private-asset> element of the page or component specification. For example:

	
  <private-asset name="logo" resource-path="images/logo_200.png"/>
  
  <component id="image" type="Image">
    <binding name="image" expression="assets.logo"/>
  </component>

All assets (private, context or external) are converted into instances of IAsset and treated identically by components (such as Image). As in this example, relative paths are allowed: they are interpreted relative to the specification (page or component) they appear in.

The Tapestry framework will ensure that an asset will be converted to a valid URL that may be referenced from a client web browser ... even though the actual service is inside a JAR or otherwise on the classpath, not normally referenceable from the client browser.

The default behavior is to serve up the localized resource using the asset service. In effect, the framework will read the contents of the asset and pipe that binary content down to the client web browser.

An alternate behavior is to have the framework copy the asset to a fixed directory. This directory should be mapped to a know web folder; that is, have a URL that can be referenced from a client web browser. In this way, the web server can more efficiently serve up the asset, as a static resource (that just happens to be copied into place in a just-in-time manner).

This behavior is controlled by a pair of configuration properties: org.apache.tapestry.asset.dir and org.apache.tapestry.asset.URL.

Library Specifications

A library specification is a file with a .library extension. Library specifications use a root element of <library-specification>, which supports a subset of the attributes allowed within an <application> element (but allowing the same nested elements). Often, the library specification is an empty placeholder, used to an establish a search location for page and component specifications:

<!DOCTYPE library-specification PUBLIC 
  "-//Apache Software Foundation//Tapestry Specification 3.0//EN" 
  "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
	
<library-specification/>

It is allowed that components in one library be constructed using components provided by another library. The referencing library's specification may contain <library> elements that identify some other library.

Libraries and Namespaces

Tapestry organizes components and pages (but not engine services) into namespaces. Namespaces are closely related to, but not exactly the same as, the library prefix established using the <library> element in an application or library specification.

Every Tapestry application consists of a default namespace, the application namespace. This is the namespace used when referencing a page or component without a prefix. When a page or component can't be resolved within the application namespace, the framework namespaceis searched. Only if the component (or page) is not part of the framework namespace does an error result.

In fact, it is possible to override both pages and components provided by the framework. This is frequently used to change the look and feel of the default StateSession or Exception page. In theory, it is even possible to override fundamental components such as Insert or Foreach!

Every component provides a namespace property that defines the namespace (an instance of INamespace) that the component belongs to.

You rarely need to be concerned with namespaces, however. The rare exception is when a page from a library wishes to make use of the PageLink or ExternalLink components to create a link to another page within the same namespace. This is accomplished (in the source page's HTML template) as:

  <a href="#" jwcid="@PageLink" page="OtherPage" namespace="ognl:namespace"> ... </a>