Author: hlship
Date: Fri Feb 23 11:39:28 2007
New Revision: 511066
URL: http://svn.apache.org/viewvc?view=rev&rev=511066
Log:
Simplify action URLs for the standard case (the event type "action").
Update a bunch of out-of-date documentation.
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryConstants.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridPager.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkHandlerImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkTarget.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/dom.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/request.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryConstants.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryConstants.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryConstants.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryConstants.java
Fri Feb 23 11:39:28 2007
@@ -19,8 +19,8 @@
*/
public final class TapestryConstants
{
- /** Default client event name, used in most situations. */
- public static final String DEFAULT_EVENT = "action";
+ /** Default client event name, "action", used in most situations. */
+ public static final String ACTION_EVENT = "action";
/**
* Event triggered when a page is activated (for rendering). The component
event handler will be
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java
Fri Feb 23 11:39:28 2007
@@ -14,7 +14,7 @@
package org.apache.tapestry.corelib.components;
-import static org.apache.tapestry.TapestryConstants.DEFAULT_EVENT;
+import static org.apache.tapestry.TapestryConstants.ACTION_EVENT;
import java.util.List;
@@ -67,7 +67,7 @@
Object[] contextArray = _context == null ? new Object[0] :
_context.toArray();
- Link link = _resources.createActionLink(DEFAULT_EVENT, false,
contextArray);
+ Link link = _resources.createActionLink(ACTION_EVENT, false,
contextArray);
writer.element("a", "href", link, "id", clientId);
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java
Fri Feb 23 11:39:28 2007
@@ -202,7 +202,7 @@
String name = _pageRenderSupport.allocateClientId(_resources.getId());
Link link = _resources
- .createActionLink(TapestryConstants.DEFAULT_EVENT, true,
contextArray);
+ .createActionLink(TapestryConstants.ACTION_EVENT, true,
contextArray);
writer.element("form", "name", name, "id", name, "method", "post",
"action", link);
_resources.renderInformalParameters(writer);
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridPager.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridPager.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridPager.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridPager.java
Fri Feb 23 11:39:28 2007
@@ -124,7 +124,7 @@
return;
}
- Link link =
_resources.createActionLink(TapestryConstants.DEFAULT_EVENT, false, pageIndex);
+ Link link =
_resources.createActionLink(TapestryConstants.ACTION_EVENT, false, pageIndex);
writer.element("a", "href", link, "title",
_messages.format("goto-page", pageIndex));
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkHandlerImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkHandlerImpl.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkHandlerImpl.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkHandlerImpl.java
Fri Feb 23 11:39:28 2007
@@ -97,7 +97,7 @@
if (holder.hasValue())
return holder.get();
- element.triggerEvent(actionLinkTarget.getAction(),
invocation.getContext(), handler);
+ element.triggerEvent(actionLinkTarget.getEventType(),
invocation.getContext(), handler);
ActionResponseGenerator result = holder.get();
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkTarget.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkTarget.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkTarget.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkTarget.java
Fri Feb 23 11:39:28 2007
@@ -14,12 +14,15 @@
package org.apache.tapestry.internal.services;
+import org.apache.tapestry.TapestryConstants;
+import org.apache.tapestry.ioc.internal.util.InternalUtils;
+
/**
* It represents an invocation target for an action link.
*/
public class ActionLinkTarget implements InvocationTarget
{
- private final String _action;
+ private final String _eventType;
private final String _pageName;
@@ -27,7 +30,7 @@
public ActionLinkTarget(String action, String pageName, String
componentNestedId)
{
- _action = action;
+ _eventType = action;
_pageName = pageName;
_componentNestedId = componentNestedId;
@@ -38,18 +41,32 @@
StringBuilder builder = new StringBuilder();
builder.append(_pageName.toLowerCase());
- builder.append(".");
- // Already lower case by design.
- builder.append(_componentNestedId);
- builder.append(".");
- builder.append(_action);
+
+ boolean hasComponentId = InternalUtils.isNonBlank(_componentNestedId);
+
+ if (hasComponentId)
+ {
+
+ builder.append(".");
+ // Already lower case by design.
+ builder.append(_componentNestedId);
+ }
+
+ // If no nested component id, then must append the action; the ':' and
the action become the
+ // delimiter between the page name and the event context.
+
+ if (!hasComponentId ||
!_eventType.equals(TapestryConstants.ACTION_EVENT))
+ {
+ builder.append(":");
+ builder.append(_eventType);
+ }
return builder.toString();
}
- public String getAction()
+ public String getEventType()
{
- return _action;
+ return _eventType;
}
public String getComponentNestedId()
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
Fri Feb 23 11:39:28 2007
@@ -16,6 +16,7 @@
import java.io.IOException;
+import org.apache.tapestry.TapestryConstants;
import org.apache.tapestry.internal.InternalConstants;
import org.apache.tapestry.internal.TapestryUtils;
import org.apache.tapestry.services.ActionResponseGenerator;
@@ -42,26 +43,68 @@
{
String path = request.getPath();
- int dotx = path.indexOf('.');
-
- if (dotx < 0)
- return false;
+ String logicalPageName = null;
+ String nestedComponentId = "";
+ String eventType = TapestryConstants.ACTION_EVENT;
- // Skip the leading slash, the rest is logical page name.
+ // Will always have a dot or a colon
- String logicalPageName = path.substring(1, dotx);
-
- int slashx = path.indexOf('/', dotx + 1);
- if (slashx < 0)
- slashx = path.length();
+ int dotx = path.indexOf('.');
+ int colonx = path.indexOf(':');
- int lastDotx = path.lastIndexOf('.', slashx);
+ int contextStart = -1;
- String nestedComponentId = dotx != lastDotx ? path.substring(dotx + 1,
lastDotx) : "";
+ if (dotx > 0)
+ {
+ logicalPageName = path.substring(1, dotx);
+
+ int slashx = path.indexOf('/', dotx + 1);
+
+ // The nested id ends at the colon (if present) or
+ // the first slash (if present) or the end of the path.
+
+ if (slashx < 0)
+ {
+ slashx = path.length() ;
+ }
+ else
+ {
+ contextStart = slashx + 1;
+ }
+
+ int nestedIdEnd = slashx;
+
+ if (colonx > 0 && colonx < slashx)
+ {
+ nestedIdEnd = colonx;
+ eventType = path.substring(colonx + 1, slashx);
+ }
+
+ nestedComponentId = path.substring(dotx + 1, nestedIdEnd);
+ }
+ else if (colonx > 0)
+ {
+ // No dot, but a colon. Therefore no nested component id, but an
action name and
+ // maybe some event context.
+
+ int slashx = path.indexOf('/', colonx + 1);
+ if (slashx < 0)
+ {
+ slashx = path.length();
+ }
+ else
+ {
+ contextStart = slashx + 1;
+ }
+
+ eventType = path.substring(colonx + 1, slashx);
+ logicalPageName = path.substring(1, colonx);
+ }
- String eventType = path.substring(lastDotx + 1, slashx);
+ if (logicalPageName == null)
+ return false;
- String[] context = slashx < path.length() ?
decodeContext(path.substring(slashx + 1))
+ String[] eventContext = contextStart > 0 ?
decodeContext(path.substring(contextStart))
: _emptyString;
String activationContextValue =
request.getParameter(InternalConstants.PAGE_CONTEXT_NAME);
@@ -73,7 +116,7 @@
logicalPageName,
nestedComponentId,
eventType,
- context,
+ eventContext,
activationContext);
responseGenerator.sendClientResponse(response);
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
Fri Feb 23 11:39:28 2007
@@ -43,10 +43,12 @@
* identifies the target of the event: a component with a page
* @param context
* context information supplied by the component to be provided
back when the event
- * on the component is triggered
+ * on the component is triggered, or contains the activation
context when the
+ * invocation is for a page render request
* @param activationContext
* page activation context for the page containing the
component, supplied via a
- * passivate event to the page's root component
+ * passivate event to the page's root component (used when an
action component
+ * invocation is for a page with an activation context)
*/
public ComponentInvocation(InvocationTarget target, String[] context,
String[] activationContext)
{
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt Fri
Feb 23 11:39:28 2007
@@ -64,7 +64,7 @@
{
ApplicationStateCreator<MyState> creator = new
ApplicationStateCreator<MyState>()
{
- MyState create()
+ public MyState create()
{
return new MyState(new Date());
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/dom.apt
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/dom.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/dom.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/dom.apt Fri Feb
23 11:39:28 2007
@@ -142,6 +142,11 @@
The writef() method formats an number of arguments. It uses a
java.util.Formatter. It is a convience for formatting that ultimately
invokes write().
+* writeRaw()
+
+ The writeRaw() method writes unfiltered text into the DOM. When the DOM is
rendered to markup, the provided string is written to the
+ output stream exactly as-is. Care should be taken, as this can easily result
invalid markup, or even markup that is not well formed.
+
* comment()
Adds an XML comment. The comment delimiters will be supplied by Tapestry:
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt Fri Feb
23 11:39:28 2007
@@ -7,44 +7,71 @@
Component events are the means by which components are made aware of
behaviors by the user, such
as clicking links and submitting forms.
+ Component events are used for two purposes:
+
+ * They represent requests initiated by the user, triggered by links and
forms in the client web browser.
+ These are described more fully in {{{pagenav.html}page navigation}} and in
+ {{{request.html}requst processing}}.
+
+ * They represent flow-of-control within a request, allowing one component to
notify its container
+ about some kind of circumstance ("a form was submitted"), or to collect
some piece for data
+ from the container.
+
+ []
+
+ Often, a navigation request (originating with the user) will spawn a number
of flow-of-control
+ requests. For example, a Form component will be triggered by an action
request, and will then
+ send notification events to announce when the form submission is about to be
processed, and
+ whether it was succesful or not.
+
In Tapestry 4, you would configure a parameter of a component with the name
of a method to invoke
when a certain event occured, usually a request from the client.
This has some limitations, including the fact that only a single method
could be invoked.
- Tapestry 5 introduces the
- {{{../apidocs/org/apache/tapestry/annotations/OnEvent.html}OnEvent
annotation}} which is used
- to mark methods as <event handler methods>. As with other annotations,
these methods
- may be private or public.
-
- Rather than configure a component to invoke a particular method, you
annotate one or more
- methods to listen for events from that component.
+ Tapestry 5 introduces the concept of <event handler methods>, identified via
a naming convention, or
+ via the
+ {{{../apidocs/org/apache/tapestry/annotations/OnEvent.html}OnEvent
annotation}}. Event handler methods
+ have any visibility, even private (normally they are given package private
visibility, to support testing).
+
+ Rather than configure a component to invoke a particular method, you
identify one or more
+ methods to listen for events from that component. A single event handler
method may receive notifications from
+ many different components.
- For example, here's a portion of a page that lets the user choose a value
between 1 and 10:
+ For example, here's a portion of a page (let's call it "Chooser") that lets
the user choose a number between 1 and 10:
+---+
<p> Choose a number from 1 to 10: </p>
<p>
<t:comp type="Count" end="10" value="index">
- <t:comp id="choose" type="ActionLink" context="index">${index}</t:comp>
+ <a t:id="select" t:type="actionlink" context="index">${index}</t:comp>
</t:comp>
</p>
+---+
The ActionLink component creates an action URL.
- The URL identifies the page that contains the component, the type of event
- ("action", the default), the id of the component ("choose"), plus the
additional context value.
- A sample URL: <<<http://localhost:8080/ActionPage.action/choose/3>>>.
+ The URL identifies the page that contains the component ("chooser"), the
type of event
+ (unless it is "action", the default and most common event type),
+ the id of the component within the page ("select"), plus the additional
context value(s).
+ A sample URL: <<<http://localhost:8080/chooser.select/3>>>.
+
When there are additional context values, they are appended to the path.
+
+ This demonstrates a critical difference between Tapestry and a more
traditional, action oriented framework.
+ This URL doesn't say what happens when the link is clicked, it identifies
<which component is responsible>.
+
+ There's no simple mapping from URL to a piece of code; instead the component
sends notifications, in the form
+ of invocations of event handler methods,
+
A Java method can be invoked when the link for the component is clicked by
the user:
+---+
- @OnEvent(component = "choose")
- void choose(int value)
+ @OnEvent(component = "select")
+ void valueChosen(int value)
{
_value = value;
}
@@ -52,21 +79,21 @@
Tapestry has done two things here:
- * It has identified method choose() as the method to invoke.
+ * It has identified method valueChosen() as the method to invoke.
* It has converted the context value from a string to an integer and passed
it into the method.
[]
- In the above example, the choose() method will be invoked on <any event>
that originates
+ In the above example, the valueChosen() method will be invoked on <any
event> that originates
inn component <<<choose>>>. Since ActionLink components only emit a single
type of event, "action",
this will not be a problem.
Some components can emit more than one type of event, in which case you will
want to be more specific:
+---+
- @OnEvent(value = "action", component = "choose")
- void choose(int value)
+ @OnEvent(value = "action", component = "select")
+ void valueChosen(int value)
{
_value = value;
}
@@ -74,6 +101,12 @@
The value attribute of the OnEvent annotation is the name of the event to
match.
+ "action" is the name of the default event type; the ActionLink and Form
components each use this event type.
+ If you omit the component part of the OnEvent annotation, then you'll
recieve notifications from
+ <all> contained components, possibly including nested components (due to
event bubbling).
+
+ You should qualify exactly which component(s) you wish to recieve events
from.
+
Event Handler Method Convention Names
As an alternative to the use of annotations, you may name your events in a
specific fashion, and Tapestry will invoke your methods just as if
@@ -85,14 +118,19 @@
The previous example may be rewritten as:
+---+
- void onActionFromChoose(int value)
+ void onActionFromSelect(int value)
{
_value = value;
}
+---+
+ If you event type is named "onAny", it will receive all types of events.
This is rarely what you want!
+
+ If for some unfathomable reason you want to be notified of the same event
from multiple components in the same method, you'll need to use the OnEvent
annotation.
+
+ Note from Howard: I've found that I prefer the naming convention approach,
and reserve the annotation just for situations that don't otherwise fit.
-Context
+Event Context
The context values (the context parameter to the ActionLink component) can
be any object.
However, only a simple conversion to string occurs. This is in contrast to
Tapestry 4, which had
@@ -110,7 +148,7 @@
Alternately, an event handler method may take a parameter of type
java.lang.Object[]. This parameter
will receive the entire context array. This is useful when, for example, the
context
- is off different lengths at different times. You should use either explicit,
typed parameters or
+ is of different lengths at different times. You should use either explicit,
typed parameters or
a single parameter of type Object[].
Event Bubbling
@@ -118,76 +156,7 @@
The event will bubble up the hierarchy, until it is aborted. The event is
aborted
when an event handler method returns a non-null value.
- The value returned from an event handler method determines how Tapestry will
render a response.
-
-Event Handler Returns Types
+ For page navigation events, the value returned from an event handler method
{{{pagenav.html}determines how Tapestry will render a response}}.
- An event handler may return a number of different types:
-
- * A page component, via the
{{{../apidocs/org/apache/tapestry/annotations/InjectPage.html}InjectPage}}
annotation
-
- * A string, the <logical> name of a page (not the fully qualified class name)
-
- * <More types to be determined>
-
- []
-
- Returning a page will abort the event and direct Tapestry to render the
returned page. It's completely acceptible to invoke
- methods on the page before returning it (often to inform it about what it
should display), but remember that rendering of the page
- <<will occur in a subsequent request>>, which often requires that you store
information persistently between requests.
-
- Returning a string is much the same, except that the string is used to
locate the page to be activated. This is easy to use
- when there is no need to invoke methods on the page before returning it.
-
- <TODO: Describe differences between client-originating events and
flow-of-control events from components.>
-
-End of Action Request
-
- The default behavior at the end of an action request is to set up the page
containing
- the component to render. This is normally the page that contains the
component, but the active page
- (the page that renders the response) may be altered based on the value
returned from an component event
- handler method.
-
- <<This is very important:>> The rendering occurs in a <<new>> request. The
normal response
- to an action request is a client-side redirect to re-render the page. Thus
an action is <<two>>
- requests: one to process the action and update server-side state, and a
second request to render
- the resulting page.
-
- It is very important that you make use of
- {{{persist.html}page persistence}} to allow information from the action
request
- to survive to the next render request.
-
-Passivate and Activate Events
-
- When a link to a page is created, the page will be sent a passivate event.
The event handler method for the
- passivate event may return a single value, or a list or array of values.
- These objects will become the context portion of the URI. When a page is
later rendered, the context is extracted from the URI and
- passed to any activate event handlers. In this way, information about the
page can be encoded into URIs for the page, in a light-weight
- (and human readable) manner.
-
- This was created with the intent of handling pages that exist to view (or
perhaps to edit) a specific instance of some type; in the
- context of a CRUD application, the context is used to store the primary key
of some entity object:
-
-+---+
- public class ViewCustomer
- {
- private Customer _customer;
-
- @Inject
- private CustomerDAO _customerDAO;
- long onPassivate()
- {
- return _customer.getId();
- }
-
- void onActivate(long customerId)
- {
- _customer = _customerDAO.get(customerId);
- }
- }
-+---+
-
- Render page request URI's for this page would be created as
<<</ViewCustomer.html/1234>>>.
-
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt Fri
Feb 23 11:39:28 2007
@@ -202,7 +202,7 @@
This is a minimal approach, perhaps good enough for a prototype.
- When the user clicks a link, the action request URL will initially be
something like "http://.../productlisting/select.action/99" and the final
+ When the user clicks a link, the action request URL will initially be
something like "http://.../productlisting.select/99" and the final
render request URL will be something like "http://.../productdetails".
Notice that the product id ("99") does not appear in the render request URL.
It has some minor flaws:
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt Fri
Feb 23 11:39:28 2007
@@ -34,6 +34,12 @@
Reloading is based on package name; the packages that are reloaded are
derived from the {{{conf.html}application configuration}}.
+File System Only
+
+ Reloading of classes and other files applies only to files that are actually
on the file system, and not files
+ obtained from JAR files. This is perfect during development, where the
files in question are in your local workspace.
+ In a deployed application, you are somewhat subject to the implementation of
your servlet container or application server.
+
Class Loader Issues
Tapestry uses an extra class loader to load page and component classes.
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/request.apt
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/request.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/request.apt
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/request.apt Fri
Feb 23 11:39:28 2007
@@ -107,11 +107,18 @@
The URL identifies the name of the page, then a series of component ids (the
path from the page down to the specific component), then the name of the event
to be
triggered on the component. The remaining path elements are used as the
context for the <event> (not for the page activation, which
- does not currently apply). For example, "/griddemo.FOO.BAR.action/3" would
locate page "griddemo", then component "FOO.BAR", and trigger an event named
"action", with
+ does not currently apply). For example, "/griddemo.FOO.BAR/3" would locate
page "griddemo", then component "FOO.BAR", and trigger an event named "action"
(the default event type,
+ which is omitted from the URL), with
the context "3".
+ If the page in question has an activation context, it is supplied as an
additional query parameter on the link.
+
+ In cases where the event type is not the default, "action", it will appear
between the nested component id and the event context, preceded by a colon.
Example:
+ "/example/foo.bar:magic/99" would trigger an event of type "magic". This is
not common in the vanilla Tapestry framework, but will likely be more common
+ as Ajax features (which would not use the normal request logic) are
implemented.
+
The response from a component action request is typically, but not
universally, used to send a redirect to the client; the redirect URL is a page
render URL
- to display the response to the event.
+ to display the response to the event. This is detailed under
{{{pagenav.html}page navigation}}.
RequestGlobals Service
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt Fri Feb 23
11:39:28 2007
@@ -8,36 +8,17 @@
tapestry-core is built upon the {{{../tapestry-ioc/index.html}Tapestry IoC
Container}}.
-Changes from Tapestry 4 to Tapestry 5
-
- Tapestry 5 represents a significant advance over Tapestry 4. The goal is to
make Tapestry 5
- <significantly> easier to use than Tapestry 4 (or any other Java web
framework).
- We're keeping the <essence> of Tapestry 4, but starting with a brand new
code base designed
- to provide a stable, powerful, extensible platform for many years to come.
-
- Here's a few of the planned and implemented features:
-
- * Simplified, minimal API based on annotations
-
- * <<No>> base class requirement; components are true, pure Pojos (Plain Old
Java Objects)
-
- * Abstract classes ... gone! Classes are normal, concrete classes.
-
- * <<No>> XML descriptors for pages and components ... just the annotations.
-
- * Less configuration all around.
-
- * Automatic reloading of templates and even <Java classes>
-
- * Super-duper Ajax integration built on {{{http://dojotoolkit.org} Dojo}}
-
- * Easy & fast unit testing of individual pages or components
-
New And Of Note
Progress on Tapestry 5 is really taking off. This space lists some cool new
features that have been added
recently.
+ * The default ExceptionReport page has been improved to show details of the
incoming request,
+ and to display file content when an exception includes a location.
+
+ * Action request URLs have been shortened and simplified for the common
case. They may also include a query
+ parameter to identify the page's activation context.
+
* {{{component-parameters.html}Component Reference Documentation}},
generated via a Maven plugin, is now available.
* The return values for the "after" set of {{{guide/rendering.html}render
phase methods}} have changed: all render phase
@@ -82,6 +63,31 @@
* The @ComponentClass anntotation, seen in the earlier
{{{../screencast.html}screencasts}} has been removed.
+Changes from Tapestry 4 to Tapestry 5
+
+ Tapestry 5 represents a significant advance over Tapestry 4. The goal is to
make Tapestry 5
+ <significantly> easier to use than Tapestry 4 (or any other Java web
framework).
+ We're keeping the <essence> of Tapestry 4, but starting with a brand new
code base designed
+ to provide a stable, powerful, extensible platform for many years to come.
+
+ Here's a few of the planned and implemented features:
+
+ * Simplified, minimal API based on annotations
+
+ * <<No>> base class requirement; components are true, pure Pojos (Plain Old
Java Objects)
+
+ * Abstract classes ... gone! Classes are normal, concrete classes.
+
+ * <<No>> XML descriptors for pages and components ... just the annotations.
+
+ * Less configuration all around.
+
+ * Automatic reloading of templates and even <Java classes>
+
+ * Super-duper Ajax integration built on {{{http://dojotoolkit.org} Dojo}}
+
+ * Easy & fast unit testing of individual pages or components
+
Adaptive API
A key feature of Tapestry 5 is <adaptive API>.
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java
Fri Feb 23 11:39:28 2007
@@ -19,6 +19,7 @@
import java.io.IOException;
+import org.apache.tapestry.TapestryConstants;
import org.apache.tapestry.internal.InternalConstants;
import org.apache.tapestry.internal.test.InternalBaseTestCase;
import org.apache.tapestry.services.ActionResponseGenerator;
@@ -30,7 +31,7 @@
public class ComponentActionDispatcherTest extends InternalBaseTestCase
{
@Test
- public void no_dot_in_path() throws Exception
+ public void no_dot_or_colon_in_path() throws Exception
{
ActionLinkHandler handler = newActionLinkHandler();
Request request = newRequest();
@@ -55,38 +56,102 @@
@Test
public void event_on_page() throws Exception
{
- test("/foo/MyPage.anevent", "foo/MyPage", "", "anevent");
+ test("/foo/MyPage:anevent", "foo/MyPage", "", "anevent");
}
@Test
public void event_on_component_within_page() throws Exception
{
- test("/foo/MyPage.fred.anevent", "foo/MyPage", "fred", "anevent");
+ test("/foo/MyPage.fred:anevent", "foo/MyPage", "fred", "anevent");
+ }
+
+ @Test
+ public void default_event_with_nested_id() throws Exception
+ {
+ test("/foo/MyPage.fred", "foo/MyPage", "fred",
TapestryConstants.ACTION_EVENT);
+ }
+
+ @Test
+ public void default_event_with_nested_id_and_context() throws Exception
+ {
+ test(
+ "/foo/MyPage.fred/fee/fie/foe/fum",
+ "foo/MyPage",
+ "fred",
+ TapestryConstants.ACTION_EVENT,
+ "fee",
+ "fie",
+ "foe",
+ "fum");
+ }
+
+ @Test
+ public void default_event_with_context_that_includes_a_colon() throws
Exception
+ {
+ test(
+ "/foo/MyPage.underdog/a:b:c/d",
+ "foo/MyPage",
+ "underdog",
+ TapestryConstants.ACTION_EVENT,
+ "a:b:c",
+ "d");
}
@Test
public void event_on_nested_component_within_page() throws Exception
{
- test("/foo/MyPage.barney.fred.anevent", "foo/MyPage", "barney.fred",
"anevent");
+ test("/foo/MyPage.barney.fred:anevent", "foo/MyPage", "barney.fred",
"anevent");
}
@Test
public void page_event_with_context() throws Exception
{
- test("/foo/MyPage.trigger/foo", "foo/MyPage", "", "trigger", "foo");
+ test("/foo/MyPage:trigger/foo", "foo/MyPage", "", "trigger", "foo");
}
@Test
public void nested_component_event_with_context() throws Exception
{
test(
- "/foo/MyPage.nested.trigger/foo/bar/baz",
+ "/foo/MyPage.nested:trigger/foo/bar/baz",
"foo/MyPage",
"nested",
"trigger",
"foo",
"bar",
"baz");
+ }
+
+ @Test
+ public void page_activation_context_in_request() throws Exception
+ {
+ ActionLinkHandler handler = newActionLinkHandler();
+ Request request = newRequest();
+ Response response = newResponse();
+ ActionResponseGenerator generator =
newMock(ActionResponseGenerator.class);
+
+ train_getPath(request, "/mypage:eventname");
+
+ train_getParameter(request, InternalConstants.PAGE_CONTEXT_NAME,
"alpha/beta");
+
+ expect(
+ handler.handle(
+ eq("mypage"),
+ eq(""),
+ eq("eventname"),
+ aryEq(new String[0]),
+ aryEq(new String[]
+ { "alpha", "beta" }))).andReturn(generator);
+
+ generator.sendClientResponse(response);
+
+ replay();
+
+ Dispatcher dispatcher = new ComponentActionDispatcher(handler);
+
+ assertTrue(dispatcher.dispatch(request, response));
+
+ verify();
}
private void test(String requestPath, String logicalPageName, String
nestedComponentId,
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java
Fri Feb 23 11:39:28 2007
@@ -67,7 +67,8 @@
PAGE_LOGICAL_NAME,
"foo.bar",
"someaction",
- "/sub/mypage.foo.bar.someaction");
+ "/sub/mypage.foo.bar:someaction");
+
}
@Test
@@ -79,10 +80,38 @@
PAGE_LOGICAL_NAME,
"foo.bar",
"publish",
- "/sub/mypage.foo.bar.publish/fred/5",
+ "/sub/mypage.foo.bar:publish/fred/5",
+ "fred",
+ 5);
+ }
+
+ @Test
+ public void action_link_with_default_action()
+ {
+ testActionLink(
+ PAGE_CLASS_NAME,
+ "",
+ PAGE_LOGICAL_NAME,
+ "foo.bar",
+ TapestryConstants.ACTION_EVENT,
+ "/sub/mypage.foo.bar/fred/5",
"fred",
5);
}
+
+ @Test
+ public void page_level_event_always_includes_action()
+ {
+ testActionLink(
+ PAGE_CLASS_NAME,
+ "",
+ PAGE_LOGICAL_NAME,
+ "",
+ TapestryConstants.ACTION_EVENT,
+ "/sub/mypage:action/barney/99",
+ "barney",
+ 99);
+ }
@Test
public void action_link_named_context_no_ids()
@@ -93,7 +122,7 @@
PAGE_LOGICAL_NAME,
"foo.bar",
"someaction",
- "/fred/sub/mypage.foo.bar.someaction");
+ "/fred/sub/mypage.foo.bar:someaction");
}
@SuppressWarnings("unchecked")