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 | ||||
---|---|---|---|---|
| ||||
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 | ||||
---|---|---|---|---|
| ||||
@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 | ||||
---|---|---|---|---|
|
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 | ||||
---|---|---|---|---|
| ||||
@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 |
---|