You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Howard Lewis Ship <hl...@gmail.com> on 2010/12/13 18:40:58 UTC

Re: [CONF] Apache Tapestry > Frequently Asked Questions

I'm beginning to think about splitting this into multiple pages, using the
same structure as the Tapestry Tutorial.

On Mon, Dec 13, 2010 at 4:12 AM, <co...@apache.org> wrote:

>    Frequently Asked Questions<https://cwiki.apache.org/confluence/display/TAPESTRY/Frequently+Asked+Questions> Page
> *edited* by Christophe Cordenier<https://cwiki.apache.org/confluence/display/~ccordenier>
> *Comment:* Add link on general Javascript FAQ
>
> Changes (3)
>  ...
>
> {include:General Questions}
> {include:Limitations}
> {include:Templating and Markup}
> {include:Page And Component Classes}
> {include:Forms and Form Components}
> {include:Link Components FAQ}
> {include:Javascript}
> {include:Ajax Components}
> {include:Injection FAQ}
> ...
> {include:Integration with existing applications}
> {include:Specific Errors}
> {include:Limitations}
> {include:Hibernate Support FAQ}
> {include:Maven Support FAQ}
>  Full Content
>
>    - General Questions<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-GeneralQuestions>
>       - How do I get started with Tapestry?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-HowdoIgetstartedwithTapestry%3F>
>       - Why does Tapestry use Prototype? Why not *insert favorite
>       JavaScript library here*?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-WhydoesTapestryusePrototype%3FWhynotinsertfavoriteJavaScriptlibraryhere%3F>
>       - Why does Tapestry have its own Inversion of Control Container? Why
>       not Spring or Guice?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-WhydoesTapestryhaveitsownInversionofControlContainer%3FWhynotSpringorGuice%3F>
>       - How do I upgrade from Tapestry 4 to Tapestry 5?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-HowdoIupgradefromTapestry4toTapestry5%3F>
>       - Why are there both Request and HttpServletRequest?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-WhyaretherebothRequestandHttpServletRequest%3F>
>    - Templating and Markup<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-TemplatingandMarkup>
>       - Why do I get a SAXParseException when I use an HTML entity, such
>       as &nbsp; in my template?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-WhydoIgetaSAXParseExceptionwhenIuseanHTMLentity%2Csuchas%7B%7B%26amp%3Bnbsp%3B%7D%7Dinmytemplate%3F>
>       - Why do some images in my page show up as broken links?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Whydosomeimagesinmypageshowupasbrokenlinks%3F>
>       - What's the difference between id and t:id?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-What%27sthedifferencebetween%7B%7Bid%7D%7Dand%7B%7Bt%3Aid%7D%7D%3F>
>       - Why do my images and stylesheets end up with a weird URLs like
>       /assets/eea17aee26bc0cae/ctx/layout/layout.css?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-WhydomyimagesandstylesheetsendupwithaweirdURLslike%7B%7B%2Fassets%2Feea17aee26bc0cae%2Fctx%2Flayout%2Flayout.css%7D%7D%3F>
>       - How do I add a CSS class to a Tapestry component?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-HowdoIaddaCSSclasstoaTapestrycomponent%3F>
>    - Page And Component Classes<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-PageAndComponentClasses>
>       - What's the difference between a page and a component?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-What%27sthedifferencebetweenapageandacomponent%3F>
>       - How do I store my page classes in a different package?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-HowdoIstoremypageclassesinadifferentpackage%3F>
>       - Why do my instance variables have to be private?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Whydomyinstancevariableshavetobeprivate%3F>
>       - Why don't my informal parameters show up in the rendered markup?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Whydon%27tmyinformalparametersshowupintherenderedmarkup%3F>
>       - Why do I get java.lang.LinkageError when I invoke public methods
>       of my page classes?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-WhydoIgetjava.lang.LinkageErrorwhenIinvokepublicmethodsofmypageclasses%3F>
>       - Which is better, using magic method names (i.e., beginRender()) or
>       annotations (i.e. BeginRender)?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Whichisbetter%2Cusingmagicmethodnames%28i.e.%2C%7B%7BbeginRender%28%29%7D%7D%29orannotations%28i.e.%7B%7BBeginRender%7D%7D%29%3F>
>       - Why do I have to inject a page? Why can't I just create one using
>       new?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-WhydoIhavetoinjectapage%3FWhycan%27tIjustcreateoneusingnew%3F>
>    - Forms and Form Components<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-FormsandFormComponents>
>       - What is the t:formdata hidden field for?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Whatisthe%7B%7Bt%3Aformdata%7D%7Dhiddenfieldfor%3F>
>       - How do I change the label for a field on the fly?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-HowdoIchangethelabelforafieldonthefly%3F>
>    - Link Components<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-LinkComponents>
>       - How do I add query parameters to a PageLink or ActionLink?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-HowdoIaddqueryparameterstoaPageLinkorActionLink%3F>
>    - Javascript<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Javascript>
>       - Why do i get "Tapestry is undefined" error on form submit?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Whydoiget%22Tapestryisundefined%22erroronformsubmit%3F>
>    - Ajax Components<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-AjaxComponents>
>       - Do I have to specify both id and t:id for Zone components?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-DoIhavetospecifyboth%7B%7Bid%7D%7Dand%7B%7Bt%3Aid%7D%7DforZonecomponents%3F>
>       - How do update the content of a Zone from an event handler method?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-HowdoupdatethecontentofaZonefromaneventhandlermethod%3F>
>       - How to I update multiple zones in a single event handler?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-HowtoIupdatemultiplezonesinasingleeventhandler%3F>
>       - What's that weird number in the middle of the client ids after a
>       Zone is updated?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-What%27sthatweirdnumberinthemiddleoftheclientidsafteraZoneisupdated%3F>
>    - Injection<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Injection>
>       - What's the difference between the Component and InjectComponentannotations?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-What%27sthedifferencebetweenthe%7B%7BComponent%7D%7Dand%7B%7BInjectComponent%7D%7Dannotations%3F>
>       - What's the difference between the InjectPage and InjectContainerannotations?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-What%27sthedifferencebetweenthe%7B%7BInjectPage%7D%7Dand%7B%7BInjectContainer%7D%7Dannotations%3F>
>       - I get an exception because I have two services with the same
>       interface, how do I handle this?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-IgetanexceptionbecauseIhavetwoserviceswiththesameinterface%2ChowdoIhandlethis%3F>
>       - What's the difference between Inject and Environmental?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-What%27sthedifferencebetween%7B%7BInject%7D%7Dand%7B%7BEnvironmental%7D%7D%3F>
>       - I use @Inject on a field to inject a service, but the field is
>       still null, what happened?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Iuse@Injectonafieldtoinjectaservice%2Cbutthefieldisstillnull%2Cwhathappened%3F>
>    - Tapestry Inversion of Control Container<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-TapestryInversionofControlContainer>
>       - Why do I need to define an interface for my services? Why can't I
>       just use the class itself?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-WhydoIneedtodefineaninterfaceformyservices%3FWhycan%27tIjustusetheclassitself%3F>
>       - My service starts a thread; how do I know when the application is
>       shutting down, to stop that thread?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Myservicestartsathread%3BhowdoIknowwhentheapplicationisshuttingdown%2Ctostopthatthread%3F>
>    - Integration with existing applications<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Integrationwithexistingapplications>
>       - How do I make a form on a JSP submit into Tapestry?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-HowdoImakeaformonaJSPsubmitintoTapestry%3F>
>       - How do I share information between a JSP application and the
>       Tapestry application?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-HowdoIshareinformationbetweenaJSPapplicationandtheTapestryapplication%3F>
>    - Specific Errors<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-SpecificErrors>
>       - Why do I get the exception "No service implements the interface
>       org.apache.tapestry5.internal.InternalComponentResources" when trying to use
>       the BeanEditForm component?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-WhydoIgettheexception%22Noserviceimplementstheinterfaceorg.apache.tapestry5.internal.InternalComponentResources%22whentryingtousetheBeanEditFormcomponent%3F>
>       - I get an error about "Page did not generate any markup when
>       rendered." but I have a template, what happened?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Igetanerrorabout%22Pagedidnotgenerateanymarkupwhenrendered.%22butIhaveatemplate%2Cwhathappened%3F>
>    - Limitations<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Limitations>
>       - How do I add new components to an existing page dynamically?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-HowdoIaddnewcomponentstoanexistingpagedynamically%3F>
>       - Why doesn't my service implementation reload when I change it?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-Whydoesn%27tmyserviceimplementationreloadwhenIchangeit%3F>
>    - Hibernate Support<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-HibernateSupport>
>       - How do I get Hibernate to startup up when the application starts
>       up, rather than lazily with the first request for the application?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-HowdoIgetHibernatetostartupupwhentheapplicationstartsup%2Cratherthanlazilywiththefirstrequestfortheapplication%3F>
>    - Maven Support<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-MavenSupport>
>       - Why do Maven project names and other details show up in my pages?<https://cwiki.apache.org/confluence#FrequentlyAskedQuestions-WhydoMavenprojectnamesandotherdetailsshowupinmypages%3F>
>
> General Questions How do I get started with Tapestry?
>
> The easiest way to get started is to use Apache Maven<http://maven.apache.org>to create your initial project; Maven can use an
> *archetype* (a kind of project template) to create a bare-bones Tapestry
> application for you. See the Getting Started<https://cwiki.apache.org/confluence/display/TAPESTRY/Getting+Started>page for more details.
>
> Even without Maven, Tapestry is quite easy to set up. You just need to
> download <https://cwiki.apache.org/confluence/display/TAPESTRY/Download>the binaries and setup your build to place them inside your WAR's
> WEB-INF/lib folder. The rest is just some one-time configuration of the
> web.xml deployment descriptor<https://cwiki.apache.org/confluence/display/TAPESTRY/Configuration>
> .
> Why does Tapestry use Prototype? Why not *insert favorite JavaScript
> library here*?
>
> 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.
>
> At the time (this would be 2006-ish), Prototype and Scriptaculous were well
> known and well documented, and jQuery was just getting started.
>
> 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.
> Why does Tapestry have its own Inversion of Control Container? Why not
> Spring or Guice?
>
> An Inversion of Control Container is *the* key piece of Tapestry's
> infrastructure. It is absolutely necessary to create software as robust,
> performant and extensible as Tapestry.
>
> Tapestry IoC includes a number of features that distinguish itself from
> other containers:
>
>    - Configured in code, not XML
>    - Built-in extension mechanism for services: configurations and
>    contributions
>    - Built-in aspect oriented programming model (service decorations and
>    advice)
>    - Easy modularization
>    - Best-of-breed exception reporting
>
> 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.
> How do I upgrade from Tapestry 4 to Tapestry 5?
>
> There is no existing tool that supports upgrading from Tapestry 4 to
> Tapestry 5; Tapestry 5 is a complete rewrite.
>
> 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.
> Why are there both Request and HttpServletRequest?
>
> Tapestry's Request interface is *very* 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 isXHR()), as
> well as changing how some existing methods operate. For example,
> getParameterNames() returns a sorted List of Strings; HttpServletRequest
> returns an Enumeration, which is a very dated approach.
>
> 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.
> ------------------------------
>
> Footnotes  Reference Notes
>
> Templating and Markup Why do I get a SAXParseException when I use an HTML
> entity, such as &nbsp; in my template?
>
> Tapestry uses a standard SAX parser to read your templates. This means that
> your templates must be *well formed*: 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:
>
> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
>
>  Part of the DOCTYPE is the declaration of entities such as &nbsp;.
>
> Alternately, you can simply use the numeric version: &#160; This is the
> exact same character and will render identically in the browser.
> Why do some images in my page show up as broken links?
>
> 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
> ViewUser.tml file, you may have:
>
>   <img class="icon" src="icons/admin.png"/>${user.name} has Administrative access
>
>  This makes sense; ViewUser.tml is in the web context, as is the iconsfolder. The default URL for this page will be
> /viewuser  1 <https://cwiki.apache.org/confluence#Footnote1>
>
> However, most likely, the ViewUser page has a page activation context to
> identify which user is to be displayed:
>
> public class ViewUser
>
>   @Property
>   @PageActivationContext
>   private User user;
>
>   . . .
>
>  With a page activation context, the URL for the page will incorporate the
> id of the User object, something like /viewuser/37371. This is why the
> relative URLs to the admin.png image is broken: the base path is relative
> to the page's URL, not to the page template  2
> <https://cwiki.apache.org/confluence#Footnote2> .
>
> One solution would be to predict what the page URL will be, and adjust the
> path for that:
>
>   <img class="icon" src="../icons/admin.png"/>${user.name} has Administrative access
>
>  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.
>
> The *best* solution for this situation, one that will be sure to work in
> all pages and all components, is to make use of the context: binding
> prefix:
>
>   <img class="icon" src="${context:icons/admin.png}"/>${user.name} has Administrative access
>
>  The src attribute of the <img> tag will now be bound to a dynamically
> computed value: the location of the image file relative to the
> web application context. This is especially important for components that
> may be used on different pages.
> What's the difference between id and t:id?
>
> You might occasionally see something like the following in a template:
>
> <t:zone id="status" t:id="statusZone">
>
>  Why two ids? Why are they different?
>
> The t:id attribute is the Tapestry component id. This id is unique within
> its immediate container. This is the id you might use
> to inject the component into your page class:
>
>   @InjectComponent
>   private Zone statusZone;
>
>  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:
>
>   $('status').hide();
>
>  In many components, the id 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 id attribute. Often, in the latter
> case, the Tapestry component id is the *default* value for the client id.
> Why do my images and stylesheets end up with a weird URLs like
> /assets/eea17aee26bc0cae/ctx/layout/layout.css?
>
> 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.
>
> 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.
>
> The wierd hex string is a random application version number. A new one is
> chosen every time the application starts up.
>
> 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).
>
> By the time your application is ready for production, you should manage the
> application version number directly:
> *AppModule.java (partial)*
>
> 	public static void contributeApplicationDefaults(
> 			MappedConfiguration<String, String> configuration) {
> 		configuration.add(SymbolConstants.APPLICATION_VERSION, "1.7.5");
> 	}
>
>  You should be careful to change the application version number for each
> new deployment of your application; otherwise returning users may be stuck
> 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
> for changed JavaScript libraries.
> How do I add a CSS class to a Tapestry component?
>
> As they say, "just do it". The majority of Tapestry components support *informal
> parameters*, meaning that any extra attributes in the element (in the
> template)
> will be rendered out as additional attributes. So, you can apply a CSS
> class or style quite easily:
>
>   <t:textfield t:id="username" class="big-green"/>
>
>  You can even use template expansions inside the attribute value:
>
>   <t:textfield t:id="username" class="${usernameClass}"/>
>
>  and
>
>   public String getUsernameClass()
>   {
>     return isUrgent() ? "urgent" : null;
>   }
>
>  When an informal parameter is bound to null, then the attribute is not
> written out at all.
>
> You can verify which components support informal parameters by checking the
> component reference, or looking for the @SupportsInformalParameters
> annotation in the components' source file.
> ------------------------------
>
> Footnotes  Reference Notes    1
> <https://cwiki.apache.org/confluence#FootnoteMarker1>  Assuming that class
> ViewUser is in the *root-package*.pages package.   2
> <https://cwiki.apache.org/confluence#FootnoteMarker2>  In fact, the page
> template may not even be in the web context, it may be stored on the
> classpath, as component templates are.
>
> Page And Component Classes
>
> Main article: Component Classes<https://cwiki.apache.org/confluence/display/TAPESTRY/Component+Classes>
> What's the difference between a page and a component?
>
> There's very little difference between the two. Pages classes must be in
> the *root-package*.pages package; components must be in the *root-package*
> .components. Pages may provide event handlers for certain page-specific
> events (such as activate and passivate). Components may have parameters.
>
> 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).
>
> 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
> .tml extension).
> 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.
> How do I store my page classes in a different package?
>
> Tapestry is very rigid here; you can't. Page classes must go in *
> root-package*.pages, component classes in *root-package*.components, etc.
>
> You are allowed to create sub-packages, to help organize your code better
> and more logically. For example, you might have _root-package.
> pages.account.ViewAccount, which would have the page name
> "account/viewaccount"  1 <https://cwiki.apache.org/confluence#Footnote1>
>
> In addition, it is possible to define additional root packages for the
> application:
>
> public static void contributeComponentClassResolver(Configuration<LibraryMapping> configuration) {
>        configuration.add(new LibraryMapping("", "com.example.app.tasks"));
>        configuration.add(new LibraryMapping("", "com.example.app.chat"));
> }
>
>  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 com.example.app.tasks.pages, for example.
> 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.
> Why do my instance variables have to be private?
>
> 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.
>
> 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).
> Why don't my informal parameters show up in the rendered markup?
>
> Getting informal parameters to work is in two steps. First, you must make a
> call to the ComponentResources.renderInformalParameters() method, but just
> as importantly, you must tell Tapestry that you want the component to
> support informal parameters, using the SupportsInformalParametersannotation. Here's a hypothetical component that displays an image based on
> the value of a Image object (presumably, a database entity):
>
> @SupportsInformalParameterspublic class DBImage
> {
>   @Parameter(required=true)
>   private Image image;
>
>   @Inject
>   private ComponentResources resources;
>
>   boolean beginRender(MarkupWriter writer)
>   {
>     writer.element("img", "src", image.toClientURL(), "class", "db-image");
>
>     resources.renderInformalParameters(writer);
>
>     writer.end();
>
>     return false;
>   }
> }
>
>  Why do I get java.lang.LinkageError when I invoke public methods of my
> page classes?
>
> In Tapestry, there are always *two* versions of page (or component)
> classes. The first version is the version loaded by standard class loader:
> the simple POJO version that you wrote.
>
> 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.
>
> Although these two classes have the same fully qualified class name, they
> are distinct classes because they are loaded by different class loaders.
>   Full Size<https://cwiki.apache.org/confluence/spaces/gliffy/viewlargediagram.action?name=Class+Loaders&ceoid=23335008&key=TAPESTRY&pageId=23335008>| Edit
> Diagram<https://cwiki.apache.org/confluence/plugins/gliffy/showgliffyeditor.action?name=Class+Loaders&ceoid=23335008&key=TAPESTRY&lastPage=/confluence/display/TAPESTRY/Page+And+Component+Classes&pageId=23335008>| Remove
> Diagram<https://cwiki.apache.org/confluence/spaces/gliffy/removediagram.action?name=Class+Loaders&ceoid=23335008&key=TAPESTRY&lastPage=/confluence/display/TAPESTRY/Page+And+Component+Classes&pageId=23335008&input=true>  [image:
> A Gliffy Diagram named: Class Loaders]
>
> In a Tapestry application, most application classes are loaded from the
> middle class loader. Additional class loaders are used
> to support live service reloading, and live component reloading (along with
> component class transformation).
>
> 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.
>
> 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).
>
> Just be sure to put the interface class in a non-controlled package, such
> as your application's *root-package* (and *not* *root-package*.pages).
> Which is better, using magic method names (i.e., beginRender()) or
> annotations (i.e. BeginRender)?
>
> 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.
>
> 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.
>
> The main disadvantage of the method naming conventions is that the method
> names are not meaningful. onSuccessFromLoginForm() is a less meaningful
> name than storeUserCredentialsAndReturnToProductsPage(), for example.
>
> The second disadvantage is you are more susceptible to off-by-a-character
> errors. For example, onSucessFromLoginForm() will *never* be called
> because the event name is misspelled; this would not happen using the
> annotation approach:
>
>   @OnEvent(value=EventConstants.SUCCESS, component="loginForm")
>   Object storeUserCredentialsAndReturnToProductsPage()
>   {
>     . . .
>   }
>
>  The compiler will catch a misspelling of the constant SUCCESS. Likewise,
> local constants can be defined for key components, such as "loginForm".
> 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.
> Why do I have to inject a page? Why can't I just create one using new?
>
> 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.
>
> ____
>
> Footnotes  Reference Notes    1
> <https://cwiki.apache.org/confluence#FootnoteMarker1>  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.
>
> Forms and Form Components What is the t:formdata hidden field for?
>
> 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).
>
> Along the way, the Form is generating unique form control names for each
> field component, as it renders.
>
> 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.
>
> That's where t:formdata comes in. While components are rendering, they are
> using the FormSupport environmental object to record callbacks:
> *FormSupport.java (partial)*
>
> public interface FormSupport extends ClientElement
> {
>     /**
>      * Stores an action for execution during a later request.  If the action contains any mutable state, it should be in
>      * its final state before invoking this method and its internal state should not be changed subsequently.
>      */
>     <T> void store(T component, ComponentAction<T> action);
>
>     /**
>      * As with {@link #store(Object, org.apache.tapestry5.ComponentAction)}}, but the action is also invoked
>      * immediately. This is useful for 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)
>      */
>     <T> void storeAndExecute(T component, ComponentAction<T> action);
>
>  The ComponentAction objects are the callbacks. t:formdata is simply an
> object stream of these callbacks, compressed and encoded in Base64. When
> using Ajax, you may see multiple t:formdata hidden fields (they are
> processed one after another).
> How do I change the label for a field on the fly?
>
> Tapestry tries to be smart about generating the label string for a field.
> It has some smart default logic, first checking for the *component-id*
> -label in the container's message catalog, then ultimately converting the
> component's id into a user-presentable label.
>
> You can override the label in two ways:
>
> First, you can supply a body to the Label component:
>
>   <t:label for="username">${usernameLabel}</t:label>
>   <t:textfield t:id="username"/>
>
>  Here, the component class must provide a usernameLabel property. That
> property becomes the text of the label. An implementation of the property
> might look something like:
>
>   public String getUsernameLabel()
>   {
>     return systemPreferences.useEmailAddressForUserName() ? "Email address" : "User name";
>   }
>
>  However, if there are any validations on the field, the error message
> will include the default label (as discussed above).
>
> To uniformly update the label both on the page, and in any validation
> messages, bind the TextField's label parameter:
>
>   <t:label for="username"/>
>   <t:textfield t:id="username" label="prop:usernameLabel"/>
>
>  The "prop:" prefix identifies that "usernameLabel" is to be interpreted
> as a property expression (normally, the binding for the label 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.
> Link Components How do I add query parameters to a PageLink or ActionLink?
>
> These components do not have parameters to allow you to specify query
> parameters for the link; they both allow you to specify a *context* (one
> or more values to encode into the request path).
>
> 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 <a> tag:
>
> <a href="${profilePageLink}">Display Profile (w/ full details)</a>
>
>  In the matching Java class, you can create the Link programmatically:
>
>   @Inject
>   private PageRenderLinkSource linkSource;
>
>   public Link getProfilePageLink()
>   {
>     Link link = linkSource.createPageRenderLinkWithContext(DisplayProfile.class, user);
>
>     link.addParameterValue("detail", true);
>
>     return link;
>   }
>
>  ... and in the DisplayProfile page:
>
> public class DisplayProfile
> {
>   void onActivate(@RequestParameter("detail") boolean detail)
>   {
>     . . .
>   }
> }
>
>  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).
>
> 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 createEventLink().
> Javascript Why do i get "Tapestry is undefined" error on form submit?
>
> This client-side error is clear but can be awkward to solve, it means your
> browser has not been able to load tapestry.js file properly. The question is
> 'Why' ? It can be due to multiple reasons, some of them below:
>
>    - First, check if 'tapestry.js' is present in the head par of your
>    resulting HTML page.
>    - If you have set the tapestry.combine-scripts<http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/SymbolConstants.html#COMBINE_SCRIPTS>configuration symbol to true, Tapestry generates one single URL to retrieve
>    all the JS files. Sometimes, this can produce long URL that browsers are not
>    able to retrieve.
>    - If you have included jQuery in conjunction with Tapestry prototype,
>    that should generate conflict with prototype's '$' selector. In this case, i
>    encourage you to put jQuery on top of the stack and turn on the
>    jQuery.noConflict <http://api.jquery.com/jQuery.noConflict/> mode
>    - Also, if you have included a custom or third-party JS library on top
>    of the stack that causes the Javascript parsing to fail, then check the
>    javascript syntax in those script
>    - If you have used a tool to minimize your javascript libraries, this
>    can lead to javascript syntax errors, so check if it works with all the
>    javascript files unpacked.
>
> Ajax Components Do I have to specify both id and t:id for Zone components?
>
> The examples for the Zone component (in the Component Reference)
> consistently specify both id and t:id and this is probably a good idea.
>
> Generally speaking, if you don't specify the client-side id (the idattribute), it will be the same as the Tapestry component id (
> t:id).
>
> 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.
>
> The point is, to be sure, specify the exact client id. This will be the
> value for the zone parameter of the triggering component (such as a Form,
> PageLink, ActionLink, etc.).
> How do update the content of a Zone from an event handler method?
>
> 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 <div> element.
>
> Where does that content come from? You inject it into your page.
>
> <t:zone id="search" t:id="searchZone">
>   <t:form t:id="searchForm" zone="searchZone">
>     <t:textfield t:id="query" size="20"/>
>     <input type="submit" value="Search"/>
>   </t:form>
> </t:zone>
>
> <t:block id="searchResults">
>   <ul>
>     <li t:type="loop" source="searchHits" value="searchHit">${searchHit}</li>
>   </ul>
> </t:block>
>
>    @Inject
>   private Block searchResults;
>
>   Object onSuccessFromSearchForm()
>   {
>     searchHits = searchService.performSearch(query);
>
>     return searchResults;
>   }
>
>  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
> <div> is replaced with the list of hits.
>
> 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 <t:block>,
> instead you can use @InjectComponent to inject the Zone object itself, and
> return the Zone's body:
>
>   @InjectComponent
>   private Zone statusZone;
>
>   Object onActionFromUpdateStatus()
>   {
>     return statusZone.getBody();
>   }
>
>  How to I update multiple zones in a single event handler?
>
> 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.
>
> From the event handler method, instead of returning a Block or a Component,
> return a multi-zone update:
>
>   @Inject
>   private Block searchResults;
>
>   @Inject
>   private Block statusBlock;
>
>   Object onSuccessFromSearchForm()
>   {
>     searchHits = searchService.performSearch(query);
>
>     message = String.format("Found %,d matching documents", searchHits.size());
>
>     return new MultiZoneUpdate("results", searchResults).add("status", statusBlock);
>   }
>
>  What's that weird number in the middle of the client ids after a Zone is
> updated?
>
> You might start with markup in your template for a component such as a
> TextField:
>
>   <t:textfield t:id="firstName"/>
>
>  When the component initially renders as part of a full page render, you
> get a sensible bit of markup:
>
>   <input id="firstName" name="firstName" type="text">
>
>  But when the form is inside a Zone and rendered as part of a zone update,
> the ids get weird:
>
>    <input id="firstName_12a820cc40e" name="firstName" type="text">
>
>  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 id is
> expected to be unique; most JavaScript is keyed off of the id field, for
> instance.
>
> In a full page render, components don't just use their component id (t:id)
> as their client id; instead they use the JavaScriptSupport environmental
> to allocate a unique id. When there's no loops or conflicts, the client id
> matches the component id.
>
> When the component is inside a loop, a suffix is appended: firstName,
> firstName_0, firstName_1, etc.
>
> 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.
>
> 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.
> Injection
>
> Main article: Injection<https://cwiki.apache.org/confluence/display/TAPESTRY/Injection>
> What's the difference between the Component and InjectComponentannotations?
>
> The Component annotation is used to define the *type* of component, and
> its parameter bindings. When using Component, the template must not define
> the type, and any parameter bindings are merged in:
>
>   <a t:id="home" class="nav">Back to home</a>
>
>    @Component(parameters={ "page=index" })
>   private PageLink home;
>
>  Here the type of component is defined by the field type. The field name
> is matched against the t:id in the template. The page parameter is set in
> the Java class, and the informal class parameter is set in the template.
> If the tag in the template was <t:pagelink>, or if the template tag
> included the attribute t:type="pagelink", then you would see an exception.
>
> By contrast, InjectComponent expects the component to be already defined,
> and doesn't allow any configuration of it:
>
>   <t:form t:id="login"> .... </t:form>
>
>    @InjectComponent
>   private Form login;
>
>  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.
> What's the difference between the InjectPage and InjectContainerannotations?
>
> The InjectPage 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:
>
>   @InjectPage
>   private ConfirmRegistration confirmRegistration;
>
>   Object onSuccessFromRegistrationForm()
>   {
>     confirmRegistration.setStatus("Registration accepted");
>     confirmRegistration.setValidationCode(userRegistrationData.getValidationCode());
>
>     return confirmRegistration;
>   }
>
>  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.
>
> InjectContainer 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.
>
> In a mixin, it injects the component to which the mixin is attached.
> I get an exception because I have two services with the same interface, how
> do I handle this?
>
> 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:
>
> 	@Inject
> 	private ComponentEventResultProcessor processor;
>
>  Which results in the error: *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.*
>
> 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:
>
> 	@InjectService("ComponentEventResultProcessor")
> 	private ComponentEventResultProcessor processor;
>
>  This works ... but it is clumsy. If the service id,
> "ComponentEventResultProcessor", ever changes, this code will break. It's
> not *refactoring safe*.
>
> Instead, we should use marker annotations. If we look at TapestryModule,
> where the ComponentEventResultProcessor service is defined, we'll see it
> identifies the necessary markers:
>
>     @Marker(
>     { Primary.class, Traditional.class })
>     public ComponentEventResultProcessor buildComponentEventResultProcessor(
>             Map<Class, ComponentEventResultProcessor> configuration)
>     {
>         return constructComponentEventResultProcessor(configuration);
>     }
>
>  When a service has marker annotations, the annotations present at the *point
> of injection* (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.
>
>     @Inject
> 	@Traditional @Primary
> 	private ComponentEventResultProcessor processor;
>
>  The two marker annotations, Traditional and Primary, ensure that only a
> single service matches.
> What's the difference between Inject and Environmental?
>
> Inject 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.
>
> Environmental is different; it exposes a request-scoped, dynamically bound
> value  1 <https://cwiki.apache.org/confluence#Footnote1> .
>
>    - Request scoped: different threads (processing different requests)
>    will see different values when reading the field.
>    - Dynamically bound: the value is explicitly placed into the
>    Environment, and can be overridden at any time.
>
> 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 FormSupport object into the environment. Other
> components, such as TextField, use the FormSupport 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
> FormSupport is the conduit that connects them.
> I use @Inject on a field to inject a service, but the field is still null,
> what happened?
>
> 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.
> ------------------------------
>
> Footnotes  Reference Notes    1
> <https://cwiki.apache.org/confluence#FootnoteMarker1>  . 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!
>
> Tapestry Inversion of Control Container
>
> Main article: Tapestry IoC<https://cwiki.apache.org/confluence/display/TAPESTRY/IoC>
> Why do I need to define an interface for my services? Why can't I just use
> the class itself?
>
> First of all: you can do exactly this, but you lose some of the
> functionality that Tapestry's IoC container provides.
>
> 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 *proxies*: Java classes that implement the service interface. The
> methods of the proxy will ultimately invoke the methods of your service
> implementation.
>
> One of the primary purposes for proxies is to encapsulate the service's
> life cycle: most services are singletons that are created *just in time*.
> 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.
>
> 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.
>
> 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.
> My service starts a thread; how do I know when the application is shutting
> down, to stop that thread?
>
> 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 adding some post-injection logic to your
> implementation class.
>
> public class MyServiceImpl implements MyService, RegistryShutdownListener
> {
>   private boolean shuttingDown;
>
>   private final Thread workerThread;
>
>   public MyServiceImpl()
>   {
>     workerThread = new Thread(. . .);
>   }
>
>   . . .
>
>   @PostInjection
>   public void startupService(RegistryShutdownHub shutdownHub)
>   {
>     shutdownHub.addRegistryShutdownListener(this);
>   }
>
>   public void registryDidShutdown()
>   {
>     shuttingDown = true;
>
>     workerThread.interrupt();
>   }
> }
>
>  After Tapestry invokes the constructor of the service implementation, and
> after it performs any field injections, it invokes post injection methods.
> The methods must be public and return void. Parameters to a post injection
> method represent further injections ... in the above example, the
> RegistryShutdownHub is injected into the PostInjection method, since it is
> only used inside that one method.
> It is *not* recommended that MyServiceImpl take RegistryShutdownHub as a
> constructor parameter and register itself as a listener inside the
> constructor. Doing so is an example of unsafe publishing<http://www.ibm.com/developerworks/java/library/j-jtp0618.html>,
> a remote but potential thread safety issue.
>
> This same technique will work for any kind of resource that must be cleaned
> up or destroyed when the registry shuts down.
> Be careful not to invoke methods on any service proxy objects as they will
> also be shutting down with the Registry. A RegistryShutdownListener should
> not be reliant on anything outside of itself.
> Integration with existing applications
>
> 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.
> How do I make a form on a JSP submit into Tapestry?
>
> 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.
>
> 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.
>
> 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
> *root-package*.pages 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 com.example.myapp.pages.LoginForm; the page name
> will be loginform  1 <https://cwiki.apache.org/confluence#Footnote1> , and
> the URL will be /loginform.
>
> <form method="post" action="/loginform">
>
>   <input type="text" value="userName"/>
>   <br/>
>   <input type="password" value="password"/>
>   <br/>
>   <input type="submit" value="Login"/>
>
> </form>
>
>  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:
>
> public class LoginForm
> {
>   void onActivate(@RequestParameter("userName") String userName, @RequestParameter("password") String password)
>   {
>      // Validate and store credentials, etc.  }
> }
>
>  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.
> How do I share information between a JSP application and the Tapestry
> application?
>
> 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.
>
> On the Tapestry side, it is very easy to read and write session attributes:
>
> public class ShowSearchResults
> {
>   @SessionAttribute
>   private SearchResults searchResults;
> }
>
>  Reading the instance variable searchResults is instrumented to instead
> read the corresponding HttpSession attribute named "searchResults". You can
> also specify the value attribute of the SessionAttribute annotation to
> override the default attribute name.
>
> Writing to the field causes the corresponding HttpSession attribute to be
> modified.
>
> The session is automatically created as needed.
> ------------------------------
>
> Footnotes  Reference Notes    1
> <https://cwiki.apache.org/confluence#FootnoteMarker1>  Tapestry is case
> insensitive, so LoginForm would work just as well.
>
> Specific Errors Why do I get the exception "No service implements the
> interface org.apache.tapestry5.internal.InternalComponentResources" when
> trying to use the BeanEditForm component?
>
> 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.
>
> Only component classes should go in the Tapestry-controlled packages (
> pages, components, mixins and base under your application's root package).
> By convention, simple data objects should go in a data package, and
> Hibernate entities should go in an entities package.
> I get an error about "Page did not generate any markup when rendered." but
> I have a template, what happened?
>
> 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.
>
> 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.
>
> 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 jar 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.
> Limitations How do I add new components to an existing page dynamically?
>
> The short answer here is: *you don't*. The long answer here is *you don't
> have to, to get the behavior you desire*.
>
> 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.
>
> Although you code Tapestry pages and components as if they were ordinary
> POJOs  1 <https://cwiki.apache.org/confluence#Footnote1> , 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.
>
> What this means is that *any* incoming request must be handled by a *single
> page instance*. Therefore, Tapestry enforces the concept of *static
> structure, dynamic behavior*.
>
> 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.
> Why doesn't my service implementation reload when I change it?
>
> Live service reloading has some limitations:
>
>    - The service must define a service interface.
>    - The service implementation must be on the file system (not inside a
>    JAR).
>    - The implementation must be instantiated by Tapestry, not inside code
>    (even code inside a module class).
>    - The service must use the default scope<https://cwiki.apache.org/confluence/display/TAPESTRY/Defining+Tapestry+IOC+Services#DefiningTapestryIOCServices-ServiceScope>(reloading of perthread scopes is not supported).
>
> Consider the following example module:
>
> public static void bind(ServiceBinder binder)
> {
>   binder.bind(ArchiveService.class, ArchiveServiceImpl.class);
> }
> public static JobQueue buildJobQueue(MessageService messageService, Map<String,Job> configuration)
> {
>   JobQueueImpl service = new JobQueueImpl(configuration);
>
>   messageService.addQueueListener(service);
>
>   return service;
> }
>
>  ArchiveService is reloadable, because Tapestry instantiates
> ArchiveServiceImpl itself. On the other hand, Tapestry invokes
> buildJobQueue() and it is your code inside the method that instantiates
> JobQueueImpl, so the JobQueue service will not be reloadable.
>
> 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.
> ------------------------------
>
> Footnotes  Reference Notes    1
> <https://cwiki.apache.org/confluence#FootnoteMarker1>  Plain Old Java
> Object. Tapestry does not require you to extend any base classes or
> implement any special interfaces.
>
> Hibernate Support
>
> Main article: Hibernate<https://cwiki.apache.org/confluence/display/TAPESTRY/Hibernate>
> How do I get Hibernate to startup up when the application starts up, rather
> than lazily with the first request for the application?
>
> This was a minor problem in 5.0; by 5.1 it is just a matter of overriding
> the configuration system tapestry.hibernate-early-startup to "true".
> Maven Support Why do Maven project names and other details show up in my
> pages?
>
> Tapestry and maven both use the same syntax for dynamic portions of files:
> the ${...} syntax. When Maven is copying resources from src/main/resources,
> and when filtering is *enabled* (which is not the default), then any
> expansions in *Tapestry templates* that match against Maven project
> properties are substituted. If you look at the deployed application you'll
> see that ${name} is gone, replaced with your project's name!
>
> The solution is to update your pom.xml and ignore any .tml files when
> copying and filtering:
> *pom.xml (partial)*
>
>   <resource>
>     <directory>src/main/resources</directory>
>     <excludes>
>       <exclude>**/*.tml</exclude>
>     </excludes>
>     <filtering>true</filtering>
>   </resource>
>
>   <resource>
>     <directory>src/main/resources</directory>
>     <includes>
>       <include>**/*.tml</include>
>     </includes>
>     <filtering>false</filtering>
>   </resource>
>
>   Change Notification Preferences<https://cwiki.apache.org/confluence/users/viewnotifications.action>
> View Online<https://cwiki.apache.org/confluence/display/TAPESTRY/Frequently+Asked+Questions>| View
> Changes<https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=23334884&revisedVersion=32&originalVersion=31>
>



-- 
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to learn
how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

Re: [CONF] Apache Tapestry > Frequently Asked Questions

Posted by Bob Harner <bo...@gmail.com>.
Happy to help out. Hopefully we're making a dent in the doc shortcomings
Tapestry critics always mention. I believe so, anyway.

On Dec 16, 2010 7:41 PM, "Howard Lewis Ship" <hl...@gmail.com> wrote:
>
> Thanks for the continued effort on the Tapestry documentation!
>
> Make sure to add yourself as a contributor as well.
>
> On Mon, Dec 13, 2010 at 4:23 PM, Bob Harner <bo...@gmail.com> wrote:
>
> > My suggestion would be to both have and eat your cake:  Have the main
> > FAQ page be just a "table of contents" type page, with links to all of
> > the separate child pages that are now "included" in the overly-large
> > version we have now.  Then, somewhere near the top of main FAQ page,
> > have a link to a new  "All FAQs In One Page" page which would just be
> > a bunch of {include} statements like we have now on the main page.
> >
> > On Mon, Dec 13, 2010 at 12:40 PM, Howard Lewis Ship <hl...@gmail.com>
> > wrote:
> > > I'm beginning to think about splitting this into multiple pages, using
> > the
> > > same structure as the Tapestry Tutorial.
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> > For additional commands, e-mail: dev-help@tapestry.apache.org
> >
> >
>
>
> --
> Howard M. Lewis Ship
>
> Creator of Apache Tapestry
>
> The source for Tapestry training, mentoring and support. Contact me to
learn
> how I can get you up and productive in Tapestry fast!
>
> (971) 678-5210
> http://howardlewisship.com

Re: [CONF] Apache Tapestry > Frequently Asked Questions

Posted by Howard Lewis Ship <hl...@gmail.com>.
Thanks for the continued effort on the Tapestry documentation!

Make sure to add yourself as a contributor as well.

On Mon, Dec 13, 2010 at 4:23 PM, Bob Harner <bo...@gmail.com> wrote:

> My suggestion would be to both have and eat your cake:  Have the main
> FAQ page be just a "table of contents" type page, with links to all of
> the separate child pages that are now "included" in the overly-large
> version we have now.  Then, somewhere near the top of main FAQ page,
> have a link to a new  "All FAQs In One Page" page which would just be
> a bunch of {include} statements like we have now on the main page.
>
> On Mon, Dec 13, 2010 at 12:40 PM, Howard Lewis Ship <hl...@gmail.com>
> wrote:
> > I'm beginning to think about splitting this into multiple pages, using
> the
> > same structure as the Tapestry Tutorial.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: dev-help@tapestry.apache.org
>
>


-- 
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to learn
how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

Re: [CONF] Apache Tapestry > Frequently Asked Questions

Posted by Howard Lewis Ship <hl...@gmail.com>.
What I'd really like would be a Confluence macro that can show a TOC that
includes child pages.

On Mon, Dec 13, 2010 at 4:23 PM, Bob Harner <bo...@gmail.com> wrote:

> My suggestion would be to both have and eat your cake:  Have the main
> FAQ page be just a "table of contents" type page, with links to all of
> the separate child pages that are now "included" in the overly-large
> version we have now.  Then, somewhere near the top of main FAQ page,
> have a link to a new  "All FAQs In One Page" page which would just be
> a bunch of {include} statements like we have now on the main page.
>
> On Mon, Dec 13, 2010 at 12:40 PM, Howard Lewis Ship <hl...@gmail.com>
> wrote:
> > I'm beginning to think about splitting this into multiple pages, using
> the
> > same structure as the Tapestry Tutorial.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: dev-help@tapestry.apache.org
>
>


-- 
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to learn
how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

Re: [CONF] Apache Tapestry > Frequently Asked Questions

Posted by Bob Harner <bo...@gmail.com>.
My suggestion would be to both have and eat your cake:  Have the main
FAQ page be just a "table of contents" type page, with links to all of
the separate child pages that are now "included" in the overly-large
version we have now.  Then, somewhere near the top of main FAQ page,
have a link to a new  "All FAQs In One Page" page which would just be
a bunch of {include} statements like we have now on the main page.

On Mon, Dec 13, 2010 at 12:40 PM, Howard Lewis Ship <hl...@gmail.com> wrote:
> I'm beginning to think about splitting this into multiple pages, using the
> same structure as the Tapestry Tutorial.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org