| <?xml version="1.0"?> |
| <!-- |
| /* |
| * Copyright 2001-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| --> |
| |
| <document> |
| |
| <properties> |
| <title>Application Service Proposal</title> |
| </properties> |
| |
| <body> |
| |
| <section name="Browser window bound application context"> |
| |
| <p><b>The problem: multiple windows</b></p> |
| <p> |
| Suppose that you write an application that will have the ability to open |
| multiple windows at once. These windows will contain views for different |
| application modules. Sometimes, different windows will show the same module, |
| but the data or it's presentation form will be different. It is obvious that |
| each of the windows has an amount of state information associated with it. The |
| HTTP protocol is by design stateless. Because statefullness is necessary for a |
| multitude of applications, cookies mechanism was introduced. Usually, the |
| cookies passed between the server and browser carry only an identifier of the |
| session. The actual data is kept in the servers memory (or other storage device) |
| Unfortunately cookies are not appropriate for managing state information |
| associated with a single window. The primary way of overcoming this limitation |
| is encoding information about the subset of data to be displayed and the |
| presentation details (like sorting order) into the request URLs. This technique |
| allows the user to maintain multiple simultaneous sessions with the same screen |
| of the application in different browser windows, viewing different data sets or |
| using different presentation settings. This technique might be unacceptable in |
| two situations: |
| </p> |
| <ul> |
| <li>the presentation settings should not be visible in the URL so that the user |
| can not tamper with them. </li> |
| <li> the amount of state information is large and/or the generated page contains |
| large number of links. This would lead to generating large amounts of markup, |
| decreasing application responsiveness and consuming resources.</li> |
| </ul> |
| |
| <p><b>The solution: server side window context</b></p> |
| <p> |
| A technique similar to that applied to global session data. Window specific |
| information can be stored on the server, and an token allowing to uniquely |
| identify this information can be added to all URLs generated on the page. |
| This way on the next request originating from a given browser window, the |
| application has access to the state information associated with this window. |
| </p> |
| |
| <p><b>The problem: "Open in new window"</b></p> |
| <p> |
| If opening of windows in a multi-windowed application is utterly under control |
| of the application (the window is created using JavaScript, with context |
| identifier token removed from the URL, to inform the application that it needs |
| to create a new context) window contexts will work fine. In reality users will |
| often create new windows using "open in new window" command, or by dragging |
| URLs between windows. In each of the situations mentioned above, multiple |
| windows displaying the same URL (and thus, by definition the same collection |
| of cookies will appear. These windows are indistinguishable to the application, |
| but it is undesirable that these windows share the window context. That would |
| mean that changes to the state information performed in one window would affect |
| all future requests to the other windows in the group. |
| </p> |
| |
| <p><b>The solution: session context tree</b></p> |
| <p> |
| To effectively detect opening of windows, the token identifying a session |
| context must be different for every request. Please recall the example of a few |
| windows opened "open in new window" command. All of them share the URL, and the |
| context identifying token contained in it. This means that they can access the |
| state information that was valid during the previous request. The data subset |
| displayed and the presentation settings used in all of the windows is the same. |
| But because there are multiple windows now, the session context must split. New |
| contexts must be created, inheriting the contents of the parent (previous) |
| context, an tokens identifying these newly generated context must be included |
| in all URLs generated on the associated pages. |
| </p> |
| |
| |
| <p><b>The problem: the "back" button</b></p> |
| <p> |
| While reading the previous paragraph, you may have an impression that it is |
| possible to perform educated guesses about context branching points and store |
| only as many contexts as there are windows simultaneously open. But when you |
| consider the situation when user uses "back" and "forward" buttons to navigate |
| the application, you'll find out that ALL of the contexts must be remembered |
| by the server. The state information associated with each request may be used |
| multiple times in the future. An LRU garbage collection scheme could be |
| performed on the context objects (only a fixed number of most recently accessed |
| context would be remembered) to conserve server's memory. Unfortunately, this |
| could easily lead to undesirable application operation. Imagine an application |
| with two windows open. An user performs an operation in the window A, then |
| switches to window B an performs so many operations in it that the context of |
| the window A is discarded. Then, performing an operation in the window A may |
| yield unexpected results because the state information was lost. |
| </p> |
| |
| <p><b>Explicit vs Implicit cloning.</b></p> |
| |
| <p> |
| All of the the session contexts have to be replicated per every hit to the |
| application. Memory consumption seems like an important factor to consider |
| here. I had an idea of reducing it a bit, by requiring the programmer to |
| explicitly copy the data from the previous context to the current context |
| that are important. This is makes using session contexts tedious, but |
| avoids cloning unused data over and over, when the user moves from one |
| screen to another (which will obviously need different state information). |
| This has the following downside - when the user uses a link to go back |
| to a screen that he visited earlier, the state information will be lost, |
| because the other screen didn't clone it (because it had no idea about them). |
| The presentation details will be reset to normal. On the other hand, if |
| the user pressed the "back" button multiple times to go back to that screen, |
| the presentation details would be remembered (the URLs contain valid |
| context identifier tokens). The conclusion is, that cloning all of the |
| stuff contained in the context gives a better user experience. Memory is |
| cheap these days, right? Oh, don't worry that those context have to stay |
| in memory forever. They should be bound to a global (cookie style) session |
| and discarded when the global session times out. |
| </p> |
| |
| <p><b>A sketch of implementation</b></p> |
| |
| <p> |
| <ul> |
| <li> |
| SessionContext interface similar to that of ServletSession |
| </li> |
| <li> |
| getGlobalContext() and getLocalContext() methods in RunData |
| </li> |
| <li> |
| a wrapper object containing a global context and multiple |
| local context keyed by id, to be stored in the HTTP session |
| </li> |
| <li> |
| context id tokens automatically picked up (after ParameterParser |
| runs) and the context extracted/cloned/created as needed using |
| the wrapper object from the session, and appropriate contexts |
| made available through RunData |
| </li> |
| <li> |
| context id added to the url by the DynamicURI et al |
| </li> |
| </ul> |
| </p> |
| |
| </section> |
| |
| </body> |
| </document> |