tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Tapestry > Component Libraries
Date Tue, 19 Oct 2010 11:31:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/1810/9/12/_/styles/combined.css?spaceKey=TAPESTRY&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/TAPESTRY/Component+Libraries">Component
Libraries</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~ccordenier">Christophe
Cordenier</a>
    </h4>
        <br/>
                         <h4>Changes (11)</h4>
                                 
    
<div id="page-diffs">
            <table class="diff" cellpadding="0" cellspacing="0">
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >As with an application, we&#39;ll
follow the conventions: we&#39;ll place the module for this library inside the services
package, and place pages and components under their respective packages. <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >h2. Step <span class="diff-changed-words"><span
class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">3</span><span
class="diff-added-chars"style="background-color: #dfd;">2</span>:</span> Create
your pages and/or components <br></td></tr>
            <tr><td class="diff-unchanged" > <br>Our component is very simple:
<br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >This component renders out an img
tag for the icon. <br> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Typically,
a component library will have many different components and/or mixins, and may even provide
pages. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Often,
a component library will have many different components, or even pages. <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-changed-lines" >h2. Step <span class="diff-changed-words"><span
class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">2</span><span
class="diff-added-chars"style="background-color: #dfd;">3</span>:</span> Choose
a virtual folder name <br></td></tr>
            <tr><td class="diff-unchanged" > <br>In Tapestry, components
that have been packaged in a library are referenced using a virtual folder name. It&#39;s
effectively as if the application had a new root-level folder containing the components. <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >&lt;html xmlns:t=&quot;http://tapestry.apache.org/schema/tapestry_5_1_0.xsd&quot;
<br>  xmlns:h=&quot;tapestry-library:happy&quot;&gt; <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-unchanged" >  ... <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-unchanged" >  &lt;h:icon/&gt; <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-unchanged" >  ... <br>&lt;/html&gt;
<br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >The special namespace mapping for
sets up namespace prefix &quot;h:&quot; to mean the same as &quot;happy/&quot;.
It then becomes possible to reference components within the happy virtual folder directly.
<br> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h2.
Step 3: Configure the library <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">h2.
Step 4: Configure the virtual folder <br></td></tr>
            <tr><td class="diff-unchanged" > <br>Tapestry needs to know
where to search for your component class. This is accomplished in your library&#39;s IoC
module class, by making a _contribution_ to the ComponentClassResolver service configuration.
<br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >{note} <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >h2. Step <span class="diff-changed-words"><span
class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">4</span><span
class="diff-added-chars"style="background-color: #dfd;">5</span>:</span> Configure
the module to autoload <br></td></tr>
            <tr><td class="diff-unchanged" > <br>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: <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >{code} <br> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">h2.
Step 6: Extending Client Access <br> <br>As of Tapestry 5.2, a new step is needed:
extending access for the assets. This is accomplished in your library&#39;s module class,
HappyModule: <br> <br>{code:java} <br>public static void contributeRegexAuthorizer(Configuration&lt;String&gt;
configuration) <br>{ <br>    configuration.add(&quot;^org/example/happylib/.*\\.jpg$&quot;);
<br>} <br>{code} <br> <br>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). <br> <br>h2. Step 7: Versioning Assets <br> <br>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. <br> <br>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). <br> <br>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&#39;s Performance Best Practices|http://developer.yahoo.com/performance/rules.html#expires].
<br> <br>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: <br> <br>{code} <br>public static void contributeClasspathAssetAliasManager(MappedConfiguration&lt;String,
String&gt; configuration) <br>{ <br>    configuration.add(&quot;happylib/1.0&quot;,
&quot;org/example/happylib&quot;); <br>} <br>{code} <br> <br>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 (&quot;1.0&quot;) that can be changed in a later release. <br>
<br></td></tr>
            <tr><td class="diff-unchanged" >h2. Conclusion <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >That&#39;s <span class="diff-changed-words">it<span
class="diff-added-chars"style="background-color: #dfd;">\</span>!</span> 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.
<br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">{since:since=5.2}Added
in 5.2{since} <br> <br></td></tr>
            <tr><td class="diff-unchanged" >h2. A note about Assets <br>
<br></td></tr>
            <tr><td class="diff-changed-lines" >Tapestry automatically creates
a mapping for assets inside your JAR. In the above example, the icon image will be exposed
as <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">{{/assets/}}_application
version_{{/happy/components/happy.jpg}}</span> <span class="diff-added-words"style="background-color:
#dfd;">{{/assets/}}{_}application version{_}{{/happy/components/happy.jpg}}</span>
(the application version number is incorporated into the URL). The &quot;happy&quot;
portion is a virtual folder that maps to the librarie&#39;s root package (as folder {{org/example/happylib}}
on the Java classpath). <br></td></tr>
            <tr><td class="diff-unchanged" > <br>The application version
is a configurable value. <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
        </table>
</div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h1><a name="ComponentLibraries-CreatingComponentLibraries"></a>Creating
Component Libraries</h1>

<p>Nearly every Tapestry application includes a least a couple of custom components,
specific to the application. What's exciting about Tapestry is how easy it is to package components
for reuse across many applications ... and the fact that applications using a component library
need no special configuration.</p>

<p>A Tapestry component library consists of components (as well as component base class,
pages and mixins). In addition, a component library will have a module that can define new
services (needed by the components) or configure other services present in Tapestry. Finally,
components can be packaged with <em>assets</em>: resources such as images, stylesheets
and JavaScript libraries that need to be provided to the client web browser.</p>

<p>We're going to create a somewhat insipid component that displays a large happy face
icon.</p>

<p>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:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b>pom.xml</b></div><div class="codeContent
panelContent">
<pre class="code-java">&lt;project&gt;
  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
  &lt;groupId&gt;org.example&lt;/groupId&gt;
  &lt;artifactId&gt;happylib&lt;/artifactId&gt;
  &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
  &lt;packaging&gt;jar&lt;/packaging&gt;
  &lt;name&gt;happylib Tapestry 5 Library&lt;/name&gt;

  &lt;dependencies&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;org.apache.tapestry&lt;/groupId&gt;
      &lt;artifactId&gt;tapestry-core&lt;/artifactId&gt;
      &lt;version&gt;${tapestry-release-version}&lt;/version&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
      &lt;groupId&gt;org.testng&lt;/groupId&gt;
      &lt;artifactId&gt;testng&lt;/artifactId&gt;
      &lt;version&gt;5.1&lt;/version&gt;
      &lt;classifier&gt;jdk15&lt;/classifier&gt;
      &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
  &lt;/dependencies&gt;

  &lt;build&gt;
    &lt;plugins&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
        &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
        &lt;configuration&gt;
          &lt;source&gt;1.5&lt;/source&gt;
          &lt;target&gt;1.5&lt;/target&gt;
          &lt;optimize&gt;<span class="code-keyword">true</span>&lt;/optimize&gt;
        &lt;/configuration&gt;
      &lt;/plugin&gt;

      &lt;plugin&gt;
           &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
           &lt;artifactId&gt;maven-jar-plugin&lt;/artifactId&gt;
           &lt;configuration&gt;
           &lt;archive&gt;
             &lt;manifestEntries&gt;
               &lt;Tapestry-Module-Classes&gt;org.example.happylib.services.HappyModule&lt;/Tapestry-Module-Classes&gt;
             &lt;/manifestEntries&gt;
           &lt;/archive&gt;
           &lt;/configuration&gt;
       &lt;/plugin&gt;

    &lt;/plugins&gt;
  &lt;/build&gt;

  &lt;repositories&gt;
    &lt;repository&gt;
      &lt;id&gt;codehaus.snapshots&lt;/id&gt;
      &lt;url&gt;http:<span class="code-comment">//snapshots.repository.codehaus.org&lt;/url&gt;
</span>    &lt;/repository&gt;
    &lt;repository&gt;
      &lt;id&gt;OpenQA_Release&lt;/id&gt;
      &lt;name&gt;OpenQA Release Repository&lt;/name&gt;
      &lt;url&gt;http:<span class="code-comment">//archiva.openqa.org/repository/releases/&lt;/url&gt;
</span>    &lt;/repository&gt;
  &lt;/repositories&gt;

  &lt;properties&gt;
    &lt;tapestry-release-version&gt;5.2.0&lt;/tapestry-release-version&gt;
  &lt;/properties&gt;
&lt;/project&gt;
</pre>
</div></div>

<p>You will need to modify the Tapestry release version number ("5.2.0" in the listing
above) to reflect the current version of Tapestry when you create your component library.</p>

<p>We'll go into more detail about the relevant portions of this POM in the later sections.</p>

<h2><a name="ComponentLibraries-Step1%3AChooseabasepackagename"></a>Step
1: Choose a base package name</h2>

<p>Just as with Tapestry applications, Tapestry component libraries should have a <em>unique</em>
base package name. In this example, we'll use <tt>org.examples.happylib</tt>.</p>

<p>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.</p>

<h2><a name="ComponentLibraries-Step2%3ACreateyourpagesand%2Forcomponents"></a>Step
2: Create your pages and/or components</h2>

<p>Our component is very simple:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b>HappyIcon.java</b></div><div
class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">package</span> org.example.happylib.components;

<span class="code-keyword">import</span> org.apache.tapestry5.Asset;
<span class="code-keyword">import</span> org.apache.tapestry5.MarkupWriter;
<span class="code-keyword">import</span> org.apache.tapestry5.annotations.Path;
<span class="code-keyword">import</span> org.apache.tapestry5.ioc.annotations.Inject;

<span class="code-keyword">public</span> class HappyIcon
{
    @Inject
    @Path(<span class="code-quote">"happy.jpg"</span>)
    <span class="code-keyword">private</span> Asset happyIcon;

    <span class="code-object">boolean</span> beginRender(MarkupWriter writer)
    {
        writer.element(<span class="code-quote">"img"</span>, <span class="code-quote">"src"</span>,
happyIcon);
        writer.end();

        <span class="code-keyword">return</span> <span class="code-keyword">false</span>;
    }
}
</pre>
</div></div>

<p>HappyIcon appears inside the components sub-package. The happyIcon field is injected
with the the Asset for the file <tt>happy.jpg</tt>. The path specified with the
@Path annotation is relative to the <tt>HappyIcon.class</tt> file; it should be
stored in the project under <tt>src/main/resources/org/example/happylib/components</tt>.</p>

<p>Tapestry ensures that the <tt>happy.jpg</tt> asset can be accessed from
the client web browser; the src attribute of the &lt;img&gt; tag will be a URL that
directly accesses the image file ... there's no need to unpackage the <tt>happy.jpg</tt>
file. This works for any asset file stored under the librarie's root package.</p>

<p>This component renders out an img tag for the icon.</p>

<p>Often, a component library will have many different components, or even pages.</p>

<h2><a name="ComponentLibraries-Step3%3AChooseavirtualfoldername"></a>Step
3: Choose a virtual folder name</h2>

<p>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.</p>

<p>In our example, we'll use "happy" as the folder name. That means the application
will include the HappyIcon component in the template as:</p>

<ul>
	<li><tt>&lt;t:happy.happyicon/&gt;</tt> or <tt>&lt;t:happy.icon/&gt;</tt></li>
	<li><tt>&lt;img t:type="happy.happyicon"/&gt;</tt> or <tt>&lt;img
t:type="happy/icon/"&gt;</tt></li>
</ul>


<p>Why "icon" vs. "happyicon"? Tapestry notices that the folder name, "happy" is a prefix
or suffix of the class name ("HappyIcon") and creates an alias that strips off the prefix
(or suffix). To Tapestry, they are completely identical: two different aliases for the same
component class name.</p>

<p>The above naming is somewhat clumsy, and can be improved by introducing an additional
namespace into the template:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">&lt;html <span class="code-keyword">xmlns:t</span>=<span
class="code-quote">"http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"</span>
  <span class="code-keyword">xmlns:h</span>=<span class="code-quote">"tapestry-library:happy"</span>&gt;

  ...

  <span class="code-tag">&lt;h:icon/&gt;</span>

  ...
<span class="code-tag">&lt;/html&gt;</span>
</pre>
</div></div>

<p>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.</p>

<h2><a name="ComponentLibraries-Step4%3AConfigurethevirtualfolder"></a>Step
4: Configure the virtual folder</h2>

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

<p>At application startup, Tapestry will read the library module along with all other
modules and configure the ComponentClassResolver service using information in the module:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b>HappyModule.java</b></div><div
class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">package</span> org.example.happylib.services;

<span class="code-keyword">import</span> org.apache.tapestry5.ioc.Configuration;
<span class="code-keyword">import</span> org.apache.tapestry5.services.LibraryMapping;

<span class="code-keyword">public</span> class HappyModule
{
    <span class="code-keyword">public</span> <span class="code-keyword">static</span>
void contributeComponentClassResolver(Configuration&lt;LibraryMapping&gt; configuration)
    {
        configuration.add(<span class="code-keyword">new</span> LibraryMapping(<span
class="code-quote">"happy"</span>, <span class="code-quote">"org.example.happylib"</span>));
    }
}
</pre>
</div></div>

<p>The ComponentClassResolver service is responsible for mapping libraries to packages;
it takes as a contribution a collection of these LibraryMapping objects. Every module may
make its own contribution to the ComponentClassResolver service, mapping its own package ("org.example.happylib")
to its own folder ("happy").</p>

<p>This module class is also where you would define new services that can be accessed
by your components (or other parts of the application).</p>

<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/warning.gif" width="16" height="16"
align="absmiddle" alt="" border="0"></td><td>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).</td></tr></table></div>

<h2><a name="ComponentLibraries-Step5%3AConfigurethemoduletoautoload"></a>Step
5: Configure the module to autoload</h2>

<p>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:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b>pom.xml (partial)</b></div><div
class="codeContent panelContent">
<pre class="code-xml">      <span class="code-tag">&lt;plugin&gt;</span>
           <span class="code-tag">&lt;groupId&gt;</span>org.apache.maven.plugins<span
class="code-tag">&lt;/groupId&gt;</span>
           <span class="code-tag">&lt;artifactId&gt;</span>maven-jar-plugin<span
class="code-tag">&lt;/artifactId&gt;</span>
           <span class="code-tag">&lt;configuration&gt;</span>
           <span class="code-tag">&lt;archive&gt;</span>
             <span class="code-tag">&lt;manifestEntries&gt;</span>
             <span class="code-tag">&lt;Tapestry-Module-Classes&gt;</span>org.example.happylib.services.HappyModule<span
class="code-tag">&lt;/Tapestry-Module-Classes&gt;</span>
             <span class="code-tag">&lt;/manifestEntries&gt;</span>
           <span class="code-tag">&lt;/archive&gt;</span>
           <span class="code-tag">&lt;/configuration&gt;</span>
       <span class="code-tag">&lt;/plugin&gt;</span>
</pre>
</div></div>

<h2><a name="ComponentLibraries-Step6%3AExtendingClientAccess"></a>Step
6: Extending Client Access</h2>

<p>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:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> <span
class="code-keyword">static</span> void contributeRegexAuthorizer(Configuration&lt;<span
class="code-object">String</span>&gt; configuration)
{
    configuration.add(<span class="code-quote">"^org/example/happylib/.*\\.jpg$"</span>);
}
</pre>
</div></div>

<p>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&#124;gif&#124;png).</p>

<h2><a name="ComponentLibraries-Step7%3AVersioningAssets"></a>Step 7: Versioning
Assets</h2>

<p>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.</p>

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

<p>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 <a href="http://developer.yahoo.com/performance/rules.html#expires"
class="external-link" rel="nofollow">Yahoo's Performance Best Practices</a>.</p>

<p>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:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> <span
class="code-keyword">static</span> void contributeClasspathAssetAliasManager(MappedConfiguration&lt;<span
class="code-object">String</span>, <span class="code-object">String</span>&gt;
configuration)
{
    configuration.add(<span class="code-quote">"happylib/1.0"</span>, <span
class="code-quote">"org/example/happylib"</span>);
}
</pre>
</div></div>

<p>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.</p>

<h2><a name="ComponentLibraries-Conclusion"></a>Conclusion</h2>

<p>That's it&#33; 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.</p>



<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/information.gif" width="16"
height="16" align="absmiddle" alt="" border="0"></td><td><b>Added in
5.2</b><br /></td></tr></table></div>
<div style="border-right: 20px solid #D8E4F1;border-left: 20px solid #D8E4F1;"><p>Added
in 5.2</p></div>

<h2><a name="ComponentLibraries-AnoteaboutAssets"></a>A note about Assets</h2>

<p>Tapestry automatically creates a mapping for assets inside your JAR. In the above
example, the icon image will be exposed as <tt>/assets/</tt><em>application
version</em><tt>/happy/components/happy.jpg</tt> (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 <tt>org/example/happylib</tt> on the Java
classpath).</p>

<p>The application version is a configurable value.</p>

<p>In Tapestry 5.1 and earlier, it was necessary to explicitly create a mapping, via
a contribution to the ClasspathAssetAliasManager service, to expose library assets. This is
no longer necessary in Tapestry 5.2.</p>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/TAPESTRY/Component+Libraries">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=21266608&revisedVersion=4&originalVersion=3">View
Changes</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message