Hello Volunteers,
When writing the spec language for the changes to default
ActionListener, I added some test content to verify navigation into and
between flows using OutcomeTarget type renderers (h:button and h:link)
worked. Turns out it did not, and I had to add spec and impl for it.
The changes are described inline.
SECTION: API changes
--------------------
M applicationIntegration.fm
- In 7.1.1 document new requirements for default ActionListener.
- In 7.4.2.1 require pasing NULL_FLOW as the flow document id on a flow
return. This is necessary for the OutcomeTarget navigation style.
M jsf-api/doc/standard-html-renderkit-base.xml
M jsf-api/doc/standard-html-renderkit.xml
- In javax.faces.OutcomeTarget Button and Link:
* Provide for getting the navigation case to be sensitive to flows.
Obtain a reference to the NavigationCase, called navCase for
discussion. If the component has a non-null attribute named by the
value of the symbolic constant
javax.faces.event.ActionListener.TO_FLOW_DOCUMENT_ID_ATTR_NAME, let
navCase be the return from calling getNavigationCase() on the
ConfigurableNavigationHandler, passing the current FacesContext as
the first argument, null, as the second argument, outcome as the
third argument, and the value of the TO_FLOW_DOCUMENT_ID_ATTR_NAME
attribute as the fourth argument. Otherwise, let navCase be the
return from calling getNavigationCase() on the
ConfigurableNavigationHandler, passing the current FacesContext as
the first argument, null, as the second argument, and outcome as the
third argument.
* Modify "Algorithm to obtain the url to which the user-agent should
issue a GET request when clicked", which is used by all renderers of
component-family javax.faces.OutcomeTarget.
<li class="changed_added_2_2"><p>If the navigation case has a
non-null <code>toFlowDocumentId</code> property, add two
parameters as shown in this table.</p>
<table border="1">
<tr>
<th>parameter name</th>
<th>parameter value</th>
</tr>
<tr>
<td>value of FlowHandler.TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME</td>
<td>value of the <code>toFlowDocumentId</code> property
of the navigation case</td>
</tr>
<tr>
<td>value of FlowHandler.FLOW_ID_REQUEST_PARAM_NAME</td>
<td>value of the <code>fromOutcome</code> property
of the navigation case</td>
</tr>
</table>
</li>
* Document the ability to use the <f:attribute
name="to-flow-document-id"> attribute on <h:button>, <h:link>,
<h:commandButton>, <h:commandLink>.
+ <p>To support entering flows that are defined by both a defining
+ document id and a flow id, add a component attribute to this
+ component whose name is given by the value of the symbolic
+ constant
+ <code>javax.faces.event.ActionListener.TO_FLOW_DOCUMENT_ID_ATTR_NAME</code>,
+ and whose value is the defining document id. For example, when
+ using this component in a facelet page, the following markup
+ would cause such an attribute to be added.</p>
+
+<pre><code><h:commandButton id="start_a" value="enter flow-a" action="flow-a"><br />
+ <f:attribute name="to-flow-document-id" value="unique"/><br />
+</h:commandButton><br />
+</code></pre>
+
+<div class="changed_added_2_2">
+
+ <p>To support entering flows that are defined by both a defining
+ document id and a flow id, add a component attribute to this
+ component whose name is given by the value of the symbolic
+ constant
+ <code>javax.faces.event.ActionListener.TO_FLOW_DOCUMENT_ID_ATTR_NAME</code>,
+ and whose value is the defining document id. For example, when
+ using this component in a facelet page, the following markup
+ would cause such an attribute to be added.</p>
+
+<pre><code><h:commandLink id="start_a" value="enter flow-a" action="flow-a"><br />
+ <f:attribute name="to-flow-document-id" value="unique"/><br />
+</h:commandLink><br />
+</code></pre>
+
+</div>
+<div class="changed_added_2_2">
+
+ <p>To support entering flows that are defined by both a defining
+ document id and a flow id, add a component attribute to this
+ component whose name is given by the value of the symbolic
+ constant
+ <code>javax.faces.event.ActionListener.TO_FLOW_DOCUMENT_ID_ATTR_NAME</code>,
+ and whose value is the defining document id. For example, when
+ using this component in a facelet page, the following markup
+ would cause such an attribute to be added.</p>
+
+<pre><code><h:link id="start_a" value="enter flow-a" outcome="flow-a"><br />
+ <f:attribute name="to-flow-document-id" value="unique"/><br />
+</h:link><br />
+</code></pre>
+
+</div>
+ <p>To support entering flows that are defined by both a defining
+ document id and a flow id, add a component attribute to this
+ component whose name is given by the value of the symbolic
+ constant
+ <code>javax.faces.event.ActionListener.TO_FLOW_DOCUMENT_ID_ATTR_NAME</code>,
+ and whose value is the defining document id. For example, when
+ using this component in a facelet page, the following markup
+ would cause such an attribute to be added.</p>
+
+<pre><code><h:button id="start_a" value="enter flow-a" outcome="flow-a"><br />
+ <f:attribute name="to-flow-document-id" value="unique"/><br />
+</h:button><br />
+</code></pre>
+
+
M jsf-api/src/main/java/javax/faces/application/ConfigurableNavigationHandler.java
- Add variant of getNavigationCase() that takes toFlowDocumentId. The
documentation is basically the same, so I'm not calling out
specifically here.
M jsf-api/src/main/java/javax/faces/application/NavigationHandler.java
- Document variant of handleNavigation() that takes toFlowDocumentId.
The documentation is basically the same, so I'm not calling out
specifically here.
M jsf-api/src/main/java/javax/faces/lifecycle/Lifecycle.java
- Document changes to attachWindow(): added a call to
FlowHandler.clientWindowTransition(). This method is a no-op unless
we are in an OutcomeTarget navigation.
M jsf-api/src/main/java/javax/faces/flow/FlowHandler.java
- New constants
/**
* <p class="changed_added_2_2">Components that are rendered by <code>Renderers</code>
* of component-family <code>javax.faces.OutcomeTarget</code> must use this
* constant as the parameter name for a parameter representing the flow id
* of the flow that this component will cause to be entered.</p>
*
* <p class="changed_added_2_2"></p>
*
* @since 2.2
*/
public static final String FLOW_ID_REQUEST_PARAM_NAME = "jffi";
/**
* <p class="changed_added_2_2">Components that are rendered by <code>Renderers</code>
* of component-family <code>javax.faces.OutcomeTarget</code> must use this
* constant as the parameter name for a parameter representing the defining document id
* of the flow that this component will cause to be entered.</p>
*
* @since 2.2
*/
public static final String TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME = "jftfdi";
/**
* <p class="changed_added_2_2">Components that are rendered by <code>Renderers</code>
* of component-family <code>javax.faces.OutcomeTarget</code> must use this
* constant as the value of the parameter named by {_at_link #TO_FLOW_DOCUMENT_ID_REQUEST_PARM_NAME}
* when returning from a flow (without entering another flow) using such a component. </p>
* @since 2.2
*/
public static final String NULL_FLOW = "javax.faces.flow.NullFlow";
- Document existing getCurrentFlow().
- New method clientWindowTransition()
* <p class="changed_added_2_2">Allow for flow transitions in the
* case of components rendered by the renderers from
* component-family <code>javax.faces.OutcomeTarget</code>. These
* transitions must happen at the front of the request processing
* lifecycle due to the HTTP GET based nature of such components.
* Therefore, this method is called from {_at_link
* javax.faces.lifecycle.Lifecycle#attachWindow}.</p>
* <div class="changed_added_2_2">
* <p>Let <em>flowId</em> be the value in the request parameter map
* for the parameter whose name is given by the value of {_at_link
* #FLOW_ID_REQUEST_PARAM_NAME}. Let <em>toFlowDocumentId</em> be
* the value in the request parameter map for the paramater whose
* name is given by the value of {_at_link
* #TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME}. If
* <em>toFlowDocumentId</em> is <code>null</code>, take no action
* and return. Otherwise, let <em>sourceFlow</em> be the return
* from {_at_link #getCurrentFlow(javax.faces.context.FacesContext)}. A
* <code>null</code> value indicates there is no current flow, which
* will be the case if this navigation is trying to enter a flow. If
* <em>flowId</em> is not <code>null</code> and
* <em>toFlowDocumentId</em> is <strong>not</strong> equal to the
* value of {_at_link #NULL_FLOW}, let <em>targetFlow</em> be the
* result of calling {_at_link
* #getFlow(javax.faces.context.FacesContext, java.lang.String,
* java.lang.String)}, passing <em>toFlowDocumentId</em> and
* <em>flowId</em> as the last two arguments, respectively. If the
* result is non-<code>null</code>, let <em>flowCallNode</em> be the
* return from calling {_at_link #getFlowCall} on the
* <em>sourceFlow</em>, passing <em>targetFlow</em> as the argument.
* Otherwise, <em>targetFlow</em> and <em>flowCallNode</em> must
* remain <code>null</code>, indicating that this is a flow
* return.</p>
* <p>Call, {_at_link #transition}, passing the arguments gathered in
* the preceding algorithm.</p>
*
* </div>
* @since 2.2
*
* @param context the {_at_code FacesContext} for the current request.
* @throws NullPointerException if {_at_code context} is {_at_code null}.
*/
public abstract void clientWindowTransition(FacesContext context);
M jsf-api/src/main/java/javax/faces/event/ActionListener.java
- add constant for attribute name
+
+ /**
+ * <p class="changed_added_2_2">The presence of this component attribute
+ * on an {_at_link javax.faces.component.ActionSource} component will cause
+ * the default {_at_code ActionListener} to interpret the value of the
+ * attribute as the </p>
+ *
+ */
+ public static final String TO_FLOW_DOCUMENT_ID_ATTR_NAME = "to-flow-document-id";
SECTION: Modified Files
----------------------------
M jsf-ri/conf/share/tlddoc-resources/stylesheet.css
- Provenance of changes
M jsf-ri/src/main/java/com/sun/faces/renderkit/html_basic/OutcomeTargetRenderer.java
- Implement renderer changes.
M jsf-ri/src/main/java/com/sun/faces/lifecycle/LifecycleImpl.java
- Call clientWindowTransition() from attachWindow().
M jsf-ri/src/main/java/com/sun/faces/application/ActionListenerImpl.java
- Use the constant instead of a literal string for the toFlowDocumentId.
M jsf-ri/src/main/java/com/sun/faces/application/resource/FaceletWebappResourceHelper.java
- Use the variant of getCurrentFlow() that takes FacesContext, if you
have one handy.
M jsf-ri/src/main/java/com/sun/faces/application/NavigationHandlerImpl.java
- Implement new overloaded getNavigationCase().
- Use the variant of getCurrentFlow() that takes FacesContext, if you
have one handy.
M jsf-ri/src/main/java/com/sun/faces/flow/builder/MutableNavigationCase.java
- Revert previously committed revision. Turns out it was not needed.
M jsf-ri/src/main/java/com/sun/faces/flow/FlowHandlerImpl.java
- Implement clientWindowTransition().
M test/web-profile/flow/basic_faces_flow_call/src/test/java/com/sun/faces/test/webprofile/flow/basic_faces_flow_call/FlowACallsFlowBIT.java
M test/web-profile/flow/basic_faces_flow_call/src/main/java/com/sun/faces/test/webprofile/flow/basic/FlowA.java
M test/web-profile/flow/basic_faces_flow_call/src/main/java/com/sun/faces/test/webprofile/flow/basic/Flow_a_Bean.java
M test/web-profile/flow/basic_faces_flow_call/src/main/webapp/index.xhtml
M test/web-profile/flow/basic_faces_flow_call/src/main/webapp/flow-a/next_b.xhtml
M test/web-profile/flow/basic_faces_flow_call/src/main/webapp/flow-b/flow-b-flow.xml
M test/web-profile/flow/basic_faces_flow_call/src/main/webapp/flow-b/next_b.xhtml
- New test content.
--