Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

As with an application, we'll follow the conventions: we'll place the module for this library inside the services package, and place pages and components under their respective packages.

Step

...

2: Create your pages and/or components

Our component is very simple:

...

This component renders out an img tag for the icon.

TypicallyOften, a component library will have many different components and/or mixins, and may even provide , or even pages.

Step

...

3: Choose a virtual folder name

In Tapestry, components that have been packaged in a library are referenced using a virtual folder name. It's effectively as if the application had a new root-level folder containing the components.

...

Code Block
xml
xml
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"
  xmlns:h="tapestry-library:happy">
  
  ...
  
  <h:icon/>
  
  ...
</html>

The special namespace mapping for sets up namespace prefix "h:" to mean the same as "happy/". It then becomes possible to reference components within the happy virtual folder directly.

Step

...

4: Configure the

...

virtual folder

Tapestry needs to know where to search for your component class. This is accomplished in your library's IoC module class, by making a contribution to the ComponentClassResolver service configuration.

...

Note

It is possible to add a mapping for "core". "core" is the core library for Tapestry components; all the built-in Tapestry components (TextField, BeanEditForm, Grid, etc.) are actually in the core library. All Tapestry does is search inside the "core" library when it does find a component in the application. Contributing an additional package as "core" simply extends the number of packages searched for core components (it doesn't replace Tapestry's default package, org.apache.tapestry5.corelib). Adding to "core" is sometimes reasonable, if there is virtually no chance of a naming conflict (via different modules contributing packages to core with conflicting class names).

Step

...

5: Configure the module to autoload

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

Step 6: Extending Client Access

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
java

public static void contributeRegexAuthorizer(Configuration<String> configuration)
{
    configuration.add("^org/example/happylib/.*\\.jpg$");
}

This contribution uses a regular expression to identify that any resource on the classpath under the org/example/happylib folder with a jpg extension is allowed. If you had a mix of different image types, you could replace jpg with (jpg|gif|png).

Step 7: Versioning Assets

Classpath assets, those packaged in JAR files (such as the happy.jpg asset) are retrieved by the client web browser using a URL that reflects the package name. Tapestry users a special virtual folder, /assets, under the context folder for this purpose.

The image file here would exposed to the web browser via the URL /happyapp/assets/org/example/happylib/components/happy.jpg (this assumes that the application was deployed as happyapp.war).

Tapestry uses a far-future expiration date for classpath assets; this allows browsers to aggresively cache the file, but this causes a problem should a later version of the library change the file. This is discussed in detail in Yahoo's Performance Best Practices.

To handle this problem, 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.

Conclusion

That's it! Autoloading plus the virtual folders for components and for assets takes care of all the issues related to components. Just build your JARs, setup the JAR Manifest, and drop them into your applications.

Since
since5.2

Added in 5.2

A note about Assets

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 librarie's root package (as folder org/example/happylib on the Java classpath).

...