Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: scrollbar

A component class is the class associated with a page, component or mixin in your Tapestry web application. Classes for pages, components and mixins are all created in an identical way. They are pure POJOs (Plain Old Java Objects), typically with annotations and conventionally named methods. They are not abstract, nor do they need to extend base classes or implement interfaces.

Div
stylefloat:right
titleRelated Articles
classaui-label
Content by Label
showLabelsfalse
showSpacefalse
titleRelated Articles
cqllabel in ("component-classes","components") and space = currentSpace()

In most cases, each component class will have a corresponding component template. However, it is also possible for a component class to emit all of its markup itself, without using a template.

...

Here's a minimal component that outputs a fixed message, using a template with a matching file name:

Section
Column
Code Block
languagejava
titleHelloWorld.java
package org.example.myapp.components;
public class HelloWorld
{
}
Column
Code Block
languagexml
titleHelloWorld.tml
<html>
    Bonjour from HelloWorld component.
</html>

In the example above, the HelloWorld class contains no code at all (except what it inherits from the Object class and what Tapestry adds invisibly).

And here's a component that does the same thing, but without needing a template:

Code Block
languagejava
titleHelloWorld.java -- without a template
package org.example.myapp.components;

import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.BeginRender;

public class HelloWorld
{
    @BeginRender
    void renderMessage(MarkupWriter writer)
    {
        writer.write("Bonjour from HelloWorld component.");
    }
}

In this example, just like the first one, the component's only job is to write out a fixed message. The @BeginRender annotation is a type of render phase annotation

, a method annotation that instructs Tapestry when and under what circumstances to invoke methods of your class.

...

In addition, it is common for an application to have base classes, often abstract base classes, that should not be directly referenced. These should not go in the pages, components or mixins packages, because they then look like valid pages, components or mixins. Instead, use the root.base package to store such base classes.

Warning

Only component classes should go in any of these controlled packages; classes representing data, or interfaces, or anything that isn't precisely a component class, must go elsewhere. Any top-level class in any of the controlled packages will be transformed at runtime. The only exception is inner classes (anonymous or not), which are loaded by the same class loader as the component class loader, but not transformed as components.

Sub-Folders / Sub-Packages

...

In previous versions of Tapestry there was also the concept of a start page configured with the tapestry.start-page-name configuration symbol (defaults to "start"). If a page with a name as configured with that symbol exists at the root level, this page is used as the root URL. This has precedence over an existing Index page. If for example you have a page class com.example.myapp.pages.Start it will map to /.

Warning

Use of start-pages is discouraged and support for it will eventually be removed. Use an Index page instead.

Pages vs. Components

The distinction between pages and component is very, very small. The primary difference is the package name: root.pages.PageName for pages, and root.components.ComponentType for components. Conceptually, page components are simply the root component of a page's component tree.

...

Since release 5.3.2, instance variables may be protected, or package private (that is, no access modifier). Under specific circumstances they may even be public (public fields must either be final, or have the @Retain annotation).

Be aware that you will need to either provide getter and setter methods to access your classes' instance variables, or else annotate the fields with @Property.

Transient Instance Variables

Unless an instance variable is decorated with an annotation, it will be a transient instance variable. This means that its value resets to its default value at the end of reach request (when the page is detached from the request).

Note
titleAbout initialization

Never initialize an instance field to a mutable object at the point of declaration. If this is done, the instance created from that initializer becomes the default value for that field and is reused inside the component on every request. This could cause state to inadvertently be shared between different sessions in an application.

Deprecated
since5.2
For Tapestry 5.1 and earlier, in the rare event that you have a variable that can keep its value between requests and you would like to defeat that reset logic, then you can add a @[Retain|http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Retain.html] a @Retain annotation to the field. You should take care that no client-specific data is stored into such a field, since on a later request the same page _instance_ may be used for a different user. Likewise, on a later request for the _same_ client, a _different_ page instance may be used.

...

Injection of dependencies occurs at the field level, via additional annotations. At runtime, fields that contain injections become read-only.

Code Block
languagejava
@Inject // inject a resource
private ComponentResources componentResources;

@Inject // inject a block
private Block foo;

@Inject // inject an asset
@Path("context:images/top_banner.png")
private Asset banner;

@Inject // inject a service
private AjaxResponseRenderer ajaxResponseRenderer;

Parameters

Main Article: Component Parameters

...

Most fields in component classes are automatically cleared at the end of each request. However, fields may be annotated so that they retain their value across requests, using the @Persist annotation.

Anchor
Embedded_Components
Embedded_Components
Embedded Components

Components often contain other components. Components inside another component's template are called embedded components. The containing component's template will contain special elements, in the Tapestry namespace, identifying where the the embedded components go.

You can define the type of component inside template, or you can create an instance variable for the component and use the @Component annotation to define the component type and parameters.

Example:

Code Block
languagejava
package org.example.app.pages;

import org.apache.tapestry5.annotations.Component;
import org.apache.tapestry5.annotations.Property;
import org.example.app.components.Count;

public class Countdown
{
    @Component(parameters =
    { "start=5", "end=1", "value=countValue" })
    private Count count;

    @Property
    private int countValue;
}

The above defines a component whose embedded id is "count" (this id is derived from the name of the field and an element with that id must be present in the corresponding template, otherwise an error is displayed (see below)). The type of the component is org.example.app.components.Count. The start and end parameters of the Count component are bound to literal values, and the value parameter of the Count component is bound to the countValue property of the Countdown component.

...

If you define a component in the component class, and there is no corresponding element in the template, Tapestry will log an error. In the example above that would be the case if the template for the Countdown page didn't contain an element with <t:count t:id="count">.

Scrollbar