Wiki Markup |
{scrollbar} |
Excerpt |
|
How to create a library of your custom components |
Creating Component Libraries
...
Tapestry doesn't mandate that you use any build system, but we'll assume for the moment that you are using Maven 2. In that case, you'll have a pom.xml file something like the following:
Code Block |
|
|
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>happylib</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>happylib Tapestry 5 Library</name>
<dependencies>
<dependency>
<groupId>org.apache.tapestry</groupId>
<artifactId>tapestry-core</artifactId>
<version>${tapestry-release-version}</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>5.1</version>
<classifier>jdk15</classifier>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
<optimize>true</optimize>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Tapestry-Module-Classes>org.example.happylib.services.HappyModule</Tapestry-Module-Classes>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>codehaus.snapshots</id>
<url>http://snapshots.repository.codehaus.org</url>
</repository>
<repository>
<id>OpenQA_Release</id>
<name>OpenQA Release Repository</name>
<url>http://archiva.openqa.org/repository/releases/</url>
</repository>
</repositories>
<properties>
<tapestry-release-version>5.2.0</tapestry-release-version>
</properties>
</project>
|
...
Our component is very simple:
Code Block |
java |
title |
HappyIcon.java |
|
|
package org.example.happylib.components;
import org.apache.tapestry5.Asset;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.Path;
import org.apache.tapestry5.ioc.annotations.Inject;
public class HappyIcon
{
@Inject
@Path("happy.jpg")
private Asset happyIcon;
boolean beginRender(MarkupWriter writer)
{
writer.element("img", "src", happyIcon);
writer.end();
return false;
}
}
|
...
The above naming is somewhat clumsy, and can be improved by introducing an additional namespace into the template:
Code Block |
|
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"
xmlns:h="tapestry-library:happy">
...
<h:icon/>
...
</html>
|
...
At application startup, Tapestry will read the library module along with all other modules and configure the ComponentClassResolver service using information in the module:
Code Block |
java |
title |
HappyModule.java |
|
|
package org.example.happylib.services;
import org.apache.tapestry5.ioc.Configuration;
import org.apache.tapestry5.services.LibraryMapping;
public class HappyModule
{
public static void contributeComponentClassResolver(Configuration<LibraryMapping> configuration)
{
configuration.add(new LibraryMapping("happy", "org.example.happylib"));
}
}
|
...
For Tapestry to load your module at application startup, it is necessary to put an entry in the JAR manifest. This is taken care of in the pom.xml above:
Code Block |
xml |
title |
pom.xml (partial) |
language |
xml |
|
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Tapestry-Module-Classes>org.example.happylib.services.HappyModule</Tapestry-Module-Classes>
</manifestEntries>
</archive>
</configuration>
</plugin>
|
...
As of Tapestry 5.2, a new step is needed: extending access for the assets. This is accomplished in your library's module class, HappyModule:
Code Block |
|
public static void contributeRegexAuthorizer(Configuration<String> configuration)
{
configuration.add("^org/example/happylib/.*\\.jpg$");
}
|
...
To handle this problem in Tapestry 5.1 and earlier, you should map your library assets to a versioned folder. This can be accomplished using another contribution from the HappyModule, this time to the ClasspathAssetAliasManager service whose configuration maps a virtual folder underneath /assets to a package:
Code Block |
|
public static void contributeClasspathAssetAliasManager(MappedConfiguration<String, String> configuration)
{
configuration.add("happylib/1.0", "org/example/happylib");
}
|
With this in place, and the library and applications rebuilt and redeployed, the URL for happy.jpg becomes /happyapp/assets/happylib/1.0/components/happy.jpg. This is shorter, but also incorporates a version number ("1.0") that can be changed in a later release.
since |
|
In version 5.2 and later, Tapestry automatically creates a mapping for assets inside your JAR. In the above example, the icon image will be exposed as {{/assets/}}{_}application version{_}{{/happy/components/happy.jpg}} (the application version number is incorporated into the URL). The "happy" portion is a virtual folder that maps to the library's root package (as folder {{org/example/happylib}} on the Java classpath). The application version is a configurable value.
|
...