| <!DOCTYPE html> |
| |
| |
| <!-- |
| | Generated by Apache Maven Doxia Site Renderer 2.0.0 from src/site/xdoc/proposals/browser-bound-app-context.xml at 10 Sep 2025 |
| | Rendered using Apache Maven Fluido Skin 2.1.0 |
| --> |
| <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> |
| <head> |
| <meta charset="UTF-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| <meta name="generator" content="Apache Maven Doxia Site Renderer 2.0.0" /> |
| <title>Application Service Proposal – Apache Turbine</title> |
| <link rel="stylesheet" href="../css/apache-maven-fluido-2.1.0.min.css" /> |
| <link rel="stylesheet" href="../css/site.css" /> |
| <link rel="stylesheet" href="../css/print.css" media="print" /> |
| <script src="../js/apache-maven-fluido-2.1.0.min.js"></script> |
| <link rel="icon" type="image/png" sizes="48x48" href="https://apache.org/favicons/favicon.ico"> |
| <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
| <style>.github-fork-ribbon:before { background-color: orange; }</style> |
| </head> |
| <body> |
| <a class="github-fork-ribbon right-top" href="https://github.com/apache/turbine-build" data-ribbon="Fork me on GitHub">Fork me on GitHub</a> |
| <div class="container-fluid container-fluid-top"> |
| <header> |
| <div id="banner"> |
| <div class="pull-left"><div id="bannerLeft"><h1><a href="https://turbine.apache.org/"><img src="https://www.apache.org/img/feather_glyph_notm.png" style="width: 50px;" /> The Apache Turbine project</a></h1></div></div> |
| <div class="pull-right"><div id="bannerRight"><h1><a href="https://turbine.apache.org/"><img src="https://turbine.apache.org/images/logo.gif" alt="Apache Turbine" /></a></h1></div></div> |
| <div class="clear"><hr/></div> |
| </div> |
| |
| <div id="breadcrumbs"> |
| <ul class="breadcrumb"> |
| <li id="publishDate">Last Published: 01 Apr 2025<span class="divider">|</span> |
| </li> |
| <li id="projectVersion">Version: 7.1-SNAPSHOT</li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="https://turbine.apache.org/fulcrum/">Fulcrum</a></li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="https://turbine.apache.org/">Turbine</a></li> |
| <li class="pull-right"><a href="https://www.apache.org">Apache</a></li> |
| </ul> |
| </div> |
| </header> |
| <div class="row-fluid"> |
| <header id="leftColumn" class="span2"> |
| <nav class="well sidebar-nav"> |
| <ul class="nav nav-list"> |
| <li class="nav-header">General Information</li> |
| <li><a href="../index.html">Overview</a></li> |
| <li><a href="../features.html">Features</a></li> |
| <li><a href="../fsd.html">Specification</a></li> |
| <li><a href="../getting-started.html">Getting Started</a></li> |
| <li><a href="../how-to-build.html">Howto Build Turbine</a></li> |
| <li><a href="../changes-report.html">Changes</a></li> |
| <li class="nav-header">Documentation</li> |
| <li><a href="../services/index.html"><span class="icon-chevron-right"></span>Services</a></li> |
| <li><a href="../howto/index.html"><span class="icon-chevron-right"></span>Howtos</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/TURBINE">Wiki</a></li> |
| <li><a href="../apidocs/index.html">JavaDocs</a></li> |
| <li class="nav-header">Development</li> |
| <li><a href="../proposals.html">Proposals</a></li> |
| <li><a href="../how-to-help.html">How To Help</a></li> |
| <li><a href="../todo.html">Todo</a></li> |
| <li class="nav-header">Project Documentation</li> |
| <li><a href="../project-info.html"><span class="icon-chevron-right"></span>Project Information</a></li> |
| <li><a href="../project-reports.html"><span class="icon-chevron-right"></span>Project Reports</a></li> |
| <li class="nav-header">Apache</li> |
| <li><a href="https://www.apache.org/">Apache Website</a></li> |
| <li><a href="https://www.apache.org/licenses/">License</a></li> |
| <li><a href="https://www.apache.org/foundation/how-it-works.html">How the ASF works</a></li> |
| <li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li> |
| <li><a href="https://www.apache.org/foundation/thanks.html">Thanks</a></li> |
| <li><a href="https://www.apache.org/security/">Security</a></li> |
| </ul> |
| </nav> |
| <div class="well sidebar-nav"> |
| <form id="search-form" action="https://www.google.com/search" method="get" > |
| <input value="http://turbine.apache.org/turbine/turbine-7-0" name="sitesearch" type="hidden" /> |
| <input class="search-query" name="q" id="query" type="text" placeholder="Search with Google..." /> |
| </form> |
| <div id="poweredBy"> |
| <div class="clear"></div> |
| <div class="clear"></div> |
| <a href="https://maven.apache.org/" class="builtBy" target="_blank"><img class="builtBy" alt="Built by Maven" src="../images/logos/maven-feather.png" /></a> |
| </div> |
| </div> |
| </header> |
| <main id="bodyColumn" class="span10"> |
| |
| |
| |
| |
| <section><a id="Browser_window_bound_application_context"></a> |
| <h1>Browser window bound application context</h1> |
| |
| |
| <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> |
| </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> |
| |
| |
| </section> |
| |
| |
| </main> |
| </div> |
| </div> |
| <hr/> |
| <footer> |
| <div class="container-fluid"> |
| <div class="row-fluid"> |
| <p>© 2000–2025 |
| <a href="https://www.apache.org/">The Apache Software Foundation</a> |
| </p> |
| </div> |
| </div> |
| </footer> |
| </body> |
| </html> |