tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Tapestry > Frequently Asked Questions
Date Fri, 26 Nov 2010 21:57: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/Frequently+Asked+Questions">Frequently Asked Questions</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~hlship">Howard M. Lewis Ship</a>
    </h4>
        <br/>
                         <h4>Changes (1)</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" >{include:Hibernate Support FAQ} <br>{include:Maven Support FAQ} <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">{cheese} <br></td></tr>
        </table>
</div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <div>
<ul>
    <li><a href='#FrequentlyAskedQuestions-GeneralQuestions'>General Questions</a></li>
<ul>
    <li><a href='#FrequentlyAskedQuestions-HowdoIgetstartedwithTapestry%3F'>How do I get started with Tapestry?</a></li>
    <li><a href='#FrequentlyAskedQuestions-WhydoesTapestryusePrototype%3FWhynotinsertfavoriteJavaScriptlibraryhere%3F'>Why does Tapestry use Prototype? Why not <em>insert favorite JavaScript library here</em>?</a></li>
    <li><a href='#FrequentlyAskedQuestions-WhydoesTapestryhaveitsownInversionofControlContainer%3FWhynotSpringorGuice%3F'>Why does Tapestry have its own Inversion of Control Container? Why not Spring or Guice?</a></li>
    <li><a href='#FrequentlyAskedQuestions-HowdoIupgradefromTapestry4toTapestry5%3F'>How do I upgrade from Tapestry 4 to Tapestry 5?</a></li>
    <li><a href='#FrequentlyAskedQuestions-WhyaretherebothRequestandHttpServletRequest%3F'>Why are there both Request and HttpServletRequest?</a></li>
</ul>
    <li><a href='#FrequentlyAskedQuestions-Limitations'>Limitations</a></li>
<ul>
    <li><a href='#FrequentlyAskedQuestions-HowdoIaddnewcomponentstoanexistingpagedynamically%3F'>How do I add new components to an existing page dynamically?</a></li>
    <li><a href='#FrequentlyAskedQuestions-Whydoesn%27tmyserviceimplementationreloadwhenIchangeit%3F'>Why doesn't my service implementation reload when I change it?</a></li>
</ul>
    <li><a href='#FrequentlyAskedQuestions-TemplatingandMarkup'>Templating and Markup</a></li>
<ul>
    <li><a href='#FrequentlyAskedQuestions-WhydoIgetaSAXParseExceptionwhenIuseanHTMLentity%2Csuchas%7B%7B%26amp%3Bnbsp%3B%7D%7Dinmytemplate%3F'>Why do I get a SAXParseException when I use an HTML entity, such as <tt>&amp;nbsp;</tt> in my template?</a></li>
    <li><a href='#FrequentlyAskedQuestions-Whydosomeimagesinmypageshowupasbrokenlinks%3F'>Why do some images in my page show up as broken links?</a></li>
    <li><a href='#FrequentlyAskedQuestions-What%27sthedifferencebetween%7B%7Bid%7D%7Dand%7B%7Bt%3Aid%7D%7D%3F'>What's the difference between <tt>id</tt> and <tt>t:id</tt>?</a></li>
    <li><a href='#FrequentlyAskedQuestions-WhydomyimagesandstylesheetsendupwithaweirdURLslike%7B%7B%2Fassets%2Feea17aee26bc0cae%2Fctx%2Flayout%2Flayout.css%7D%7D%3F'>Why do my images and stylesheets end up with a weird URLs like <tt>/assets/eea17aee26bc0cae/ctx/layout/layout.css</tt>?</a></li>
    <li><a href='#FrequentlyAskedQuestions-HowdoIaddaCSSclasstoaTapestrycomponent%3F'>How do I add a CSS class to a Tapestry component?</a></li>
</ul>
    <li><a href='#FrequentlyAskedQuestions-PageAndComponentClasses'>Page And Component Classes</a></li>
<ul>
    <li><a href='#FrequentlyAskedQuestions-What%27sthedifferencebetweenapageandacomponent%3F'>What's the difference between a page and a component?</a></li>
    <li><a href='#FrequentlyAskedQuestions-HowdoIstoremypageclassesinadifferentpackage%3F'>How do I store my page classes in a different package?</a></li>
    <li><a href='#FrequentlyAskedQuestions-Whydomyinstancevariableshavetobeprivate%3F'>Why do my instance variables have to be private?</a></li>
    <li><a href='#FrequentlyAskedQuestions-Whydon%27tmyinformalparametersshowupintherenderedmarkup%3F'>Why don't my informal parameters show up in the rendered markup?</a></li>
    <li><a href='#FrequentlyAskedQuestions-WhydoIgetjava.lang.LinkageErrorwhenIinvokepublicmethodsofmypageclasses%3F'>Why do I get java.lang.LinkageError when I invoke public methods of my page classes?</a></li>
    <li><a href='#FrequentlyAskedQuestions-Whichisbetter%2Cusingmagicmethodnames%28i.e.%2C%7B%7BbeginRender%28%29%7D%7D%29orannotations%28i.e.%7B%7BBeginRender%7D%7D%29%3F'>Which is better, using magic method names (i.e., <tt>beginRender()</tt>) or annotations (i.e. <tt>BeginRender</tt>)?</a></li>
    <li><a href='#FrequentlyAskedQuestions-WhydoIhavetoinjectapage%3FWhycan%27tIjustcreateoneusingnew%3F'>Why do I have to inject a page? Why can't I just create one using new?</a></li>
</ul>
    <li><a href='#FrequentlyAskedQuestions-FormsandFormComponents'>Forms and Form Components</a></li>
<ul>
    <li><a href='#FrequentlyAskedQuestions-Whatisthe%7B%7Bt%3Aformdata%7D%7Dhiddenfieldfor%3F'>What is the <tt>t:formdata</tt> hidden field for?</a></li>
    <li><a href='#FrequentlyAskedQuestions-HowdoIchangethelabelforafieldonthefly%3F'>How do I change the label for a field on the fly?</a></li>
</ul>
    <li><a href='#FrequentlyAskedQuestions-LinkComponents'>Link Components</a></li>
<ul>
    <li><a href='#FrequentlyAskedQuestions-HowdoIaddqueryparameterstoaPageLinkorActionLink%3F'>How do I add query parameters to a PageLink or ActionLink?</a></li>
</ul>
    <li><a href='#FrequentlyAskedQuestions-AjaxComponents'>Ajax Components</a></li>
<ul>
    <li><a href='#FrequentlyAskedQuestions-DoIhavetospecifyboth%7B%7Bid%7D%7Dand%7B%7Bt%3Aid%7D%7DforZonecomponents%3F'>Do I have to specify both <tt>id</tt> and <tt>t:id</tt> for Zone components?</a></li>
    <li><a href='#FrequentlyAskedQuestions-HowdoupdatethecontentofaZonefromaneventhandlermethod%3F'>How do update the content of a Zone from an event handler method?</a></li>
    <li><a href='#FrequentlyAskedQuestions-HowtoIupdatemultiplezonesinasingleeventhandler%3F'>How to I update multiple zones in a single event handler?</a></li>
    <li><a href='#FrequentlyAskedQuestions-What%27sthatweirdnumberinthemiddleoftheclientidsafteraZoneisupdated%3F'>What's that weird number in the middle of the client ids after a Zone is updated?</a></li>
</ul>
    <li><a href='#FrequentlyAskedQuestions-Injection'>Injection</a></li>
<ul>
    <li><a href='#FrequentlyAskedQuestions-What%27sthedifferencebetweenthe%7B%7BComponent%7D%7Dand%7B%7BInjectComponent%7D%7Dannotations%3F'>What's the difference between the <tt>Component</tt> and <tt>InjectComponent</tt> annotations?</a></li>
    <li><a href='#FrequentlyAskedQuestions-What%27sthedifferencebetweenthe%7B%7BInjectPage%7D%7Dand%7B%7BInjectContainer%7D%7Dannotations%3F'>What's the difference between the <tt>InjectPage</tt> and <tt>InjectContainer</tt> annotations?</a></li>
    <li><a href='#FrequentlyAskedQuestions-IgetanexceptionbecauseIhavetwoserviceswiththesameinterface%2ChowdoIhandlethis%3F'>I get an exception because I have two services with the same interface, how do I handle this?</a></li>
    <li><a href='#FrequentlyAskedQuestions-What%27sthedifferencebetween%7B%7BInject%7D%7Dand%7B%7BEnvironmental%7D%7D%3F'>What's the difference between <tt>Inject</tt> and <tt>Environmental</tt>?</a></li>
    <li><a href='#FrequentlyAskedQuestions-Iuse@Injectonafieldtoinjectaservice%2Cbutthefieldisstillnull%2Cwhathappened%3F'>I use @Inject on a field to inject a service, but the field is still null, what happened?</a></li>
</ul>
    <li><a href='#FrequentlyAskedQuestions-TapestryInversionofControlContainer'>Tapestry Inversion of Control Container</a></li>
<ul>
    <li><a href='#FrequentlyAskedQuestions-WhydoIneedtodefineaninterfaceformyservices%3FWhycan%27tIjustusetheclassitself%3F'>Why do I need to define an interface for my services? Why can't I just use the class itself?</a></li>
    <li><a href='#FrequentlyAskedQuestions-Myservicestartsathread%3BhowdoIknowwhentheapplicationisshuttingdown%2Ctostopthatthread%3F'>My service starts a thread; how do I know when the application is shutting down, to stop that thread?</a></li>
</ul>
    <li><a href='#FrequentlyAskedQuestions-Integrationwithexistingapplications'>Integration with existing applications</a></li>
<ul>
    <li><a href='#FrequentlyAskedQuestions-HowdoImakeaformonaJSPsubmitintoTapestry%3F'>How do I make a form on a JSP submit into Tapestry?</a></li>
    <li><a href='#FrequentlyAskedQuestions-HowdoIshareinformationbetweenaJSPapplicationandtheTapestryapplication%3F'>How do I share information between a JSP application and the Tapestry application?</a></li>
</ul>
    <li><a href='#FrequentlyAskedQuestions-SpecificErrors'>Specific Errors</a></li>
<ul>
    <li><a href='#FrequentlyAskedQuestions-WhydoIgettheexception%22Noserviceimplementstheinterfaceorg.apache.tapestry5.internal.InternalComponentResources%22whentryingtousetheBeanEditFormcomponent%3F'>Why do I get the exception "No service implements the interface org.apache.tapestry5.internal.InternalComponentResources" when trying to use the BeanEditForm component?</a></li>
    <li><a href='#FrequentlyAskedQuestions-Igetanerrorabout%22Pagedidnotgenerateanymarkupwhenrendered.%22butIhaveatemplate%2Cwhathappened%3F'>I get an error about "Page did not generate any markup when rendered." but I have a template, what happened?</a></li>
</ul>
    <li><a href='#FrequentlyAskedQuestions-HibernateSupport'>Hibernate Support</a></li>
<ul>
    <li><a href='#FrequentlyAskedQuestions-HowdoIgetHibernatetostartupupwhentheapplicationstartsup%2Cratherthanlazilywiththefirstrequestfortheapplication%3F'>How do I get Hibernate to startup up when the application starts up, rather than lazily with the first request for the application?</a></li>
</ul>
    <li><a href='#FrequentlyAskedQuestions-MavenSupport'>Maven Support</a></li>
<ul>
    <li><a href='#FrequentlyAskedQuestions-WhydoMavenprojectnamesandotherdetailsshowupinmypages%3F'>Why do Maven project names and other details show up in my pages?</a></li>
</ul>
</ul></div>

<h2><a name="FrequentlyAskedQuestions-GeneralQuestions"></a>General Questions</h2>

<h3><a name="FrequentlyAskedQuestions-HowdoIgetstartedwithTapestry%3F"></a>How do I get started with Tapestry?</h3>

<p>The easiest way to get started is to use <a href="http://maven.apache.org" class="external-link" rel="nofollow">Apache Maven</a> to create your initial project; Maven can use an <em>archetype</em> (a kind of project template) to create a bare-bones Tapestry application for you.  See the <a href="/confluence/display/TAPESTRY/Getting+Started" title="Getting Started">Getting Started</a> page for more details.</p>

<p>Even without Maven, Tapestry is quite easy to set up.  You just need to <a href="/confluence/display/TAPESTRY/Download" title="Download">download</a> the binaries and setup your build to place them inside your WAR's WEB-INF/lib folder. The rest is just some one-time <a href="/confluence/display/TAPESTRY/Configuration" title="Configuration">configuration of the web.xml deployment descriptor</a>.</p>

<h3><a name="FrequentlyAskedQuestions-WhydoesTapestryusePrototype%3FWhynotinsertfavoriteJavaScriptlibraryhere%3F"></a>Why does Tapestry use Prototype?  Why not <em>insert favorite JavaScript library here</em>?</h3>

<p>An important goal for Tapestry is seamless DHTML and Ajax integration. To serve that goal, it was important that the built in components be capable of Ajax operations, such as dynamically re-rendering parts of the page. Because of that, it made sense to bundle a well-known JavaScript library as part of Tapestry.</p>

<p>At the time (this would be 2006-ish), Prototype and Scriptaculous were well known and well documented, and jQuery was just getting started.</p>

<p>The intent has always been to make this aspect of Tapestry pluggable. This is work expected in Tapestry 5.3, where a kind of adapter layer will be introduced so that Tapestry can be easily customized to work with any of the major JavaScript libraries.  </p>

<h3><a name="FrequentlyAskedQuestions-WhydoesTapestryhaveitsownInversionofControlContainer%3FWhynotSpringorGuice%3F"></a>Why does Tapestry have its own Inversion of Control Container?  Why not Spring or Guice?</h3>

<p>An Inversion of Control Container is <em>the</em> key piece of Tapestry's infrastructure. It is absolutely necessary to create software as robust, performant and extensible as Tapestry.</p>

<p>Tapestry IoC includes a number of features that distinguish itself from other containers:</p>
<ul>
	<li>Configured in code, not XML</li>
	<li>Built-in extension mechanism for services: configurations and contributions</li>
	<li>Built-in aspect oriented programming model (service decorations and advice)</li>
	<li>Easy modularization</li>
	<li>Best-of-breed exception reporting</li>
</ul>


<p>Because Tapestry is implemented on top of its IoC container, and because the container makes it easy to extend or replace any service inside the container, it is possible to make the small changes to Tapestry needed to customize it to any project's needs.</p>

<h3><a name="FrequentlyAskedQuestions-HowdoIupgradefromTapestry4toTapestry5%3F"></a>How do I upgrade from Tapestry 4 to Tapestry 5?</h3>

<p>There is no existing tool that supports upgrading from Tapestry 4 to Tapestry 5; Tapestry 5 is a complete rewrite.</p>

<p>Many of the basic concepts in Tapestry 4 are still present in Tapestry 5, but refactored, improved, streamlined, and simplified.  The basic concept of pages, templates and components are largely the same. Other aspects, such as server-side event handling, is markedly different.</p>

<h3><a name="FrequentlyAskedQuestions-WhyaretherebothRequestandHttpServletRequest%3F"></a>Why are there both Request and HttpServletRequest?</h3>

<p>Tapestry's Request interface is <em>very</em> close to the standard HttpServletRequest interface. It differs in a few ways, omitting some unneeded methods, and adding a couple of new methods (such as <tt>isXHR()</tt>), as well as changing how some existing methods operate. For example, <tt>getParameterNames()</tt> returns a sorted List of Strings; HttpServletRequest returns an Enumeration, which is a very dated approach.</p>

<p>However, the stronger reason for Request (and the related interfaces Response and Session) is to enable the support for Portlets at some point in the future. By writing code in terms of Tapestry's Request, and not HttpServletRequest, you can be assured that the same code will operate in both Servlet Tapestry and Portlet Tapestry.</p>

<hr />
<p><table class='Footnotes' style='width: 100%; border:none;' cellspacing='0' cellpadding='0' summary='This table contains one or more notes for references made elsewhere on the page.'>
  <caption class='accessibility'>Footnotes</caption>
  <thead class='accessibility'>
    <tr class='accessibility'>
      <th class='accessibility' id='footnote-th1'>Reference</th>
      <th class='accessibility' id='footnote-th2'>Notes</th>
    </tr>
  </thead>
  <tbody>
  </tbody>
</table></p>

<h2><a name="FrequentlyAskedQuestions-Limitations"></a>Limitations</h2>

<h3><a name="FrequentlyAskedQuestions-HowdoIaddnewcomponentstoanexistingpagedynamically%3F"></a>How do I add new components to an existing page dynamically?</h3>

<p>The short answer here is: <b>you don't</b>. The long answer here is <b>you don't have to, to get the behavior you desire</b>.</p>

<p>One of Tapestry basic values is high scalability: this is expressed in a number of ways, reflecting scalability concerns within a single server, and within a cluster of servers.</p>

<p>Although you code Tapestry pages and components as if they were ordinary POJOs<style type='text/css'>
.FootnoteMarker, .FootnoteNum a {
  background: transparent url(/confluence/download/resources/com.adaptavist.confluence.footnoteMacros:footnote/gfx/footnote.png) no-repeat top right;
  padding: 1px 2px 0px 1px;
  border-left: 1px solid #8898B8;
  border-bottom: 1px solid #6B7C9B;
  margin: 1px;
  text-decoration: none;
}
.FootnoteNum a {
  margin-top: 2px;
  margin-right: 0px;
}
.FootnoteNum {
  font-size: x-small;
  text-align: right;
  padding-bottom: 4px;
}
.footnote-th1 {
  text-align: right;
}
.Footnote {
  padding-left: 7px;
  margin-bottom: 4px;
  border: 1px none #DDDDDD;
  writingMode: tb-rl;
}
.accessibility {
     display: none;
     visibility: hidden;
}
@media aural,braille,embossed {
        .FootnoteMarker, .FootnoteNum a {
         border: 1px solid #000000;
         background: #ffffff none;
    }
    .accessibility {
         display: run-in;
         visibility: visible;
    }
}
</style>
<script type='text/javascript' language='JavaScript'>
//<!--\n
var effectInProgress = {};
var despamEffect = function (id,effectType,duration) {
  if ((effectInProgress[id]) || (typeof(Effect)=="undefined") || (typeof(Effect[effectType])=="undefined")) return;
  new Effect[effectType](id);
  effectInProgress[id]=true;
  setTimeout('effectInProgress[\"'+id+'\"]=false;',duration*1000);
};
var oldFootnoteId = '';
var footnoteHighlight = function(id,pulsateNum) {
  if (oldFootnoteId!='') document.getElementById('Footnote'+oldFootnoteId).style['borderStyle'] = 'none';
  oldFootnoteId = id;
  document.getElementById('Footnote'+id).style['borderStyle'] = 'solid';
  despamEffect('Footnote'+id,'Highlight',1)
  if (pulsateNum) despamEffect('FootnoteNum'+id,'Pulsate',3)
}
var footnoteMarkerHighlight = function(id) {
  if (oldFootnoteId!='') document.getElementById('Footnote'+oldFootnoteId).style['borderStyle'] = 'none';
  oldFootnoteId = '';
  despamEffect('FootnoteMarker'+id,'Pulsate',3)
}
//-->
</script>

<sup id='FootnoteMarker1'>
    <a name='FootnoteMarker1'
        href='#Footnote1'
        onClick='footnoteHighlight("1",true);'
        alt='Footnote: Click here to display the footnote'
        title='Footnote: Click here to display the footnote'
        class='FootnoteMarker'>
            1
    </a>
</sup>
, as deployed by Tapestry they are closer to a traditional servlet: a single instance of each page services requests from multiple threads. Behind the scenes, Tapestry transforms you code, rewriting it on the fly.</p>

<p>What this means is that <em>any</em> incoming request must be handled by a <em>single page instance</em>. Therefore, Tapestry enforces the concept of <b>static structure, dynamic behavior</b>.</p>

<p>Tapestry provides quite a number of ways to vary what content is rendered, well beyond simple conditionals and loops. It is possible to "drag in" components from other pages when rendering a page (other FAQs will expand on this concept). The point is, that although a Tapestry page's structure is very rigid, the order in which the components of the page render does not have to be top to bottom.</p>


<h3><a name="FrequentlyAskedQuestions-Whydoesn%27tmyserviceimplementationreloadwhenIchangeit%3F"></a>Why doesn't my service implementation reload when I change it?</h3>

<p>Live service reloading has some limitations:</p>
<ul>
	<li>The service must define a service interface.</li>
	<li>The service implementation must be on the file system (not inside a JAR).</li>
	<li>The implementation must be instantiated by Tapestry, not inside code (even code inside a module class).</li>
</ul>


<p>Consider the following example module:</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 bind(ServiceBinder binder)
{
  binder.bind(ArchiveService.class, ArchiveServiceImpl.class);
}

<span class="code-keyword">public</span> <span class="code-keyword">static</span> JobQueue buildJobQueue(MessageService messageService, Map&lt;<span class="code-object">String</span>,Job&gt; configuration)
{
  JobQueueImpl service = <span class="code-keyword">new</span> JobQueueImpl(configuration);

  messageService.addQueueListener(service);
 
  <span class="code-keyword">return</span> service;
}
</pre>
</div></div>

<p>ArchiveService is reloadable, because Tapestry instantiates <tt>ArchiveServiceImpl</tt> itself.  On the other hand, Tapestry invokes <tt>buildJobQueue()</tt> and it is your code inside the method that instantiates <tt>JobQueueImpl</tt>, so the JobQueue service will not be reloadable.</p>

<p>Finally, only classes whose class files are stored directly on the file system, and not packaged inside JARs, are ever reloadable ... generally, only the services of the application being built (and not services from libraries) will be stored on the file system. This reflects the intent of reloading: as an agile development tool, but not something to be used in deployment.</p>


<hr />
<p><table class='Footnotes' style='width: 100%; border:none;' cellspacing='0' cellpadding='0' summary='This table contains one or more notes for references made elsewhere on the page.'>
  <caption class='accessibility'>Footnotes</caption>
  <thead class='accessibility'>
    <tr class='accessibility'>
      <th class='accessibility' id='footnote-th1'>Reference</th>
      <th class='accessibility' id='footnote-th2'>Notes</th>
    </tr>
  </thead>
  <tbody>
    <tr name='Footnote1'>
      <td valign='top' class='FootnoteNum' headings='footnote-th1'>
        <a href='#FootnoteMarker1'
          onClick='footnoteMarkerHighlight("1");'
          onMouseOver='footnoteHighlight("1",false);'
          alt='Footnote: Click to return to reference in text'
          title='Footnote: Click to return to reference in text'
          id='FootnoteNum1'>
            1
        </a>
      </td>
      <td id='Footnote1'
        valign='top'
        width='100%'
        class='Footnote'
        headings='footnote-th2'>
          Plain Old Java Object. Tapestry does not require you to extend any base classes or implement any special interfaces.
      </td>
    </tr>
  </tbody>
</table></p>
<h2><a name="FrequentlyAskedQuestions-TemplatingandMarkup"></a>Templating and Markup</h2>

<h3><a name="FrequentlyAskedQuestions-WhydoIgetaSAXParseExceptionwhenIuseanHTMLentity%2Csuchas%7B%7B%26amp%3Bnbsp%3B%7D%7Dinmytemplate%3F"></a>Why do I get a SAXParseException when I use an HTML entity, such as <tt>&amp;nbsp;</tt> in my template?</h3>

<p>Tapestry uses a standard SAX parser to read your templates. This means that your templates must be <em>well formed</em>: open and close tags must balance, attribute values must be quoted, and entities must be declared. The easiest way to accomplish this is to add a DOCTYPE to your the top of your template:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
&lt;!DOCTYPE html PUBLIC <span class="code-quote">"-<span class="code-comment">//W3C//DTD XHTML 1.0 Strict//EN"</span>
</span>   <span class="code-quote">"http:<span class="code-comment">//www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"</span>&gt;</span>
</pre>
</div></div>

<p>Part of the DOCTYPE is the declaration of entities such as <tt>&amp;nbsp;</tt>.</p>

<p>Alternately, you can simply use the numeric version: <tt>&amp;#160</tt>;  This is the exact same character and will render identically in the browser.</p>


<h3><a name="FrequentlyAskedQuestions-Whydosomeimagesinmypageshowupasbrokenlinks%3F"></a>Why do some images in my page show up as broken links?</h3>

<p>You have to be careful when using relative URLs inside page templates; the base URL may not always be what you expect.  For example, inside your <tt>ViewUser.tml</tt> file, you may have:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  &lt;img class=<span class="code-quote">"icon"</span> src=<span class="code-quote">"icons/admin.png"</span>/&gt;${user.name} has Administrative access
</pre>
</div></div>

<p>This makes sense; <tt>ViewUser.tml</tt> is in the web context, as is the <tt>icons</tt> folder.  The default URL for this page will be <tt>/viewuser</tt><style type='text/css'>
.FootnoteMarker, .FootnoteNum a {
  background: transparent url(/confluence/download/resources/com.adaptavist.confluence.footnoteMacros:footnote/gfx/footnote.png) no-repeat top right;
  padding: 1px 2px 0px 1px;
  border-left: 1px solid #8898B8;
  border-bottom: 1px solid #6B7C9B;
  margin: 1px;
  text-decoration: none;
}
.FootnoteNum a {
  margin-top: 2px;
  margin-right: 0px;
}
.FootnoteNum {
  font-size: x-small;
  text-align: right;
  padding-bottom: 4px;
}
.footnote-th1 {
  text-align: right;
}
.Footnote {
  padding-left: 7px;
  margin-bottom: 4px;
  border: 1px none #DDDDDD;
  writingMode: tb-rl;
}
.accessibility {
     display: none;
     visibility: hidden;
}
@media aural,braille,embossed {
        .FootnoteMarker, .FootnoteNum a {
         border: 1px solid #000000;
         background: #ffffff none;
    }
    .accessibility {
         display: run-in;
         visibility: visible;
    }
}
</style>
<script type='text/javascript' language='JavaScript'>
//<!--\n
var effectInProgress = {};
var despamEffect = function (id,effectType,duration) {
  if ((effectInProgress[id]) || (typeof(Effect)=="undefined") || (typeof(Effect[effectType])=="undefined")) return;
  new Effect[effectType](id);
  effectInProgress[id]=true;
  setTimeout('effectInProgress[\"'+id+'\"]=false;',duration*1000);
};
var oldFootnoteId = '';
var footnoteHighlight = function(id,pulsateNum) {
  if (oldFootnoteId!='') document.getElementById('Footnote'+oldFootnoteId).style['borderStyle'] = 'none';
  oldFootnoteId = id;
  document.getElementById('Footnote'+id).style['borderStyle'] = 'solid';
  despamEffect('Footnote'+id,'Highlight',1)
  if (pulsateNum) despamEffect('FootnoteNum'+id,'Pulsate',3)
}
var footnoteMarkerHighlight = function(id) {
  if (oldFootnoteId!='') document.getElementById('Footnote'+oldFootnoteId).style['borderStyle'] = 'none';
  oldFootnoteId = '';
  despamEffect('FootnoteMarker'+id,'Pulsate',3)
}
//-->
</script>

<sup id='FootnoteMarker1'>
    <a name='FootnoteMarker1'
        href='#Footnote1'
        onClick='footnoteHighlight("1",true);'
        alt='Footnote: Click here to display the footnote'
        title='Footnote: Click here to display the footnote'
        class='FootnoteMarker'>
            1
    </a>
</sup>
</p>

<p>However, most likely, the ViewUser page has a page activation context to identify which user is to be displayed:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> class ViewUser

  @Property
  @PageActivationContext
  <span class="code-keyword">private</span> User user;

  . . .
</pre>
</div></div>

<p>With a page activation context, the URL for the page will incorporate the id of the User object, something like <tt>/viewuser/37371</tt>.  This is why the relative URLs to the <tt>admin.png</tt> image is broken: the base path is relative to the page's URL, not to the page template
<sup id='FootnoteMarker2'>
    <a name='FootnoteMarker2'
        href='#Footnote2'
        onClick='footnoteHighlight("2",true);'
        alt='Footnote: Click here to display the footnote'
        title='Footnote: Click here to display the footnote'
        class='FootnoteMarker'>
            2
    </a>
</sup>
.</p>

<p>One solution would be to predict what the page URL will be, and adjust the path for that:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  &lt;img class=<span class="code-quote">"icon"</span> src=<span class="code-quote">"../icons/admin.png"</span>/&gt;${user.name} has Administrative access
</pre>
</div></div>

<p>But this has its own problems; the page activation context may vary in length at different times, or the template in question may be a component used across many different pages, making it difficult to predict what the correct relative URL would be.</p>

<p>The <em>best</em> solution for this situation, one that will be sure to work in all pages and all components, is to make use of the <tt>context:</tt> binding prefix:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  &lt;img class=<span class="code-quote">"icon"</span> src=<span class="code-quote">"${context:icons/admin.png}"</span>/&gt;${user.name} has Administrative access
</pre>
</div></div>

<p>The src attribute of the &lt;img&gt; tag will now be bound to a dynamically computed value: the location of the image file relative to the <br/>
web application context. This is especially important for components that may be used on different pages.</p>

<h3><a name="FrequentlyAskedQuestions-What%27sthedifferencebetween%7B%7Bid%7D%7Dand%7B%7Bt%3Aid%7D%7D%3F"></a>What's the difference between <tt>id</tt> and <tt>t:id</tt>?</h3>

<p>You might occasionally see something like the following in a template:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
&lt;t:zone id=<span class="code-quote">"status"</span> t:id=<span class="code-quote">"statusZone"</span>&gt;
</pre>
</div></div>

<p>Why two ids?  Why are they different?</p>

<p>The <tt>t:id</tt> attribute is the Tapestry component id. This id is unique within its immediate container.  This is the id you might use<br/>
to inject the component into your page class:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  @InjectComponent
  <span class="code-keyword">private</span> Zone statusZone;
</pre>
</div></div>

<p>The other id is the client id, a unique id for the rendered element within the client-side DOM. JavaScript that needs to access the element uses this id.  For example:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  $('status').hide();
</pre>
</div></div>

<p>In many components, the <tt>id</tt> attribute is an informal parameter; a value from the template that is blindly echoed into the output document.  In other cases, the component itself has an <tt>id</tt> attribute.  Often, in the latter case, the Tapestry component id is the <em>default</em> value for the client id.</p>


<h3><a name="FrequentlyAskedQuestions-WhydomyimagesandstylesheetsendupwithaweirdURLslike%7B%7B%2Fassets%2Feea17aee26bc0cae%2Fctx%2Flayout%2Flayout.css%7D%7D%3F"></a>Why do my images and stylesheets end up with a weird URLs like <tt>/assets/eea17aee26bc0cae/ctx/layout/layout.css</tt>?</h3>

<p>Tapestry doesn't rely on the servlet container to serve up your static assets (images, stylesheets, flash movies, etc.).  Instead, if builds a URL that Tapestry processed itself.</p>

<p>The content that is sent to the browser will be GZIP compressed (if the client supports compression). In addition, Tapestry will set a far-future expires header on the content. This means that the browser will not ask for the file again, greatly reducing network traffic.</p>

<p>The wierd hex string is a random application version number.  A new one is chosen every time the application starts up.</p>

<p>This is necessary so that, if an asset changes in place, browsers will download the new version.  Because the application version number has changed, it represents a new asset to browsers, who will download the new version, even if the old version was previously downloaded (remember the far future expires header).</p>

<p>By the time your application is ready for production, you should manage the application version number directly:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>AppModule.java (partial)</b></div><div class="codeContent panelContent">
<pre class="code-java">
	<span class="code-keyword">public</span> <span class="code-keyword">static</span> void contributeApplicationDefaults(
			MappedConfiguration&lt;<span class="code-object">String</span>, <span class="code-object">String</span>&gt; configuration) {
		configuration.add(SymbolConstants.APPLICATION_VERSION, <span class="code-quote">"1.7.5"</span>);
	}
</pre>
</div></div>

<p>You should be careful to change the application version number for each new deployment of your application; otherwise returning users may be stuck<br/>
with old versions of assets that have changed in the interrum.  This kind of mismatch can cause visual annoyances for style sheets or image files, but can break client-side behavior<br/>
for changed JavaScript libraries.</p>

<h3><a name="FrequentlyAskedQuestions-HowdoIaddaCSSclasstoaTapestrycomponent%3F"></a>How do I add a CSS class to a Tapestry component?</h3>

<p>As they say, "just do it".  The majority of Tapestry components support <em>informal parameters</em>, meaning that any extra attributes in the element (in the template)<br/>
will be rendered out as additional attributes.  So, you can apply a CSS class or style quite easily:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  &lt;t:textfield t:id=<span class="code-quote">"username"</span> class=<span class="code-quote">"big-green"</span>/&gt;
</pre>
</div></div>

<p>You can even use template expansions inside the attribute value:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  &lt;t:textfield t:id=<span class="code-quote">"username"</span> class=<span class="code-quote">"${usernameClass}"</span>/&gt;
</pre>
</div></div>

<p>and</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-object">String</span> getUsernameClass() 
  {
    <span class="code-keyword">return</span> isUrgent() ? <span class="code-quote">"urgent"</span> : <span class="code-keyword">null</span>;
  }
</pre>
</div></div>

<p>When an informal parameter is bound to null, then the attribute is not written out at all.</p>

<p>You can verify which components support informal parameters by checking the component reference, or looking for the @SupportsInformalParameters annotation in the components' source file.</p>



<hr />
<p><table class='Footnotes' style='width: 100%; border:none;' cellspacing='0' cellpadding='0' summary='This table contains one or more notes for references made elsewhere on the page.'>
  <caption class='accessibility'>Footnotes</caption>
  <thead class='accessibility'>
    <tr class='accessibility'>
      <th class='accessibility' id='footnote-th1'>Reference</th>
      <th class='accessibility' id='footnote-th2'>Notes</th>
    </tr>
  </thead>
  <tbody>
    <tr name='Footnote1'>
      <td valign='top' class='FootnoteNum' headings='footnote-th1'>
        <a href='#FootnoteMarker1'
          onClick='footnoteMarkerHighlight("1");'
          onMouseOver='footnoteHighlight("1",false);'
          alt='Footnote: Click to return to reference in text'
          title='Footnote: Click to return to reference in text'
          id='FootnoteNum1'>
            1
        </a>
      </td>
      <td id='Footnote1'
        valign='top'
        width='100%'
        class='Footnote'
        headings='footnote-th2'>
          Assuming that class ViewUser is in the <em>root-package</em>.<tt>pages</tt> package.
      </td>
    </tr>
    <tr name='Footnote2'>
      <td valign='top' class='FootnoteNum' headings='footnote-th1'>
        <a href='#FootnoteMarker2'
          onClick='footnoteMarkerHighlight("2");'
          onMouseOver='footnoteHighlight("2",false);'
          alt='Footnote: Click to return to reference in text'
          title='Footnote: Click to return to reference in text'
          id='FootnoteNum2'>
            2
        </a>
      </td>
      <td id='Footnote2'
        valign='top'
        width='100%'
        class='Footnote'
        headings='footnote-th2'>
          In fact, the page template may not even be in the web context, it may be stored on the classpath, as component templates are.
      </td>
    </tr>
  </tbody>
</table></p>
<h2><a name="FrequentlyAskedQuestions-PageAndComponentClasses"></a>Page And Component Classes</h2>

<h3><a name="FrequentlyAskedQuestions-What%27sthedifferencebetweenapageandacomponent%3F"></a>What's the difference between a page and a component?</h3>

<p>There's very little difference between the two. Pages clases must be in the <em>root-package</em>.<tt>pages</tt> package; components must be in the <em>root-package</em>.<tt>components</tt>.  Pages may provide event handlers for certain page-specific events (such as activate and passivate).  Components may have parameters.</p>

<p>Other than that, they are more equal than they are different. They may have templates or may render themselves in code (pages usually have a template, components are more likely to render only in code).</p>

<p>The major difference is that Tapestry page templates may be stored in the web context directory, as if they were static files (they can't be accessed from the client however; a specific rule prevents access to files with the <tt>.tml</tt> extension).</p>

<div class='panelMacro'><table class='warningMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/confluence/images/icons/emoticons/forbidden.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>It is possible that this feature may be removed in a later release. It is preferred that page templates be stored on the classpath, like component templates.</td></tr></table></div>

<h3><a name="FrequentlyAskedQuestions-HowdoIstoremypageclassesinadifferentpackage%3F"></a>How do I store my page classes in a different package?</h3>

<p>Tapestry is very rigid here; you can't. Page classes must go in <em>root-package</em>.<tt>pages</tt>, component classes in <em>root-package</em>.<tt>components</tt>, etc.</p>

<p>You are allowed to create sub-packages, to help organize your code better and more logically. For example, you might have _root-package.<tt>pages.account.ViewAccount</tt>, which would have the page name "account/viewaccount"<style type='text/css'>
.FootnoteMarker, .FootnoteNum a {
  background: transparent url(/confluence/download/resources/com.adaptavist.confluence.footnoteMacros:footnote/gfx/footnote.png) no-repeat top right;
  padding: 1px 2px 0px 1px;
  border-left: 1px solid #8898B8;
  border-bottom: 1px solid #6B7C9B;
  margin: 1px;
  text-decoration: none;
}
.FootnoteNum a {
  margin-top: 2px;
  margin-right: 0px;
}
.FootnoteNum {
  font-size: x-small;
  text-align: right;
  padding-bottom: 4px;
}
.footnote-th1 {
  text-align: right;
}
.Footnote {
  padding-left: 7px;
  margin-bottom: 4px;
  border: 1px none #DDDDDD;
  writingMode: tb-rl;
}
.accessibility {
     display: none;
     visibility: hidden;
}
@media aural,braille,embossed {
        .FootnoteMarker, .FootnoteNum a {
         border: 1px solid #000000;
         background: #ffffff none;
    }
    .accessibility {
         display: run-in;
         visibility: visible;
    }
}
</style>
<script type='text/javascript' language='JavaScript'>
//<!--\n
var effectInProgress = {};
var despamEffect = function (id,effectType,duration) {
  if ((effectInProgress[id]) || (typeof(Effect)=="undefined") || (typeof(Effect[effectType])=="undefined")) return;
  new Effect[effectType](id);
  effectInProgress[id]=true;
  setTimeout('effectInProgress[\"'+id+'\"]=false;',duration*1000);
};
var oldFootnoteId = '';
var footnoteHighlight = function(id,pulsateNum) {
  if (oldFootnoteId!='') document.getElementById('Footnote'+oldFootnoteId).style['borderStyle'] = 'none';
  oldFootnoteId = id;
  document.getElementById('Footnote'+id).style['borderStyle'] = 'solid';
  despamEffect('Footnote'+id,'Highlight',1)
  if (pulsateNum) despamEffect('FootnoteNum'+id,'Pulsate',3)
}
var footnoteMarkerHighlight = function(id) {
  if (oldFootnoteId!='') document.getElementById('Footnote'+oldFootnoteId).style['borderStyle'] = 'none';
  oldFootnoteId = '';
  despamEffect('FootnoteMarker'+id,'Pulsate',3)
}
//-->
</script>

<sup id='FootnoteMarker1'>
    <a name='FootnoteMarker1'
        href='#Footnote1'
        onClick='footnoteHighlight("1",true);'
        alt='Footnote: Click here to display the footnote'
        title='Footnote: Click here to display the footnote'
        class='FootnoteMarker'>
            1
    </a>
</sup>
</p>

<p>In addition, it is possible to define additional root packages for the application:</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 contributeComponentClassResolver(Configuration&lt;LibraryMapping&gt; configuration) {
       configuration.add(<span class="code-keyword">new</span> LibraryMapping(<span class="code-quote">"", "</span>com.example.app.tasks"));
       configuration.add(<span class="code-keyword">new</span> LibraryMapping(<span class="code-quote">"", "</span>com.example.app.chat"));
}
</pre>
</div></div>

<p>LibraryMappings are used to resolve a library prefix to one or more package names.  The empty string represents the application itself; the above example adds two additional root packages; you might see additional pages under <tt>com.example.app.tasks.pages</tt>, for example.</p>

<div class='panelMacro'><table class='warningMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/confluence/images/icons/emoticons/forbidden.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>Tapestry doesn't check for name collisions, and the order the packages are searched for pages and components is not defined. In general, if you can get by with a single root package for your application, that is better.</td></tr></table></div>

<h3><a name="FrequentlyAskedQuestions-Whydomyinstancevariableshavetobeprivate%3F"></a>Why do my instance variables have to be private?</h3>

<p>Tapestry does a large amount of transformation to your simple POJO classes as it loads them into memory. In many cases, it must locate every read or write of an instance variable and change its behavior; for example, reading a field that is a component parameter will cause a property of the containing page or component to be read.</p>

<p>Limiting fields to private means that Tapestry can do the necessary processing one class at a time, as needed, at runtime. More complex Aspect Orient Programming systems such as AspectJ can perform similar transformations (and much more complex ones), but requires a dedicated build step (or the introduction of a JVM agent).</p>

<h3><a name="FrequentlyAskedQuestions-Whydon%27tmyinformalparametersshowupintherenderedmarkup%3F"></a>Why don't my informal parameters show up in the rendered markup?</h3>

<p>Getting informal parameters to work is in two steps.  First, you must make a call to the <tt>ComponentResources.renderInformalParameters()</tt> method, but just as importantly, you must tell Tapestry that you want the component to support informal parameters, using the <tt>SupportsInformalParameters</tt> annotation. Here's a hypothetical component that displays an image based on the value of a <tt>Image</tt> object (presumably, a database entity):</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
@SupportsInformalParameters
<span class="code-keyword">public</span> class DBImage
{
  @Parameter(required=<span class="code-keyword">true</span>)
  <span class="code-keyword">private</span> Image image;

  @Inject
  <span class="code-keyword">private</span> ComponentResources resources;

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

    resources.renderInformalParameters(writer);

    writer.end();

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


<h3><a name="FrequentlyAskedQuestions-WhydoIgetjava.lang.LinkageErrorwhenIinvokepublicmethodsofmypageclasses%3F"></a>Why do I get java.lang.LinkageError when I invoke public methods of my page classes?</h3>

<p>In Tapestry, there are always <em>two</em> versions of page (or component) classes.  The first version is the version loaded by standard class loader: the simple POJO version that you wrote.</p>

<p>The second version is much more complicated; it's the transformed version of your code, with lots of extra hooks and changes to allow the class to operate inside Tapestry. This includes implementing new interfaces and methods, adding new constructors, and changing access to existing fields and methods.</p>

<p>Although these two classes have the same fully qualified class name, they are distinct classes because they are loaded by different class loaders.</p>


<table width="100%">
    <tr><td align="left"> 
        <table>     
            <caption align="bottom">
                                 
                                            
                        <a href="/confluence/spaces/gliffy/viewlargediagram.action?name=Class+Loaders&ceoid=23335008&key=TAPESTRY&pageId=23335008"
                                                    target=""
                                                >Full Size</a>
                        
                                  
                         |                     
                        <a href="/confluence/plugins/gliffy/showgliffyeditor.action?name=Class+Loaders&ceoid=23335008&key=TAPESTRY&lastPage=/confluence/display/TAPESTRY/Page+And+Component+Classes&pageId=23335008"
                                                    target=""
                                                >Edit Diagram</a>
                        
                                  
                         |                     
                        <a href="/confluence/spaces/gliffy/removediagram.action?name=Class+Loaders&ceoid=23335008&key=TAPESTRY&lastPage=/confluence/display/TAPESTRY/Page+And+Component+Classes&pageId=23335008&input=true"
                                                    target=""
                                                >Remove Diagram</a>
                        
                          </caption>

            <tr><td>
                            <img style="border: none" usemap="#GLIFFY_MAP_23335008_Class_Loaders" src="/confluence/plugins/servlet/gliffyapi/clientdiagramjpeg?cb=704547904&pk=pub&name=Class+Loaders&ceoid=23335008&key=TAPESTRY&size=L&version=4" alt="A&#32;Gliffy&#32;Diagram&#32;named&#58;&#32;Class&#32;Loaders" />
                       </td></tr>
        </table> 
</td></tr>
</table>
<map name='GLIFFY_MAP_23335008_Class_Loaders'></map>

<p>In a Tapestry application, most application classes are loaded from the middle class loader.  Additional class loaders are used<br/>
to support live service reloading, and live component reloading (along with component class transformation). </p>

<p>When a page or component is passed as a parameter to a service, a failure occurs (how it is reported varies in different JDK releases) because of the class mismatch.</p>

<p>The solution is to define an interface with the methods that the service will invoke on the page or component instance. The service will expect an object implementing the interface (and doesn't care what class loader loaded the implementing class).</p>

<p>Just be sure to put the interface class in a non-controlled package, such as your application's <em>root-package</em> (and <b>not</b> <em>root-package</em>.<tt>pages</tt>).</p>

<h3><a name="FrequentlyAskedQuestions-Whichisbetter%2Cusingmagicmethodnames%28i.e.%2C%7B%7BbeginRender%28%29%7D%7D%29orannotations%28i.e.%7B%7BBeginRender%7D%7D%29%3F"></a>Which is better, using magic method names (i.e., <tt>beginRender()</tt>) or annotations (i.e. <tt>BeginRender</tt>)?</h3>

<p>There is no single best way; this is where your taste may vary.  Historically, the annotations came first, and the method naming conventions came later.</p>

<p>The advantage of using the method naming conventions is that the method names are more concise, which fewer characters to type, and fewer classes to import.</p>

<p>The main disadvantage of the method naming conventions is that the method names are not meaningful. <tt>onSuccessFromLoginForm()</tt> is a less meaningful name than <tt>storeUserCredentialsAndReturnToProductsPage()</tt>, for example.</p>

<p>The second disadvantage is you are more susceptible to off-by-a-character errors. For example, <tt>onSucessFromLoginForm()</tt> will <em>never</em> be called because the event name is misspelled; this would not happen using the annotation approach:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  @OnEvent(value=EventConstants.SUCCESS, component=<span class="code-quote">"loginForm"</span>)
  <span class="code-object">Object</span> storeUserCredentialsAndReturnToProductsPage()
  {
    . . .
  }
</pre>
</div></div>

<p>The compiler will catch a misspelling of the constant <tt>SUCCESS</tt>. Likewise, local constants can be defined for key components, such as "loginForm".</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>Ultimately, it's developer choice. HLS prefers the method naming conventions in nearly all cases, especially prototypes and demos, but can see that in some projects and some teams, an annotation-only approach is best.</td></tr></table></div>

<h3><a name="FrequentlyAskedQuestions-WhydoIhavetoinjectapage%3FWhycan%27tIjustcreateoneusingnew%3F"></a>Why do I have to inject a page? Why can't I just create one using new?</h3>

<p>Tapestry tranforms your class at runtime. It tends to build a large constructor for the class instance. Further, an instance of the class is useless by itself, it must be wired together with its template and its sub-components. </p>

<p>____</p>

<p><table class='Footnotes' style='width: 100%; border:none;' cellspacing='0' cellpadding='0' summary='This table contains one or more notes for references made elsewhere on the page.'>
  <caption class='accessibility'>Footnotes</caption>
  <thead class='accessibility'>
    <tr class='accessibility'>
      <th class='accessibility' id='footnote-th1'>Reference</th>
      <th class='accessibility' id='footnote-th2'>Notes</th>
    </tr>
  </thead>
  <tbody>
    <tr name='Footnote1'>
      <td valign='top' class='FootnoteNum' headings='footnote-th1'>
        <a href='#FootnoteMarker1'
          onClick='footnoteMarkerHighlight("1");'
          onMouseOver='footnoteHighlight("1",false);'
          alt='Footnote: Click to return to reference in text'
          title='Footnote: Click to return to reference in text'
          id='FootnoteNum1'>
            1
        </a>
      </td>
      <td id='Footnote1'
        valign='top'
        width='100%'
        class='Footnote'
        headings='footnote-th2'>
          Tapestry would also create an alias "account/view", by stripping off the redundant "account" suffix. Either name is equally valid in your code, and Tapestry will use the shorter name, "account/view" in URLs.
      </td>
    </tr>
  </tbody>
</table></p>
<h2><a name="FrequentlyAskedQuestions-FormsandFormComponents"></a>Forms and Form Components</h2>

<h3><a name="FrequentlyAskedQuestions-Whatisthe%7B%7Bt%3Aformdata%7D%7Dhiddenfieldfor%3F"></a>What is the <tt>t:formdata</tt> hidden field for?</h3>

<p>In Tapestry, rendering a form can be a complicated process; inside the body of the Form component are many of field components: TextField, Select, TextArea, and so forth. Each of these must pull data out of your data model and convert it to the string form used inside the client web browser.  In addition, JavaScript to support client-side validation must be generated.  This can be further complicated by the use of Loop and If components, or made really complicated by the use of Block (to render portions of other pages: this is what the BeanEditForm component does).</p>

<p>Along the way, the Form is generating unique form control names for each field component, as it renders.</p>

<p>When the client-side Form is submitted, an event is triggered on the server-side Form component. It now needs to locate each component, in turn, inform the component of its control name, and allow the component to read the corresponding query parameter. The component then converts the client-side string back into a server-side value and performs validations before updating the data model.</p>

<p>That's where <tt>t:formdata</tt> comes in.  While components are rendering, they are using the FormSupport environmental object to record callbacks:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>FormSupport.java (partial)</b></div><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> <span class="code-keyword">interface</span> FormSupport <span class="code-keyword">extends</span> ClientElement
{
    /**
     * Stores an action <span class="code-keyword">for</span> execution during a later request.  If the action contains any mutable state, it should be in
     * its <span class="code-keyword">final</span> state before invoking <span class="code-keyword">this</span> method and its internal state should not be changed subsequently.
     */
    &lt;T&gt; void store(T component, ComponentAction&lt;T&gt; action);

    /**
     * As with {@link #store(<span class="code-object">Object</span>, org.apache.tapestry5.ComponentAction)}}, but the action is also invoked
     * immediately. This is useful <span class="code-keyword">for</span> defining an action that should occur symmetrically in both the render request and
     * the form submission's event request.
     *
     * @param component component against which to trigger the action
     * @param action    the action that will be triggered (and passed the component)
     */
    &lt;T&gt; void storeAndExecute(T component, ComponentAction&lt;T&gt; action);
</pre>
</div></div>

<p>The <tt>ComponentAction</tt> objects are the callbacks.  <tt>t:formdata</tt> is simply an object stream of these callbacks, compressed and encoded in Base64.  When using Ajax, you may see multiple <tt>t:formdata</tt> hidden fields (they are processed one after another).</p>


<h3><a name="FrequentlyAskedQuestions-HowdoIchangethelabelforafieldonthefly%3F"></a>How do I change the label for a field on the fly?</h3>


<p>Tapestry tries to be smart about generating the label string for a field.  It has some smart default logic, first checking for the <em>component-id</em><tt>-label</tt> in the container's message catalog, then ultimately converting the component's id into a user-presentable label.</p>

<p>You can override the label in two ways:</p>

<p>First, you can supply a body to the <tt>Label</tt> component:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  &lt;t:label <span class="code-keyword">for</span>=<span class="code-quote">"username"</span>&gt;${usernameLabel}&lt;/t:label&gt;
  &lt;t:textfield t:id=<span class="code-quote">"username"</span>/&gt;
</pre>
</div></div>

<p>Here, the component class must provide a <tt>usernameLabel</tt> property. That property becomes the text of the label. An implementation of the property might look something like:</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-object">String</span> getUsernameLabel()
  {
    <span class="code-keyword">return</span> systemPreferences.useEmailAddressForUserName() ? <span class="code-quote">"Email address"</span> : <span class="code-quote">"User name"</span>;
  }
</pre>
</div></div>

<p>However, if there are any validations on the field, the error message will include the default label (as discussed above).</p>

<p>To uniformly update the label both on the page, and in any validation messages, bind the TextField's <tt>label</tt> parameter:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  &lt;t:label <span class="code-keyword">for</span>=<span class="code-quote">"username"</span>/&gt;
  &lt;t:textfield t:id=<span class="code-quote">"username"</span> label=<span class="code-quote">"prop:usernameLabel"</span>/&gt;
</pre>
</div></div>

<p>The "prop:" prefix identifies that "usernameLabel" is to be interpreted as a property expression (normally, the binding for the <tt>label</tt> parameter is interpreted as a string literal).  The Label component gets the text it displays from the TextField component, and the TextField component uses the same text when generating server-side and client-side validation messages.</p>
<h2><a name="FrequentlyAskedQuestions-LinkComponents"></a>Link Components</h2>

<h3><a name="FrequentlyAskedQuestions-HowdoIaddqueryparameterstoaPageLinkorActionLink%3F"></a>How do I add query parameters to a PageLink or ActionLink?</h3>

<p>These components do not have parameters to allow you to specify query parameters for the link; they both allow you to specify a <em>context</em> (one or more values to encode into the request path).</p>

<p>However, you can accomplish the same thing with a little code and markup.  For example, to create a link to another page and pass a query parameter, you can replace your PageLink component with a standard <tt>&lt;a&gt;</tt> tag:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
&lt;a href=<span class="code-quote">"${profilePageLink}"</span>&gt;Display Profile (w/ full details)&lt;/a&gt;
</pre>
</div></div>

<p>In the matching Java class, you can create the Link programmatically:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  @Inject
  <span class="code-keyword">private</span> PageRenderLinkSource linkSource;

  <span class="code-keyword">public</span> Link getProfilePageLink()
  {
    Link link = linkSource.createPageRenderLinkWithContext(DisplayProfile.class, user);

    link.addParameterValue(<span class="code-quote">"detail"</span>, <span class="code-keyword">true</span>);

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

<p>... and in the DisplayProfile page:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> class DisplayProfile
{
  void onActivate(@RequestParameter(<span class="code-quote">"detail"</span>) <span class="code-object">boolean</span> detail)
  {
    . . .
  }
}
</pre>
</div></div>

<p>The @RequestParameter annotation directs Tapestry to extract the query parameter from the request and coerce it to type boolean.  You can use any reasonable type for such a parameter (int, long and Date are common).</p>

<p>A similar technique can be used to add query parmeters to component event URLs (the type generated by the ActionLink or EventLink components), by injecting the ComponentResources, and invoking method <tt>createEventLink()</tt>.</p>
<h2><a name="FrequentlyAskedQuestions-AjaxComponents"></a>Ajax Components</h2>

<h3><a name="FrequentlyAskedQuestions-DoIhavetospecifyboth%7B%7Bid%7D%7Dand%7B%7Bt%3Aid%7D%7DforZonecomponents%3F"></a>Do I have to specify both <tt>id</tt> and <tt>t:id</tt> for Zone components?</h3>

<p>The examples for the Zone component (in the Component Reference) consistently specify both <tt>id</tt> and <tt>t:id</tt> and this is probably a good idea.</p>

<p>Generally speaking, if you don't specify the client-side id (the <tt>id</tt> attribute), it will be the same as the Tapestry component id (<tt>t:id</tt>).</p>

<p>However, there are any number of exceptions to this rule. The Zone may be rendering inside a Loop (in which case, each rendering will have a unique client side id). The Zone may be rendering as part of a partial page render, in which case, a random unique id is inserted into the id. There are other examples where Tapestry component ids in nested components may also clash.</p>

<p>The point is, to be sure, specify the exact client id.  This will be the value for the <tt>zone</tt> parameter of the triggering component (such as a Form, PageLink, ActionLink, etc.).</p>

<h3><a name="FrequentlyAskedQuestions-HowdoupdatethecontentofaZonefromaneventhandlermethod%3F"></a>How do update the content of a Zone from an event handler method?</h3>

<p>When a client-side link or form triggers an update, the return value from the event handler method is used to construct a partial page response; this partial page response includes markup content that is used to update the Zone's client-side <tt>&lt;div&gt;</tt> element.</p>

<p>Where does that content come from?  You inject it into your page.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
&lt;t:zone id=<span class="code-quote">"search"</span> t:id=<span class="code-quote">"searchZone"</span>&gt;
  &lt;t:form t:id=<span class="code-quote">"searchForm"</span> zone=<span class="code-quote">"searchZone"</span>&gt;
    &lt;t:textfield t:id=<span class="code-quote">"query"</span> size=<span class="code-quote">"20"</span>/&gt;
    &lt;input type=<span class="code-quote">"submit"</span> value=<span class="code-quote">"Search"</span>/&gt;
  &lt;/t:form&gt;
&lt;/t:zone&gt;

&lt;t:block id=<span class="code-quote">"searchResults"</span>&gt;
  &lt;ul&gt;
    &lt;li t:type=<span class="code-quote">"loop"</span> source=<span class="code-quote">"searchHits"</span> value=<span class="code-quote">"searchHit"</span>&gt;${searchHit}&lt;/li&gt;
  &lt;/ul&gt;
&lt;/t:block&gt;
</pre>
</div></div>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  @Inject
  <span class="code-keyword">private</span> Block searchResults;

  <span class="code-object">Object</span> onSuccessFromSearchForm()
  {
    searchHits = searchService.performSearch(query);

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

<p>So, when the search form is submitted, the resulting search hits are collected.  In the same request, the searchResults block is rendered, package, and sent to the client.  The form inside the client-side Zone <tt>&lt;div&gt;</tt> is replaced with the list of hits.</p>

<p>In many cases, you just want to re-render the Zone itself, to display updated content.  In that case, you don't need a seperate <tt>&lt;t:block&gt;</tt>, instead you can use @InjectComponent to inject the Zone object itself, and return the Zone's body:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  @InjectComponent
  <span class="code-keyword">private</span> Zone statusZone;

  <span class="code-object">Object</span> onActionFromUpdateStatus()
  {
    <span class="code-keyword">return</span> statusZone.getBody();
  }
</pre>
</div></div>
<h3><a name="FrequentlyAskedQuestions-HowtoIupdatemultiplezonesinasingleeventhandler%3F"></a>How to I update multiple zones in a single event handler?</h3>

<p>To do this, you must know, on the server, the client ids of each Zone. That's one of the reasons that you will generally set the Zone's client id (via the Zone's id parameter), rather than let Tapestry assign a client id for you.</p>

<p>From the event handler method, instead of returning a Block or a Component, return a multi-zone update:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  @Inject
  <span class="code-keyword">private</span> Block searchResults;

  @Inject
  <span class="code-keyword">private</span> Block statusBlock;

  <span class="code-object">Object</span> onSuccessFromSearchForm()
  {
    searchHits = searchService.performSearch(query);

    message = <span class="code-object">String</span>.format(<span class="code-quote">"Found %,d matching documents"</span>, searchHits.size());

    <span class="code-keyword">return</span> <span class="code-keyword">new</span> MultiZoneUpdate(<span class="code-quote">"results"</span>, searchResults).add(<span class="code-quote">"status"</span>, statusBlock);
  }
</pre>
</div></div>

<h3><a name="FrequentlyAskedQuestions-What%27sthatweirdnumberinthemiddleoftheclientidsafteraZoneisupdated%3F"></a>What's that weird number in the middle of the client ids after a Zone is updated?</h3>

<p>You might start with markup in your template for a component such as a TextField:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  &lt;t:textfield t:id=<span class="code-quote">"firstName"</span>/&gt;
</pre>
</div></div>

<p>When the component initially renders as part of a full page render, you get a sensible bit of markup:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  &lt;input id=<span class="code-quote">"firstName"</span> name=<span class="code-quote">"firstName"</span> type=<span class="code-quote">"text"</span>&gt;
</pre>
</div></div>

<p>But when the form is inside a Zone and rendered as part of a zone update, the ids get weird:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
   &lt;input id=<span class="code-quote">"firstName_12a820cc40e"</span> name=<span class="code-quote">"firstName"</span> type=<span class="code-quote">"text"</span>&gt;
</pre>
</div></div>

<p>What's happening here is that Tapestry is working to prevent unwanted id clashes as part of the page update.  In an HTML document, each <tt>id</tt> is expected to be unique; most JavaScript is keyed off of the <tt>id</tt> field, for instance.</p>

<p>In a full page render, components don't just use their component id (<tt>t:id</tt>) as their client id; instead they use the <tt>JavaScriptSupport</tt> environmental to allocate a unique id. When there's no loops or conflicts, the client id matches the component id.</p>

<p>When the component is inside a loop, a suffix is appended:  <tt>firstName</tt>, <tt>firstName_0</tt>, <tt>firstName_1</tt>, etc.</p>

<p>When the component is rendered as part of an Ajax partial page update, the rules are different. Since Tapestry doesn't know what content has been rendered onto the page previously, it can't use its normal tricks to ensure that ids are unique.</p>

<p>Instead, Tapestry creates a random-ish unique id suffix, such as "12a820cc40e" in the example; this suffix is appended to all allocated ids to ensure that they do not conflict with previously rendered ids.</p>
<h2><a name="FrequentlyAskedQuestions-Injection"></a>Injection</h2>

<h3><a name="FrequentlyAskedQuestions-What%27sthedifferencebetweenthe%7B%7BComponent%7D%7Dand%7B%7BInjectComponent%7D%7Dannotations%3F"></a>What's the difference between the <tt>Component</tt> and <tt>InjectComponent</tt> annotations?</h3>

<p>The <tt>Component</tt> annotation is used to define the <em>type</em> of component, and its parameter bindings. When using <tt>Component</tt>, the template must not define the type, and any parameter bindings are merged in:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  &lt;a t:id=<span class="code-quote">"home"</span> class=<span class="code-quote">"nav"</span>&gt;Back to home&lt;/a&gt;
</pre>
</div></div>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  @Component(parameters={ <span class="code-quote">"page=index"</span> })
  <span class="code-keyword">private</span> PageLink home;
</pre>
</div></div>

<p>Here the type of component is defined by the field type. The field name is matched against the <tt>t:id</tt> in the template. The <tt>page</tt> parameter is set in the Java class, and the informal <tt>class</tt> parameter is set in the template.  If the tag in the template was <tt>&lt;t:pagelink&gt;</tt>, or if the template tag included the attribute <tt>t:type="pagelink"</tt>, then you would see an exception.</p>

<p>By contrast, <tt>InjectComponent</tt> expects the component to be already defined, and doesn't allow any configuration of it:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  &lt;t:form t:id=<span class="code-quote">"login"</span>&gt; .... &lt;/t:form&gt;
</pre>
</div></div>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  @InjectComponent
  <span class="code-keyword">private</span> Form login;
</pre>
</div></div>

<p>Again, we're matching the field name to the component id, and you would get an error if the component is not defined in the template.</p>

<h3><a name="FrequentlyAskedQuestions-What%27sthedifferencebetweenthe%7B%7BInjectPage%7D%7Dand%7B%7BInjectContainer%7D%7Dannotations%3F"></a>What's the difference between the <tt>InjectPage</tt> and <tt>InjectContainer</tt> annotations?</h3>

<p>The <tt>InjectPage</tt> annotation is used to inject some page in the application into a field of some other page.  You often see it used from event handler methods:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  @InjectPage
  <span class="code-keyword">private</span> ConfirmRegistration confirmRegistration;

  <span class="code-object">Object</span> onSuccessFromRegistrationForm()
  {
    confirmRegistration.setStatus(<span class="code-quote">"Registration accepted"</span>);
    confirmRegistration.setValidationCode(userRegistrationData.getValidationCode());

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

<p>This code pattern is used to configure peristent properties of a page before returning it; Tapestry will send a client redirect to the page to present the data.</p>

<p><tt>InjectContainer</tt> can be used inside a component or a mixin.  In a component, it injects the immediate container of the component; this is often the top-level page object.</p>

<p>In a mixin, it injects the component to which the mixin is attached.</p>

<h3><a name="FrequentlyAskedQuestions-IgetanexceptionbecauseIhavetwoserviceswiththesameinterface%2ChowdoIhandlethis%3F"></a>I get an exception because I have two services with the same interface, how do I handle this?</h3>

<p>It's not uncommon to have two or more services that implement the exact same interface. When you inject, you might start by just identifying the type of service to inject:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
	@Inject
	<span class="code-keyword">private</span> ComponentEventResultProcessor processor;
</pre>
</div></div>

<p>Which results in the error: <b>Service interface org.apache.tapestry5.services.ComponentEventResultProcessor is matched by 3 services: AjaxComponentEventResultProcessor, ComponentEventResultProcessor, ComponentInstanceResultProcessor. Automatic dependency resolution requires that exactly one service implement the interface.</b></p>

<p>We need more information than just the service interface type in order to identify which of the three services to inject. One possibility is to inject with the correct service id:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
	@InjectService(<span class="code-quote">"ComponentEventResultProcessor"</span>)
	<span class="code-keyword">private</span> ComponentEventResultProcessor processor;
</pre>
</div></div>

<p>This works ... but it is clumsy. If the service id, "ComponentEventResultProcessor", ever changes, this code will break. It's not <em>refactoring safe</em>.</p>

<p>Instead, we should use marker annotations.  If we look at <tt>TapestryModule</tt>, where the ComponentEventResultProcessor service is defined, we'll see it identifies the necessary markers:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    @Marker(
    { Primary.class, Traditional.class })
    <span class="code-keyword">public</span> ComponentEventResultProcessor buildComponentEventResultProcessor(
            Map&lt;<span class="code-object">Class</span>, ComponentEventResultProcessor&gt; configuration)
    {
        <span class="code-keyword">return</span> constructComponentEventResultProcessor(configuration);
    }
</pre>
</div></div>

<p>When a service has marker annotations, the annotations present at the <em>point of injection</em> (the field, method parameter, or constructor parameter) are used to select a matching service.  The list of services that match by type is then filtered to only include services that have all of the marker annotations present at the point of injection.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    @Inject
	@Traditional @Primary
	<span class="code-keyword">private</span> ComponentEventResultProcessor processor;
</pre>
</div></div>

<p>The two marker annotations, <tt>Traditional</tt> and <tt>Primary</tt>, ensure that only a single service matches.</p>

<h3><a name="FrequentlyAskedQuestions-What%27sthedifferencebetween%7B%7BInject%7D%7Dand%7B%7BEnvironmental%7D%7D%3F"></a>What's the difference between <tt>Inject</tt> and <tt>Environmental</tt>?</h3>

<p><tt>Inject</tt> is relatively general; it can be used to inject resources specific to a page or component (such as ComponentResources, Logger, or Messages), or it can inject services or other objects obtained from the Tapestry IoC container.  Once the page is loaded, the values for these injections never change.</p>

<p><tt>Environmental</tt> is different; it exposes a request-scoped, dynamically bound value<style type='text/css'>
.FootnoteMarker, .FootnoteNum a {
  background: transparent url(/confluence/download/resources/com.adaptavist.confluence.footnoteMacros:footnote/gfx/footnote.png) no-repeat top right;
  padding: 1px 2px 0px 1px;
  border-left: 1px solid #8898B8;
  border-bottom: 1px solid #6B7C9B;
  margin: 1px;
  text-decoration: none;
}
.FootnoteNum a {
  margin-top: 2px;
  margin-right: 0px;
}
.FootnoteNum {
  font-size: x-small;
  text-align: right;
  padding-bottom: 4px;
}
.footnote-th1 {
  text-align: right;
}
.Footnote {
  padding-left: 7px;
  margin-bottom: 4px;
  border: 1px none #DDDDDD;
  writingMode: tb-rl;
}
.accessibility {
     display: none;
     visibility: hidden;
}
@media aural,braille,embossed {
        .FootnoteMarker, .FootnoteNum a {
         border: 1px solid #000000;
         background: #ffffff none;
    }
    .accessibility {
         display: run-in;
         visibility: visible;
    }
}
</style>
<script type='text/javascript' language='JavaScript'>
//<!--\n
var effectInProgress = {};
var despamEffect = function (id,effectType,duration) {
  if ((effectInProgress[id]) || (typeof(Effect)=="undefined") || (typeof(Effect[effectType])=="undefined")) return;
  new Effect[effectType](id);
  effectInProgress[id]=true;
  setTimeout('effectInProgress[\"'+id+'\"]=false;',duration*1000);
};
var oldFootnoteId = '';
var footnoteHighlight = function(id,pulsateNum) {
  if (oldFootnoteId!='') document.getElementById('Footnote'+oldFootnoteId).style['borderStyle'] = 'none';
  oldFootnoteId = id;
  document.getElementById('Footnote'+id).style['borderStyle'] = 'solid';
  despamEffect('Footnote'+id,'Highlight',1)
  if (pulsateNum) despamEffect('FootnoteNum'+id,'Pulsate',3)
}
var footnoteMarkerHighlight = function(id) {
  if (oldFootnoteId!='') document.getElementById('Footnote'+oldFootnoteId).style['borderStyle'] = 'none';
  oldFootnoteId = '';
  despamEffect('FootnoteMarker'+id,'Pulsate',3)
}
//-->
</script>

<sup id='FootnoteMarker1'>
    <a name='FootnoteMarker1'
        href='#Footnote1'
        onClick='footnoteHighlight("1",true);'
        alt='Footnote: Click here to display the footnote'
        title='Footnote: Click here to display the footnote'
        class='FootnoteMarker'>
            1
    </a>
</sup>
.  </p>

<ul>
	<li>Request scoped: different threads (processing different requests) will see different values when reading the field.</li>
	<li>Dynamically bound: the value is explicitly placed into the Environment, and can be overridden at any time.</li>
</ul>


<p>Environmentals are a form of loosely connected communication between an outer component (or even a service) and an inner component.  Example: the Form component places a <tt>FormSupport</tt> object into the environment.  Other components, such as TextField, use the <tt>FormSupport</tt> when rendering to perform functions such as allocate unique control names or register client-side validations.  The TextField doesn't require that the Form component be the immediate container component, or even an ancestor: a Form on one page may, indirectly, communicate with a TextField on some entirely different page. Neither component directly links to the other, the <tt>FormSupport</tt> is the conduit that connects them.</p>

<h3><a name="FrequentlyAskedQuestions-Iuse@Injectonafieldtoinjectaservice%2Cbutthefieldisstillnull%2Cwhathappened%3F"></a>I use @Inject on a field to inject a service, but the field is still null, what happened?</h3>

<p>This can happen when you use the wrong @Inject annotation; for example, com.google.inject.Inject instead of org.apache.tapestry5.ioc.annotations.Inject.  This can occur when you have TestNG on the classpath, for example, and your IDE is too helpful.  Double check your imports when things seem weird.</p>

<hr />
<p><table class='Footnotes' style='width: 100%; border:none;' cellspacing='0' cellpadding='0' summary='This table contains one or more notes for references made elsewhere on the page.'>
  <caption class='accessibility'>Footnotes</caption>
  <thead class='accessibility'>
    <tr class='accessibility'>
      <th class='accessibility' id='footnote-th1'>Reference</th>
      <th class='accessibility' id='footnote-th2'>Notes</th>
    </tr>
  </thead>
  <tbody>
    <tr name='Footnote1'>
      <td valign='top' class='FootnoteNum' headings='footnote-th1'>
        <a href='#FootnoteMarker1'
          onClick='footnoteMarkerHighlight("1");'
          onMouseOver='footnoteHighlight("1",false);'
          alt='Footnote: Click to return to reference in text'
          title='Footnote: Click to return to reference in text'
          id='FootnoteNum1'>
            1
        </a>
      </td>
      <td id='Footnote1'
        valign='top'
        width='100%'
        class='Footnote'
        headings='footnote-th2'>
          . The term "Environmental" was chosen as the value "comes from the environment", whatever that means. A name more evocative of its function still has not occurred to the Tapestry team!
      </td>
    </tr>
  </tbody>
</table> </p>
<h2><a name="FrequentlyAskedQuestions-TapestryInversionofControlContainer"></a>Tapestry Inversion of Control Container</h2>

<p>Main article: <a href="/confluence/display/TAPESTRY/IoC" title="IoC">Tapestry IoC</a></p>

<h3><a name="FrequentlyAskedQuestions-WhydoIneedtodefineaninterfaceformyservices%3FWhycan%27tIjustusetheclassitself%3F"></a>Why do I need to define an interface for my services?  Why can't I just use the class itself?</h3>

<p>First of all: you can do exactly this, but you lose some of the functionality that Tapestry's IoC container provides.</p>

<p>The reason for the split is so that Tapestry can provide functionality for your service around the core service implementation.  It does this by creating <em>proxies</em>: Java classes that implement the service interface.  The methods of the proxy will ultimately invoke the methods of your service implementation.</p>

<p>One of the primary purposes for proxies is to encapsulate the service's life cycle: most services are singletons that are created <em>just in time</em>.  Just in time means only as soon as you invoke a method.  What's going on is that the life cycle proxy (the object that gets injected into pages, components or other service implementations) checks on each method invocation to see if the actual service exists yet.  If not, it instantiates and configures it (using proper locking to ensure thread safety), then delegates the method invocation to the service.</p>

<p>If you bind a service class (not a service interface and class), then the service is fully instantiated the first time it is injected, rather than at that first method invocation. Further, you can't use decorations or method advice on such a service.</p>

<p>The final reason for the service interface / implementation split is to nudge you towards always coding to an interface, which has manifest benefits for code structure, robustness, and testability.</p>

<h3><a name="FrequentlyAskedQuestions-Myservicestartsathread%3BhowdoIknowwhentheapplicationisshuttingdown%2Ctostopthatthread%3F"></a>My service starts a thread; how do I know when the application is shutting down, to stop that thread?</h3>

<p>This same concern applies to any long-lived resource (a thread, a database connection, a JMS queue connection) that a service may hold onto.  Your code needs to know when the application has been undeployed and shutdown.  This is actually quite easy, by using a service builder method.  In your module class:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  <span class="code-keyword">public</span> MyService buildMyService(ServiceResources resources, RegistryShutdownHub shutdownHub)
  {
    <span class="code-keyword">final</span> MyServiceImpl service = resources.autobuild(MyServiceImpl.class);

    shutdownHub.addRegistryShutdownListener(<span class="code-keyword">new</span> RegistryShutdownListener()
    {
      <span class="code-keyword">public</span> void registryDidShutdown()
      {
        service.shutdown();
      }
    });

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

<p>This code uses the ServiceResources object to build an instance of MyServiceImpl, with all dependencies injected. It also injects Tapestry's RegistryShutdownHub service and adds a listener. The example assumes that the service implementation (but not the service <em>interface</em>) includes a <tt>shutdown()</tt> method.</p>

<p>A valid alternative to this would be to have MyServiceImpl implement RegistryShutdownListener:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  <span class="code-keyword">public</span> MyService buildMyService(ServiceResources resources, RegistryShutdownHub shutdownHub)
  {
    <span class="code-keyword">final</span> MyServiceImpl service = resources.autobuild(MyServiceImpl.class);

    shutdownHub.addRegistryShutdownListener(service);

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

<div class='panelMacro'><table class='warningMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/confluence/images/icons/emoticons/forbidden.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>It is <b>not</b> recommended that MyServiceImpl take RegistryShutdownHub as a constructor parameter and register itself as a listener. Doing so is an example of <a href="http://www.ibm.com/developerworks/java/library/j-jtp0618.html" class="external-link" rel="nofollow">unsafe publishing</a>.</td></tr></table></div>
<h2><a name="FrequentlyAskedQuestions-Integrationwithexistingapplications"></a>Integration with existing applications</h2>

<p>You may have an existing JSP (or Struts, Spring MVC, etc.) application that you want to migrate to Tapestry. It's quite common to do this in stages, moving some functionality into Tapestry and leaving other parts, initially, in the other system.</p>

<h3><a name="FrequentlyAskedQuestions-HowdoImakeaformonaJSPsubmitintoTapestry%3F"></a>How do I make a form on a JSP submit into Tapestry?</h3>

<p>Tapestry's Form component does a lot of work while an HTML form is rendering to store all the information needed to handle the form submission in a later request; this is all very specific to Tapestry and the particular construction of your pages and forms; it can't be reproduced from a JSP.</p>

<p>Fortunately, that isn't necessary: you can have a standard HTML Form submit to a Tapestry page, you just don't get to use all of Tapestry's built in conversion and validation logic.</p>

<p>All you need to know is how Tapestry converts page class names to page names (that appear in the URL).  It's basically a matter of stripping off the <em>root-package</em>.<tt>pages</tt> prefix from the fully qualified class name. So, for example, if you are building a login screen as a JSP, you might want to have a Tapestry page to receive the user name and password.  Let's assume the Tapestry page class is <tt>com.example.myapp.pages.LoginForm</tt>; the page name will be <tt>loginform</tt><style type='text/css'>
.FootnoteMarker, .FootnoteNum a {
  background: transparent url(/confluence/download/resources/com.adaptavist.confluence.footnoteMacros:footnote/gfx/footnote.png) no-repeat top right;
  padding: 1px 2px 0px 1px;
  border-left: 1px solid #8898B8;
  border-bottom: 1px solid #6B7C9B;
  margin: 1px;
  text-decoration: none;
}
.FootnoteNum a {
  margin-top: 2px;
  margin-right: 0px;
}
.FootnoteNum {
  font-size: x-small;
  text-align: right;
  padding-bottom: 4px;
}
.footnote-th1 {
  text-align: right;
}
.Footnote {
  padding-left: 7px;
  margin-bottom: 4px;
  border: 1px none #DDDDDD;
  writingMode: tb-rl;
}
.accessibility {
     display: none;
     visibility: hidden;
}
@media aural,braille,embossed {
        .FootnoteMarker, .FootnoteNum a {
         border: 1px solid #000000;
         background: #ffffff none;
    }
    .accessibility {
         display: run-in;
         visibility: visible;
    }
}
</style>
<script type='text/javascript' language='JavaScript'>
//<!--\n
var effectInProgress = {};
var despamEffect = function (id,effectType,duration) {
  if ((effectInProgress[id]) || (typeof(Effect)=="undefined") || (typeof(Effect[effectType])=="undefined")) return;
  new Effect[effectType](id);
  effectInProgress[id]=true;
  setTimeout('effectInProgress[\"'+id+'\"]=false;',duration*1000);
};
var oldFootnoteId = '';
var footnoteHighlight = function(id,pulsateNum) {
  if (oldFootnoteId!='') document.getElementById('Footnote'+oldFootnoteId).style['borderStyle'] = 'none';
  oldFootnoteId = id;
  document.getElementById('Footnote'+id).style['borderStyle'] = 'solid';
  despamEffect('Footnote'+id,'Highlight',1)
  if (pulsateNum) despamEffect('FootnoteNum'+id,'Pulsate',3)
}
var footnoteMarkerHighlight = function(id) {
  if (oldFootnoteId!='') document.getElementById('Footnote'+oldFootnoteId).style['borderStyle'] = 'none';
  oldFootnoteId = '';
  despamEffect('FootnoteMarker'+id,'Pulsate',3)
}
//-->
</script>

<sup id='FootnoteMarker1'>
    <a name='FootnoteMarker1'
        href='#Footnote1'
        onClick='footnoteHighlight("1",true);'
        alt='Footnote: Click here to display the footnote'
        title='Footnote: Click here to display the footnote'
        class='FootnoteMarker'>
            1
    </a>
</sup>
, and the URL will be <tt>/loginform</tt>.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
&lt;form method=<span class="code-quote">"post"</span> action=<span class="code-quote">"/loginform"</span>&gt;

  &lt;input type=<span class="code-quote">"text"</span> value=<span class="code-quote">"userName"</span>/&gt;
  &lt;br/&gt;
  &lt;input type=<span class="code-quote">"password"</span> value=<span class="code-quote">"password"</span>/&gt;
  &lt;br/&gt;
  &lt;input type=<span class="code-quote">"submit"</span> value=<span class="code-quote">"Login"</span>/&gt;

&lt;/form&gt;
</pre>
</div></div>

<p>On the Tapestry side, we can expect that the LoginForm page will be activated; this means that its activate event handler will be invoked.  We can leverage this, and Tapestry's RequestParameter annotation:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> class LoginForm
{
  void onActivate(@RequestParameter(<span class="code-quote">"userName"</span>) <span class="code-object">String</span> userName, @RequestParameter(<span class="code-quote">"password"</span>) <span class="code-object">String</span> password)
  {
     <span class="code-comment">// Validate and store credentials, etc.
</span>  }
}
</pre>
</div></div>

<p>The RequestParameter annotation extracts the named query parameter from the request, coerces its type from String to the parameter type (here, also String) and passes it into the method.</p>


<h3><a name="FrequentlyAskedQuestions-HowdoIshareinformationbetweenaJSPapplicationandtheTapestryapplication%3F"></a>How do I share information between a JSP application and the Tapestry application?</h3>

<p>From the servlet container's point of view, there's no difference between a servlet, a JSP, and an entire Tapestry application. They all share the same ServletContext, and (once created), the same HttpSession.</p>

<p>On the Tapestry side, it is very easy to read and write session attributes:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> class ShowSearchResults
{
  @SessionAttribute
  <span class="code-keyword">private</span> SearchResults searchResults;
}
</pre>
</div></div>

<p>Reading the instance variable <tt>searchResults</tt> is instrumented to instead read the corresponding HttpSession attribute named "searchResults".  You can also specify the <tt>value</tt> attribute of the SessionAttribute annotation to override the default attribute name.</p>

<p>Writing to the field causes the corresponding HttpSession attribute to be modified.</p>

<p>The session is automatically created as needed.</p>


<hr />
<p><table class='Footnotes' style='width: 100%; border:none;' cellspacing='0' cellpadding='0' summary='This table contains one or more notes for references made elsewhere on the page.'>
  <caption class='accessibility'>Footnotes</caption>
  <thead class='accessibility'>
    <tr class='accessibility'>
      <th class='accessibility' id='footnote-th1'>Reference</th>
      <th class='accessibility' id='footnote-th2'>Notes</th>
    </tr>
  </thead>
  <tbody>
    <tr name='Footnote1'>
      <td valign='top' class='FootnoteNum' headings='footnote-th1'>
        <a href='#FootnoteMarker1'
          onClick='footnoteMarkerHighlight("1");'
          onMouseOver='footnoteHighlight("1",false);'
          alt='Footnote: Click to return to reference in text'
          title='Footnote: Click to return to reference in text'
          id='FootnoteNum1'>
            1
        </a>
      </td>
      <td id='Footnote1'
        valign='top'
        width='100%'
        class='Footnote'
        headings='footnote-th2'>
          Tapestry is case insensitive, so LoginForm would work just as well.
      </td>
    </tr>
  </tbody>
</table></p>
<h2><a name="FrequentlyAskedQuestions-SpecificErrors"></a>Specific Errors</h2>

<h3><a name="FrequentlyAskedQuestions-WhydoIgettheexception%22Noserviceimplementstheinterfaceorg.apache.tapestry5.internal.InternalComponentResources%22whentryingtousetheBeanEditFormcomponent%3F"></a>Why do I get the exception "No service implements the interface org.apache.tapestry5.internal.InternalComponentResources" when trying to use the BeanEditForm component?</h3>

<p>This can occur when you choose the wrong package for your data object, the object edited by the BeanEditForm component. If you place it in the same package as your pages, Tapestry will treat it like a page, and perform a number of transformation on it, including adding a new constructor.</p>

<p>Only component classes should go in the Tapestry-controlled packages (<tt>pages</tt>, <tt>components</tt>, <tt>mixins</tt> and <tt>base</tt> under your application's root package). By convention, simple data objects should go in a <tt>data</tt> package, and Hibernate entities should go in an <tt>entities</tt> package.</p>

<h3><a name="FrequentlyAskedQuestions-Igetanerrorabout%22Pagedidnotgenerateanymarkupwhenrendered.%22butIhaveatemplate%2Cwhathappened%3F"></a>I get an error about "Page did not generate any markup when rendered." but I have a template, what happened?</h3>

<p>The most common error here is that the case of the page class did not match the case of the template. For example, you might name your class ViewOrders, but name the template vieworders.tml.  The correct name for the template is ViewOrders.tml, matching the case of the Java class name.</p>

<p>Worse, you may find that your application works during development (under Windows, which is case insensitive) but does not work when deployed on a Linux or Unix server, which may be case sensitive.</p>

<p>The other cause of this may be that your template files simply are not being packaged up correctly with the rest of your application. When in doubt, use the Java <tt>jar</tt> command to see exactly whats inside your WAR file.  Your page templates should either be in the root folder of the WAR, or package with the corresponding .class file.</p>
<h2><a name="FrequentlyAskedQuestions-HibernateSupport"></a>Hibernate Support</h2>

<p>Main article: <a href="/confluence/display/TAPESTRY/Hibernate" title="Hibernate">Hibernate</a></p>

<h3><a name="FrequentlyAskedQuestions-HowdoIgetHibernatetostartupupwhentheapplicationstartsup%2Cratherthanlazilywiththefirstrequestfortheapplication%3F"></a>How do I get Hibernate to startup up when the application starts up, rather than lazily with the first request for the application?</h3>

<p>This was a minor problem in 5.0; by 5.1 it is just a matter of overriding the configuration system <tt>tapestry.hibernate-early-startup</tt> to "true".</p>
<h2><a name="FrequentlyAskedQuestions-MavenSupport"></a>Maven Support</h2>

<h3><a name="FrequentlyAskedQuestions-WhydoMavenprojectnamesandotherdetailsshowupinmypages%3F"></a>Why do Maven project names and other details show up in my pages?</h3>

<p>Tapestry and maven both use the same syntax for dynamic portions of files: the <tt>${...</tt>} syntax.  When Maven is copying resources from <tt>src/main/resources</tt>, and when filtering is <em>enabled</em> (which is not the default), then any expansions in <em>Tapestry templates</em> that match against Maven project properties are substituted.  If you look at the deployed application you'll see that <tt>${name</tt>} is gone, replaced with your project's name!</p>

<p>The solution is to update your <tt>pom.xml</tt> and ignore any .tml files when copying and filtering:</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-java">
  &lt;resource&gt;
    &lt;directory&gt;src/main/resources&lt;/directory&gt;
    &lt;excludes&gt;
      &lt;exclude&gt;**/*.tml&lt;/exclude&gt;
    &lt;/excludes&gt;
    &lt;filtering&gt;<span class="code-keyword">true</span>&lt;/filtering&gt;
  &lt;/resource&gt;

  &lt;resource&gt;
    &lt;directory&gt;src/main/resources&lt;/directory&gt;
    &lt;includes&gt;
      &lt;include&gt;**/*.tml&lt;/include&gt;
    &lt;/includes&gt;
    &lt;filtering&gt;<span class="code-keyword">false</span>&lt;/filtering&gt;
  &lt;/resource&gt;
</pre>
</div></div>
    </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/Frequently+Asked+Questions">View Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=23334884&revisedVersion=31&originalVersion=30">View Changes</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message