Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

Wiki Markup
{scrollbar}

Page And Component Classes

Main article: Component Classes

Contents

Table of Contents
excludeContents|Page And Component Classes
FAQ
printablefalse

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.

...

Warning

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.

...

Warning

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?

In Tapestry 5.3.1 and earlier all instance variables must be private. Starting in version 5.3.2 instance variables can also be protected or package private (that is, not public), or they can even be public if final or annotated with the deprecated @Retain.

...

Restricting the scope of fields allows Tapestry to 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 they require 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 SupportsInformalParameters annotation. Here's a hypothetical component that displays an image based on the value of a Image object (presumably, a database entity):

Code Block
controlstrue
linenumberstrue
@SupportsInformalParameters
public 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.

...

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.

...

Info

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.

...