Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: fixed language param of code macro
Wiki Markup
{scrollbar}
Excerpt
hiddentrue

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
languagexmlXML
titlepom.xmlXML

<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
languagejava
titleHappyIcon.javajava

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
xml
languagexml

<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
languagejava
titleHappyModule.javajava

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
languagexml
titlepom.xml (partial)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
java
languagejava

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
languagejava

public static void contributeClasspathAssetAliasManager(MappedConfiguration<String, String> configuration)
{
    configuration.add("happylib/1.0", "org/example/happylib");
}

...