doc polish

This commit is contained in:
Keith Donald
2008-04-28 21:31:11 +00:00
parent d7a4a127c4
commit 16aee2d587
6 changed files with 85 additions and 108 deletions

View File

@@ -197,6 +197,15 @@
<evaluate expression="bookingValidator.validate(booking, messageContext)" />]]>
</programlisting>
</sect2>
<sect2 id="el-variable-resourceBundle">
<title>resourceBundle</title>
<para>
Use <code>resourceBundle</code> to access a message resource.
</para>
<programlisting type="xml"><![CDATA[
<set name="flashScope.successMessage" value="resourceBundle.successMessage" />]]>
</programlisting>
</sect2>
<sect2 id="el-variable-requestContext">
<title>flowRequestContext</title>
<para>

View File

@@ -4,29 +4,24 @@
<sect1 id="spring-js-introduction">
<title>Introduction</title>
<para>
Spring Javascript is intended to be a lightweight wrapper around common JavaScript toolkits such as Dojo. It
aims to provide a common client-side programming model for progressively enhancing a web page with rich
widget behavior and Ajax remoting.
Spring Javascript (spring-js) is a lightweight abstraction over common JavaScript toolkits such as Dojo.
It aims to provide a common client-side programming model for progressively enhancing a web page with rich widget behavior and Ajax remoting.
</para>
<para>
The Spring Javascript library has been used to apply rich functionality to the Spring MVC + Spring Web Flow
version of the Spring Travel application.
Use of the Spring JS API is demonstrated in the the Spring MVC + Web Flow version of the Spring Travel reference application.
In addition, the JSF components provided as part of the Spring Faces library build in Spring.js.
</para>
</sect1>
<sect1 id="spring-js-includes">
<title>Including Spring Javascript in a Page</title>
<para>
Spring Javascript is designed such that an implementation of its API can be built for any of the popular
Javascript toolkits. The first implementation provided is for the Dojo toolkit. (Implementations for jQuery,
Ext, Prototype and YUI will be considered in future releases.) Using Spring Javascript in a page requires
including both the underlying library as normal, the
<code>Spring.js</code>
base interface file and the
<code>Spring-(library implementation).js</code>
file for the corresponding toolkit, in this case
<code>Spring-Dojo.js</code>
. The following scripts includes are used to serve the files from the
<code>ResourceServlet</code>
Spring Javascript is designed such that an implementation of its API can be built for any of the popular Javascript toolkits.
The initial implementation provided is for the Dojo toolkit.
</para>
<para>
Using Spring Javascript in a page requires including the underlying toolkit as normal,
the <code>Spring.js</code> base interface file, and the <code>Spring-(library implementation).js</code> file for the underlying toolkit.
As an example, the following script includes obtain the Dojo implementation of Spring.js:
</para>
<programlisting language="xml"><![CDATA[
<script type="text/javascript" src="<c:url value="/resources/dojo/dojo.js" />"> </script>
@@ -34,10 +29,8 @@
<script type="text/javascript" src="<c:url value="/resources/spring/Spring-Dojo.js" />"> </script>]]>
</programlisting>
<para>
When using the widget system from an underlying library, typically you must also include some CSS resources
to obtain the desired look and feel. For the Dojo-based sample, Dojo's
<code>tundra.css</code>
is included:
When using the widget system of an underlying library, typically you must also include some CSS resources to obtain the desired look and feel.
For the Dojo-based reference application, Dojo's <code>tundra.css</code> is included:
</para>
<programlisting><![CDATA[
<link type="text/css" rel="stylesheet" href="<c:url value="/resources/dijit/themes/tundra/tundra.css" />" />]]>
@@ -46,105 +39,84 @@
<sect1 id="spring-js-decorations">
<title>Spring Javascript Decorations</title>
<para>
A central concept in Spring Javascript is the notion of applying decorations to existing DOM nodes. This
technique is used to progressively enhance a web page such that the page will still be functional in a less
capable browser. The
<code>addDecoration</code>
method is used to apply decorations. For example, to enhance a Spring MVC
<code>&lt;form:input&gt;</code>
tag with rich suggestion behavior:
A central concept in Spring Javascript is the notion of applying decorations to existing DOM nodes.
This technique is used to progressively enhance a web page such that the page will still be functional in a less capable browser.
The <code>addDecoration</code> method is used to apply decorations.
</para>
<para>
The following example illustrates enhancing a Spring MVC <code>&lt;form:input&gt;</code> tag with rich suggestion behavior:
</para>
<programlisting><![CDATA[
<form:input id="searchString" path="searchString"/>
<script type="text/javascript">
Spring.addDecoration(new Spring.ElementDecoration({
elementId : "searchString",
widgetType : "dijit.form.ValidationTextBox",
widgetAttrs : { promptMessage : "Search hotels by name, address, city, or zip." }}));
elementId: "searchString",
widgetType: "dijit.form.ValidationTextBox",
widgetAttrs: { promptMessage : "Search hotels by name, address, city, or zip." }}));
</script>]]>
</programlisting>
<para>
The
<code>ElementDecoration</code>
is used to apply rich widget behavior to an existing DOM node. This decoration type does not aim to
completely hide the underlying toolkit, so the toolkit's native widget type and widget attributes are used
directly. This approach will allow you to use this common decoration model to apply any rich widget from the
underlying toolkit in a consistent manner.
The <code>ElementDecoration</code> is used to apply rich widget behavior to an existing DOM node.
This decoration type does not aim to completely hide the underlying toolkit, so the toolkit's native widget type and attributes are used directly.
This approach allows you to use a common decoration model to integrate any widget from the underlying toolkit in a consistent manner.
See the <code>booking-mvc</code> reference application for more examples of applying decorations to do things from suggestions to client-side validation.
</para>
<para>
When using the
<code>ElementDecoration</code>
to apply widgets that have rich validation behavior, a common need is to prevent the form from being
submitted to the server until validation passes. This can be done with the
<code>ValidateAllDecoration</code>
:
When using the <code>ElementDecoration</code> to apply widgets that have rich validation behavior, a common need is to prevent the form from being submitted to the server until validation passes.
This can be done with the <code>ValidateAllDecoration</code>:
</para>
<programlisting><![CDATA[
<input type="submit" id="proceed" name="_eventId_proceed" value="Proceed" />
<script type="text/javascript">
Spring.addDecoration(new Spring.ValidateAllDecoration({elementId:'proceed', event:'onclick'}));
Spring.addDecoration(new Spring.ValidateAllDecoration({ elementId:'proceed', event:'onclick' }));
</script>]]>
</programlisting>
<para>
This decorates the "Proceed" button with a special onclick event handler that fires the client side
validators and does not allow the form to submit until they pass successfully.
This decorates the "Proceed" button with a special onclick event handler that fires the client side validators and does not allow the form to submit until they pass successfully.
</para>
<para>
An
<code>AjaxEventDecoration</code>
will apply a client-side event listener that fires a remote Ajax request to the server and installs a
callback for automatically handling the response:
An <code>AjaxEventDecoration</code> applies a client-side event listener that fires a remote Ajax request to the server. It also auto-registers a callback function to link in the response:
</para>
<programlisting><![CDATA[
<a id="prevResultsLink" href="search?searchString=${searchCriteria.searchString}&pageSize=${searchCriteria.pageSize}&
page=${searchCriteria.page - 1}">Previous Results</a>
<a id="prevResultsLink" href="search?searchString=${searchCriteria.searchString}&page=${searchCriteria.page - 1}">Previous Results</a>
<script type="text/javascript">
Spring.addDecoration(new Spring.AjaxEventDecoration({
elementId: "prevResultsLink",
event: "onclick",
params: {fragments: "body"}
Spring.addDecoration(new Spring.AjaxEventDecoration({
elementId: "prevResultsLink",
event: "onclick",
params: { fragments: "body" }
}));
</script>]]>
</programlisting>
<para>
This decorates the onclick event of the "Previous Results" link with an Ajax call, passing along a special
parameter that specifies the fragment to be re-rendered in the response. Note that this link would still be
fully functional if Javascript was unavailable in the client. (See the section on
<link linkend="spring-js-ajax">Handling Ajax Requests</link>
for details on how this request is handled on the server.)
This decorates the onclick event of the "Previous Results" link with an Ajax call, passing along a special parameter that specifies the fragment to be re-rendered in the response.
Note that this link would still be fully functional if Javascript was unavailable in the client.
(See the section on <link linkend="spring-js-ajax">Handling Ajax Requests</link> for details on how this request is handled on the server.)
</para>
<para>
Sometimes it is necessary to calling Spring Javascript's
<code>RemotingHandler</code>
directly instead of using the
<code>AjaxEventDecoration</code>
. For example, see inline
<code>onclick</code>
handler of this button:
Sometimes it is necessary to call Spring Javascript's <code>RemotingHandler</code> directly instead of using the <code>AjaxEventDecoration</code>.
For example, see inline <code>onclick</code> handler of this button:
</para>
<programlisting><![CDATA[
<input type="submit" id="proceed" name="_eventId_proceed" value="Proceed"
onclick="Spring.remoting.submitForm('proceed', 'booking', {fragments:'messages,bookingForm'}); return false;" />
onclick="Spring.remoting.submitForm('proceed', 'booking', { fragments:'messages,bookingForm' }); return false;" />
<script type="text/javascript">
Spring.addDecoration(new Spring.ValidateAllDecoration({elementId:'proceed', event:'onclick'}));
Spring.addDecoration(new Spring.ValidateAllDecoration({ elementId:'proceed', event:'onclick'} ));
</script>]]>
</programlisting>
</sect1>
<sect1 id="spring-js-ajax">
<title>Handling Ajax Requests</title>
<para>
Spring Javascript's client-side Ajax response handling is built upon the notion of receiving "fragments"
back from the server. These fragments are just standard HTML that is meant to replace portions of the
existing page. The key piece needed on the server is a way to determine which pieces of a full repsonse need
to be pulled out for partial rendering.
Spring Javascript's client-side Ajax response handling is built upon the notion of receiving "fragments" back from the server.
These fragments are just standard HTML that is meant to replace portions of the existing page.
The key piece needed on the server is a way to determine which pieces of a full response need to be pulled out for partial rendering.
</para>
<para>
In order to be able to render partial fragments of a full response, the full response must be built using a
templating technology that allows the use of composition for constructing the response, and for the member
parts of the composition to be referenced and rendered individually. Spring Javascript initially provides
some simple Spring MVC extensions that make use of Tiles to achieve this, but the same effect could
theoretically be achieved with any templating system that meets the same criteria, and more such options
will be explored in future releases.
parts of the composition to be referenced and rendered individually.
Spring Javascript provides some simple Spring MVC extensions that make use of Tiles to achieve this.
The same technique could theoretically be used with any templating system supporting composition.
</para>
<para>
Spring Javascript's Ajax remoting functionality is built upon the notion that the core handling code for an
@@ -164,40 +136,31 @@ page=${searchCriteria.page - 1}">Previous Results</a>
</bean>]]>
</programlisting>
<para>
This configures the
<code>AjaxUrlBasedViewResolver</code>
which in turn is able to interpret Ajax requests and create a
<code>FlowAjaxTilesView</code>
to handle rendering of the appropriate fragments. Note that
<code>FlowAjaxTilesView</code>
is capable of handling the rendering for both Web Flow and pure Spring MVC requests. The fragments
correspond to individual attributes of a Tiles view definition. For example, take the following Tiles
view definition:
This configures the <code>AjaxUrlBasedViewResolver</code> which in turn interprets Ajax requests and creates <code>FlowAjaxTilesView</code> objects to handle rendering of the appropriate fragments.
Note that <code>FlowAjaxTilesView</code> is capable of handling the rendering for both Web Flow and pure Spring MVC requests.
The fragments correspond to individual attributes of a Tiles view definition. For example, take the following Tiles view definition:
</para>
<programlisting><![CDATA[
<definition name="hotels/index" extends="standardLayout">
<put-attribute name="body" value="index.body" />
</definition>
<definition name="index.body" template="/WEB-INF/hotels/index.jsp">
<put-attribute name="hotelSearchForm" value="/WEB-INF/hotels/hotelSearchForm.jsp" />
<put-attribute name="bookingsTable" value="/WEB-INF/hotels/bookingsTable.jsp" />
</definition>]]>
</programlisting>
<para>
An Ajax request could specify the "body", "hotelSearchForm" or "bookingsTable" to be rendered as
fragments in the request.
An Ajax request could specify the "body", "hotelSearchForm" or "bookingsTable" to be rendered as fragments in the request.
</para>
</sect2>
<sect2 id="spring-js-ajax-mvc-webflow">
<title>Handling Ajax Requests with Spring MVC + Spring Web Flow</title>
<para>
Spring Web Flow handles the optional rendering of fragments directly in the flow definition language
through use of the
<code>render</code>
element. The benefit of this approach is that the selection of fragments is completely decoupled from
client-side code, such that no special parameters need to be passed with the request the way they
currently must be with the pure Spring MVC controller approach. For example, if you wanted to render
the "hotelSearchForm" fragment from the previous example Tiles view into a rich Javascript popup:
Spring Web Flow handles the optional rendering of fragments directly in the flow definition language through use of the <code>render</code> element.
The benefit of this approach is that the selection of fragments is completely decoupled from client-side code, such that no special parameters need to be passed with the request the way they
currently must be with the pure Spring MVC controller approach.
For example, if you wanted to render the "hotelSearchForm" fragment from the previous example Tiles view into a rich Javascript popup:
</para>
<programlisting><![CDATA[
<view-state id="changeSearchCriteria" view="enterSearchCriteria.xhtml" popup="true">

View File

@@ -176,7 +176,7 @@ public class BookingFlowHandler extends AbstractFlowHandler {
<programlisting language="xml"><![CDATA[
<!-- Enables FlowHandler URL mapping -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<constructor-arg ref="flowExecutor" />
<property name="flowExecutor" ref="flowExecutor" />
</bean>
]]>
</programlisting>
@@ -198,7 +198,7 @@ public class BookingFlowHandler extends AbstractFlowHandler {
</para>
<programlisting language="xml"><![CDATA[
<bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController">
<constructor-arg ref="flowExecutor"/>
<property name="flowExecutor" ref="flowExecutor" />
</bean>]]>
</programlisting>
<para>

View File

@@ -129,7 +129,7 @@ java org.springframework.webflow.upgrade.WebFlowUpgrader flow-to-upgrade.xml
This element replaces previous <code>FlowExecutorFactoryBean</code> bean definitions.
</para>
<programlisting language="xml"><![CDATA[
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry"/>
<webflow:flow-executor id="flowExecutor" />
]]></programlisting>
</sect3>
<sect3 id="upgrade-guide-webflow-config-schema-listeners">

View File

@@ -216,7 +216,7 @@ public void validateEnterBookingDetails(MessageContext context) {
<para>
The second way is to define a separate object, called a Validator, which validates your model object.
To do this, create a class that defines a public method with the name <code>validate${state}</code>, where <code>state</code> is the id of your view-state.
The method must declare a <code>Object</code> parameter to accept your model object, and a <code>MessageContext</code> parameter for recording validation error messages.
The method must declare a parameter to accept your model object, and a <code>MessageContext</code> parameter for recording validation error messages.
For example:
</para>
<programlisting language="java"><![CDATA[
@@ -332,6 +332,12 @@ checkinDate=Check in date must be a future date
notHealthy={0} is bad for your health
reservationConfirmation=We have processed your reservation - thank you and enjoy your stay]]>
</programlisting>
<para>
From within a view or a flow, you may also access message resources using the <code>resourceBundle</code> EL variable:
</para>
<programlisting type="properties"><![CDATA[
<h:outputText value="#{resourceBundle.reservationConfirmation}" />]]>
</programlisting>
</sect2>
</sect1>
<sect1 id="view-popup">

View File

@@ -19,18 +19,11 @@ import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.js.ajax.AjaxHandler;
import org.springframework.js.ajax.SpringJavascriptAjaxHandler;
import org.springframework.util.Assert;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.support.WebContentGenerator;
import org.springframework.webflow.context.servlet.DefaultFlowUrlHandler;
import org.springframework.webflow.context.servlet.FlowUrlHandler;
import org.springframework.webflow.context.servlet.ServletExternalContext;
@@ -42,6 +35,8 @@ import org.springframework.webflow.execution.repository.NoSuchFlowExecutionExcep
import org.springframework.webflow.executor.FlowExecutionResult;
import org.springframework.webflow.executor.FlowExecutor;
import com.sun.tools.javac.tree.Tree$Assert;
/**
* A custom MVC HandlerAdapter that encapsulates the generic workflow associated with executing flows in a Servlet
* environment. Delegates to mapped {@link FlowHandler flow handlers} to manage the interaction with executions of
@@ -365,8 +360,12 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
sendRedirect(url.toString(), response);
}
private void sendRedirect(String url, HttpServletResponse response) throws IOException {
response.sendRedirect(response.encodeRedirectURL(url));
private void sendRedirect(String url, HttpServletRequest request, HttpServletResponse response) throws IOException {
if (ajaxHandler.isAjaxRequest(getServletContext(), request, response)) {
ajaxHandler.sendAjaxRedirect(getServletContext(), request, response, url, false);
} else {
response.sendRedirect(response.encodeRedirectURL(url));
}
}
private void handleFlowException(FlowException e, HttpServletRequest request, HttpServletResponse response,