package com.smartgwt.client.docs;
/**
* <h3>Smart GWT Architecture</h3>
* Smart GWT can add interactivity and performance benefits to any web application with a
* variety of integration approaches. This topic discusses the optimal architecture for a
* Smart GWT application, which can be adopted in whole or in part.
* <p>
* In a typical HTML-based web application, every time a new view is shown to a user, a round
* trip to the server is required to retrieve new presentation information, such as a search
* screen. However in an ISC-based application, showing a new view can be accomplished by
* simply hiding some components and showing others.
* <p>
* Because ISC components are expressed in a concise declarative form, and because ISC
* components have essentially no runtime performance impact until used, dozens of application
* views can be downloaded to the browser using the same bandwidth that would have been
* required to render just the initial view in plain HTML.
* <p>
* This architectural pattern of "preloading views" has tremendous benefits. View transitions
* which do not require new data from the server can be performed near-instantaneously and
* without server involvement, boosting both interactivity and scalability.
* <p>
* Showing a dialog containing a "wizard" is a straightforward example of showing a "preloaded
* view". For example:
* <pre>
* function showNewUserWizard() {
* Window.create({
* items:[
* DynamicForm.create({ ... })
* ]
* });
* }
* Button.create({
* title:"New User..",
* click:"showNewUserWizard()"
* });
* </pre>
* In this example, none of the components involved in a potentially multi-pane wizard are
* created until they are needed. Showing the wizard has near-instantaneous response and
* causes no server load.
* <p>
* However, let's say that the first pane of the wizard is going to incorporate some dynamic
* user-specific data, such as the current user's name. To load the username, we'll use an RPC
* operation targetting a .jsp called "getUserName.jsp" and show the wizard when it completes
* (see {@link com.smartgwt.client.rpc.RPCManager} for information on RPCs and how to construct a .jsp that can
* send an RPC response).
* <pre>
* function showNewUserWizard() {
* RPCManager.sendRequest({
* actionURL:"getUserName.jsp",
* callback:"doShow(rpcResponse)"
* });
* }
* function doShow(rpcResponse) {
* Window.create({
* items:[
* Canvas.create({contents:"Hello, " + rpcResponse.userName}),
* DynamicForm.create({ ... })
* ]
* });
* }
* Button.create({
* title:"New User..",
* click:"showNewUserWizard()"
* });
* </pre>
* In this example, we've simply incorporated a user name into the first pane of a wizard.
* However, this pattern allows us to arbitrarily change user interactions based on data from
* the server. For example, the RPCResponse might have contained a flag indicating that the
* wizard should skip the first two steps, or an arbitrary warning message for the user, or
* even JavaScript code to be evaluated on the client.
* <P>
* This architecture has several key advantages:
* <dl>
*
* <dt><b>Performance: Cacheable UI</b></dt>
* <dd>
* A dynamic, data-driven UI can be expressed completely in <i>cacheable</i> JavaScript.
* This is in contrast to any architecture based on server-side HTML generation, where static
* parts of the presentation are mixed in with dynamic data, preventing cacheability so that
* bandwidth and server time are wasted repeatedly delivering the same static presentation
* data.
* <br>
* Even generated JavaScript is cacheable. For example, a Smart GWT View expressed in XML
* and contained within a JSP is still a separately cacheable resource when loaded via a
* <SCRIPT SRC> tag and advertised as a cacheable resource via HTTP headers, because it
* is ultimately delivered to the browser as simple JavaScript. Hence standard
* {@link i18n internationalization} techniques such as using JSTL tags in a JSP remain
* applicable.
* <br>
* The Smart GWT Architecture even allows you to capture all the gradations of cacheability
* from completely static (changes once per application rollout) to completely dynamic
* (timestamp). In the example above, the user name wouldn't actually change for the lifetime
* of the page, so could be loaded once only.
* <br> </dd>
*
* <dt><b>Performance: Minimal Server State</b></dt>
* <dd>
* Any architecture that relies on component descriptions being generated by the server
* must track a great deal of state, which, in the Smart GWT Architecture, is either
* completely eliminated or greatly reduced.
* <br> </dd>
*
* <dt><b>True Presentation / Business Logic separation</b></dt>
* <dd>
* The RPCResponse object represents the client's exact, minimal needs for server data.
* This is much easier to understand and to audit than a slew of .jsp files which access and
* update miscellaneous state. It is also far easier to spot reusable patterns of data access,
* which in server-side HTML generation systems often end up as duplicated code.
* <br> </dd>
*
* <dt><b>Parallel Development and Testability</b></dt>
* <dd>
* Using the Smart GWT architecture allows you to build a complete, working application
* that can run without a server, based on sample data. In the example above, it would be
* straightforward to create a testing mode that returned a faked RPC response consisting of
* simply <code>{ userName : "Bob" }</code>.
* <br>
* This allows better parallel development by enabling the client side of the system to be
* tested in isolation, and creates clearer communication between client and server-side
* developers since creation of test data tends to develop into data requirements
* specifications.
* <br>
* For more info on creating applications that support client-only testing, see
* {@link com.smartgwt.client.docs.ClientOnlyDataSources Client Only DataSources}.
* <br> </dd>
* </dl>
* <br>
* <h3>Refinements</h3>
* <br>
* <b>Creating vs Showing a View</b>
* <br>
* Many views will be shown to the user repeatedly, for example, the user may repeatedly switch
* back and forth between two panes of a TabSet. In that usage it makes sense to make a
* distinction between <i>creating</i> a view and <i>showing</i> an existing view. When
* showing an existing view, the same components and/or data may be able to be reused.
* <br>
* In the following variant on the original example, we only create the Window object and
* do the RPC to retrieve the user name the first time <code>showNewUserWizard()</code> is
* called. Subsequently we reuse the existing window, and we assume the user name has not
* changed, so we need not do the RPC again. (<i>Note: "New User" button omitted for brevity
* from here on</i>)
* <pre>
* function showNewUserWizard() {
* if (!window.myWindow) {
* Window.create({
* ID:"myWindow",
* autoDraw:false,
* items:[
* Canvas.create({ ID: "welcomeCanvas" }),
* DynamicForm.create({ ... })
* ]
* });
* RPCManager.sendRequest({
* actionURL:"getUserName.jsp",
* callback:"doShow(rpcResponse)"
* });
* } else {
* myWindow.show();
* }
* }
* function doShow(rpcResponse) {
* welcomeCanvas.setContents("Hello, " + rpcResponse.userName);
* myWindow.show();
* }
* </pre>
*
* <b>Batching Operations</b>
* <br>
* A view may incorporate multiple components, each of which requires data. In the following
* example, a DataBound ListGrid has been incorporated into the wizard, and we'd like to fetch
* the user's name and the beginning dataset for the grid in the same batch. We use
* {@link com.smartgwt.client.rpc.RPCManager#startQueue RPCManager.startQueue} to do so.
* <pre>
* function showNewUserWizard() {
* if (!window.myWindow) {
* Window.create({
* ID:"myWindow",
* autoDraw:false,
* items:[
* Canvas.create({ ID: "welcomeCanvas" }),
* <b>ListGrid.create({
* ID: "myGrid",
* dataSource:"myDataSource"
* }),</b>
* DynamicForm.create({ ... })
* ]
* });
* <b>RPCManager.startQueue();
* myGrid.fetchData();</b>
* RPCManager.sendRequest({
* actionURL:"getUserName.jsp",
* callback:"doShow(rpcResponse)"
* });
* <b>RPCManager.sendQueue();</b>
* } else {
* myWindow.show();
* }
* }
* function doShow(rpcResponse) {
* welcomeCanvas.setContents("Hello, " + rpcResponse.userName);
* myWindow.show();
* }
* </pre>
*
* <b>Segmenting very large Applications</b>
* <P>
* If an application has many hundreds of views, but only a handful of views are used by a
* given user in a typical session, for the fastest loading performance you should consider
* loading only the most commonly used views initially then loading further views on demand.
* <P>
* You can use FileLoader.loadJSFiles to load a set of JavaScript files
* compromising an application module that defines a set of related views. The loaded
* JavaScript files may define new component classes and new DataSources in addition to
* defining new views and their associated logic.
*/
public interface SmartArchitecture {
}