Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Fixed bad links due to copy-paste from cwiki-test

Assets

Wiki Markup
{float:right|background=#eee}
{contentbylabel:title=Related Articles|showLabels=false|showSpace=false|space=@self|labels=assets,response}
{float}

In Tapestry, Assets are any kind of static content that may be downloaded to a client web browser, such as images, style sheets and JavaScript files.

Div
stylefloat:right
titleRelated Articles
classaui-label
Content by Label
showLabelsfalse
showSpacefalse
titleRelated Articles
cql

...

label in ("assets","response") and space = currentSpace()

Assets can be in one of three places within a Tapestry app:

  1. In the web application's context folder

...

  1. , stored inside the web application WAR file in the usual JEE fashion. In

...

  1. a project following Maven's directory layout conventions, this would be src/main/webapp or a subdirectory of it (but not under src/main/webapp/WEB-INF).
  2. For Tapestry 5.4 and later: under META-INF, with JavaScript modules under META-INF/modules and other assets under META-INF/assets. This would be src/main/resources/META-INF/modules and src/main/resources/META-INF/assets if following Maven directory conventions.
  3. On

...

  1. the classpath, with your Java class files

...

  1. . This is deprecated in Tapestry 5.4 and later (with a warning). If following Maven directory conventions, this would correspond to a package-named subdirectory under src/main/resources/, such as src/main/resources/com/example/myapp/pages).

Referencing Assets from Templates

For referencing assets from templates, two binding prefixes exist: "context:" and "asset

Assets are exposed to your code as instances of the Asset interface.

Assets in Templates

Assets can also be referenced directly in templates. Two binding prefixes exist for this: "asset:" and "context:". The "assetcontext:" prefix can obtain assets from the classpath (the default) or from the web context (by specifying the "context:" domain explicitly):matches assets in the web application's context folder, and the "asset:" prefix is for assets from the classpath.

Code Block
languagexml
titlesrc/main/webapp/com/example/myapp/images/tapestry_banner.gifjava
<img src="${asset:context:imageimages/tapestry_banner.gif}" alt="Banner"/>
Info

This is an example of using a template expansion inside an ordinary element (rather than a component).

Because accessing context assets is so common, the "context:" binding prefix was introduced:

Code Block
languagejava
<img src="${context:image/tapestry_banner.gif}" alt="Banner"/>

Assets in Component Classes

If you don't provide either prefix, "asset:" is assumed.

Also note that in older code you may occasionally see ${asset:context:...}. That means the same thing as ${context:...}.

Assets in Component Classes

Assets are available to your code as instances of the Asset interface.

Components access assets via injection, using the @Inject annotation, which Components learn about assets via injection. The @Inject annotation allows Assets to be injected into components as read-only properties. The path to the resource is specified using the Path annotation:

...

Assets are located within domains; these domains are identified by the prefix on the @Path annotation's value.

META-INF/assets

Support for storing assets under META-INF/assets was added in Tapestry 5.4.

For security reasons (detailed below), it is best to have the assets that will be exposed to the client segregated from compiled Java classes. For that reason, classpath assets must be stored in META-INF/assets or a subfolder.

For an application asset, the assets can be stored directly in META-INF/assets.

For a library asset, Tapestry uses the library's name (from its LibraryMapping) (such as "core" for the Tapestry core library);  The library name becomes a folder under META-INF/assets; for example, Tapestry stores its component-related assets under META-INF/assets/core.

Classpath Assets 

If the prefix is omitted, the value will be interpreted as a path relative to the Java class file itself, within the "classpath:" domain. This is often used when creating component libraries, where the assets used by the components are packaged in the JAR with the components themselves.

...

In Tapestry 5.5, support for classpath assets not under META-INF/assets will may be removed.

META-INF/assets

Support for storing assets under META-INF/assets was added in Tapestry 5.4.

For security reasons (detailed below), it is best to have the assets that will be exposed to the client segregated from compiled Java classes. For that reason, classpath assets must be stored in META-INF/assets or a subfolder.

For an application asset, the assets can be stored directly in META-INF/assets.

For a library asset, Tapestry uses the library's name (from its LibraryMapping) (such as "core" for the Tapestry core library);  The library name becomes a folder under META-INF/assets; for example, Tapestry stores its component-related assets under META-INF/assets/core.

Relative Assets

You can use relative paths with domains (if you omit the prefix):

...

  • version: Application version number, defined by the tapestry.application-version symbol in your application module (normally AppModule.java). The default is a random hex number.
  • folder: Identifies the library containing the asset, or "ctx" for a context asset, or "stack" (used when combining multiple JavaScript files into a single virtual asset).
  • path: The path below the root package of the library to the specific asset file.

Asset Fingerprinting (Tapestry 5.4 and later)

Tapestry 5.4 changes how Asset URLs are constructed, the . The version number is now a content fingerprint; it is , a hash of the actual content of the asset.

...

It is frequently the case that CSS files will include links to other files, such as background images, using the url() value syntax. Under 5.4, the URL for the CSS file and the targeted file would be broken, due to the inclusions of the CSS file's content hash fingerprint. To fix this, Tapestry parses CSS files, locates the url() directives, and rewrites the URLs to be absolute (including the targeted file's content hash fingerprint).

...

Tapestry GZIP compresses the content of all assets – if the asset is compressible, the client supports it, and you don't explicitly disable it.

Further, the asset will get a far future expires header, which will encourage the client browser to cache the asset.

You For Talestry 5.3 and earlier, you should have an explicit application version number for any production application. Client browsers will aggressively cache downloaded assets; they will usually not even send a request to see if the asset has changed once the asset is downloaded the first time. Because of this it is very important that each new deployment of your application has a new version number, to force existing clients to re-download all assets.

...

Warning

This applies to how Tapestry 5.3 and earlier manage classpath assets; Tapestry 5.4 introduces another system which doesn't have this issue.

...

Because Tapestry directly exposes files on the classpath to the clients, some thought has gone into ensuring that malicious clients are not able to download assets that should not be visible to them.

...

  • Your Login page exposes a classpath asset, icon.png.
  • A malicious client copies the URL, /assets/1.0.0/app/pages/icon.png (which would indicate that the Login page is actually inside a library, which is unlikely. More likely, icon.png is a context asset and the malicious user guessed the path for Login.class by looking at the Tapestry source code.) and changes the file name to Login.class.

  • The client decompiles the class file and spots your secret emergency password: goodbye security! (Never create such back doors, of course!)

Fortunately, this can't happen. Files with extension ".class" are secured; they must be accompanied in the URL with a query parameter that is the MD5 hash of the file's contents. If the query parameter is absent, or doesn't match the actual file's content, the request is rejected.

When your code exposes an Asset , the URL will automatically include the query parameter if the file type is securedthat is secured, Tapestry generates a URL that automatically includes MD5 hash query parameter. The malicious user is locked out of access to the files. (Unless they The only way they could generate the MD5 hash is if they somehow already have the files so that they can generate the MD5 checksum ... to get access to the files they already have, in which case they don't need to download them again anyway.)

By default, Tapestry secures file extensions ".class', ".tml" and ".properties". The list can be extended by contributing to the ResourceDigestGenerator service:

...

Warning

Starting in Tapestry 5.4, there is a move to ensure that all assets are stored under META-INF/assets, rather than on the general classpath.

In Tapestry 5.5 and later, assets on the general classpath will may not be supported at all.

Minimizing Assets

...

Section
Column
Code Block
languagexml
titleFor Tapestry 5.3: pom.xml (partial)
<dependency>
    <groupId>org.apache.tapestry</groupId>
    <artifactId>tapestry-yuicompressor</artifactId>
    <version>5.3.1</version>
</dependency>

Column
Code Block
languagexml
langxml
titleFor Tapestry 5.4: pom.xml (partial)langxml
<dependency>
    <groupId>org.apache.tapestry</groupId>
    <artifactId>tapestry-webresources</artifactId>
    <version>5.4</version>
</dependency>

...

By adding this dependency, all your JavaScript and CSS files will be minimized when PRODUCTION_MODE=Production Mode is true. You can force the minimization of these files, by changing the value of the constant SymbolConstants.MINIFICATION_ENABLED in your module class (usually AppModule.java):

...