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).
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>
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.
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
.
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.
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>