Versions Compared

Key

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

Wiki Markup
{scrollbar}

Page And Component Classes

Main article: Page And Component Classes FAQ

What's the difference between a page and a component?

...

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

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?

...

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". (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.)

In addition, it is possible to define additional root packages for the application:

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

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?

...

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?

...

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

Gliffy Diagram
sizeL
nameClass 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).

...

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:

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

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?

...

On top of that, Tapestry keeps just once instance of each page in memory (since 5.2). It reworks the bytecode of the components so that a single instance can be shared across multiple request handling threads.

Wiki Markup
{scrollbar}
____

 

 

 

 

 

 

 

 

 

 

 

 

 

Footnotes Display