| <html> |
| <head> |
| <title>Struts 2.x 'Shale' Proposal</title> |
| </head> |
| <body> |
| |
| <div align="center"> |
| <h1>Struts 2.x 'Shale' Proposal</h1> |
| <h3>$Id$</h3> |
| [<a href="#Introduction">Introduction</a>] |
| [<a href="#ProposalDetails">Proposal Details</a>] |
| [<a href="#Infrastructure">Infrastructure</a>] |
| </div> |
| |
| <hr/><a name="Introduction"> |
| <h2>1. Introduction</h2> |
| |
| <h3>1.1 Background</h3> |
| |
| <p>Little did anyone know, when the first few lines of code were committed to |
| the Struts CVS repository at Apache in June 2000, that a revolution was |
| brewing. Prior to that time, there were few useful models for best practices |
| for the architecture of web based applications. The best we could do was |
| handwaving about the relative advantages of "Model 1" versus "Model 2" |
| approaches.</p> |
| |
| <p>The original implementation of Struts, which was released as a 1.0 product |
| approximately one year later, changed all that. As more and more people |
| came to understand the advantages of building on top of a stable and supported |
| framework, and as more and more developers adopted it for their own |
| application development, and as more than more books helped everyone understand |
| how to use the framework correctly, and as more and more development tools |
| provided support for building Struts based applications, the world changed. |
| A small open source project became a defacto industry standard that, even today, |
| gets downloaded many tens of thousands of times per month.</p> |
| |
| <p>But, that was then ... and this is now. In the four years that Struts has |
| been around (a relatively infinite amount of "Internet time"), vastly improved |
| technologies have become available from many talented architects and designers. |
| Moore's Law has continued its seemingly inexhaustible progress. Developers have |
| grown in their ability to understand less monolithic architectures -- as well |
| as developing preferences towards agility, the ability to create unit tests, |
| and to build applications by composition rather than inheritance.</p> |
| |
| <p>One of the critical success factors for Struts has been, and continues to |
| be, an obvious commitment (on the part of Struts developers) to maintain and |
| enhance the framework in a way that remains fundamentally backwards compatible, |
| while embracing new technologies as they have become availalble. This has led |
| to Struts being both praised (for protecting the investment of developers with |
| thousands of applications critically dependent on the framework) and dissed |
| (for being a dinosaur compared to all the "latest and greatest" favorite |
| technological approaches). History has shown (in terms of continued popularity) |
| that this is a good strategic approach.</p> |
| |
| <p>Indeed, Struts will continue to evolve in a manner that protects the |
| investments of existing users. For example, the recent discussions around |
| using the "chain of responsibility" design pattern inside the Struts controller |
| to radically simplify customization and extension of the framework, while at the |
| same time providing historically consistent default functionality, is just one |
| example of this trend. But ... it's also time for something else.</p> |
| |
| <p>It is time to harvest many of the great ideas that have matured in the last |
| four years. It is time to focus Struts on solving the unsolved problems, while |
| leveraging existing solutions instead of reinventing them. It is time to |
| answer the question "if we knew then what we know now, what would Struts have |
| looked like?"</p> |
| |
| <p>Thus, this is a proposal to fundamentally reinvent Struts ... to bring |
| the framework up to date. To focus on the key value add of a framework that |
| focuses on the "controller" tier of the traditional Model-View-Controller |
| design pattern, while expanding the areas of responsibility that the |
| controller assumes, but at the same time radically simplifying the use |
| of the overall framework -- and lets you choose the portions that you |
| care about, rather than being monolithic. To bring forth ... a proposal |
| for a future of Struts, code named the "Shale" proposal.</p> |
| |
| <blockquote><em> |
| EDITOR'S NOTE: |
| Why "Shale"? As others have pointed out, the cultural |
| rules of engagement at Apache encourage both evolution |
| and revolution in software designs. Revolutions are |
| typically assigned code names while they are still under |
| discussion, and only gain access to the branding of the |
| overall project once they are accepted. Other proposals |
| for Struts 2.x have talked about tearing down the walls |
| inside the framework, and those are Good Things. This |
| proposal, on the other hand, suggests that we fundamentally |
| divide the notion of a web application framework into |
| solid individual layers, much as we see geologically in |
| shale deposits around our volcanoes and coastlines. Each |
| layer of the framework should focus on the specific |
| requirements that are relevant to that layer -- and use of |
| one layer should not necessarily require the use of all the |
| rest (although it's certainly reasonable for synergies to |
| exist if all the layers are chosen :-). Hence, "shale." |
| </em></blockquote> |
| |
| <p>But first, let's examine some problems with the current architectures |
| of web application frameworks in general, and Struts 1.x in particular.</p> |
| |
| <h3>1.2 Monolithic Controllers</h3> |
| |
| <p>Most current implementations of a Model-View-Controller architecture |
| for web applications have focused on providing a single monolithic |
| controller that is responsible for the entire processing of every |
| incoming request. While this paradigm is very powerful, it creates |
| usability and understandability problems for some application developers, |
| because it requires artificial separation of portions of the application |
| logic that (from the viewpoint of the developer) belong together. The |
| most common scenario in a Struts-based application, for example, is the |
| following pattern:</p> |
| <ol> |
| <li>User fills out and submits the form requesting a transaction.</li> |
| <li>Controller routes the request to the business logic responsible |
| for performing the transaction.</li> |
| <li>Controller routes the request to setup logic for the next form |
| to be displayed.</li> |
| <li>Controller routes the request to the view tier component that |
| displays the new form.</li> |
| </ol> |
| |
| <p>A key issue is that, from the point of view of the person supporting |
| a particular business transaction, the following pieces of functionality |
| are tightly coupled:</p> |
| <ul> |
| <li>The setup logic for that transaction (such as retrieving |
| information from the model) that is required to complete |
| the presentation to the user.</li> |
| <li>The presentation logic in the view tier technology that |
| actually generates your user interface.</li> |
| <li>The processing logic that will accept the incoming form |
| and complete the requested transaction.</li> |
| </ul> |
| |
| <p>Yet in Struts 1.x, for example, the setup logic and processing logic end up |
| in two different Actions, requiring multiple action mappings, and a tendency |
| for people to implement action chaining and be surprised by the results. A |
| more developer-friendly approach would be to combine the tightly coupled |
| processing actions into a single Java class, implicitly associated in a 1:1 |
| relationship by a (pluggable) mapper, so that the entire combination has a |
| single "identity" from the point of view of the application framework -- and |
| so that this entire combination can be treated as a unit by development tools |
| that choose to support it.</p> |
| |
| <h3>1.3 Multiple Request Interactions</h3> |
| |
| <p>One of the most significant technological challenges of developing |
| applications based on HTTP is dealing with the stateless aspect of the |
| protocol. The servlet API provides a relatively simple mechanism for |
| identifying requests that are coming from the same user (sessions). In |
| turn, this allows convenient state saving of information particular to |
| an individual user's interactions with the application. But it doesn't |
| solve all of the problems.</p> |
| |
| <p>In particular, it is common for individual transactions to require more |
| than one interaction with a user. The servlet API offers no direct support |
| for maintaining state across these requests that is specific to that |
| transaction -- let alone deal with realities like the back button on a |
| browser, which can lead to incorrect interactions. Some frameworks do more |
| than others to manage this problem. In Struts 1.x, for example, you can use |
| the transaction token mechanism to catch the "duplicate submit" scenario. |
| But a more comprehensive solution go "guided dialog" transactions, with the |
| associated state management, would substantially improve the productivity |
| of developers utilizing the framework.</p> |
| |
| <h3>1.4 Application Scope Features</h3> |
| |
| <p>It may seem, from the above problem descriptions, that an application-level |
| controller has no reason for being any longer. Yet, nothing could be further |
| from the truth. There are still useful features that can be enabled by |
| processing on every incoming request. In Struts 1.x, we have required all |
| transactions to flow through a processing servlet -- because we have used |
| Servlet 2.2 as the base platform, we were not able to implement these features |
| using servlet filters.</p> |
| |
| <p>Moving to a Servlet 2.4 baseline provides us the opportunity to invoke only |
| the required per-every-request features that a particular application requires, |
| without requring a monolithic implementation. In addition, event listeners (at |
| the request, session, and application) levels will be important, for example, |
| for implementing end-of-request cleanup operations, or detect when request |
| attributes of a particular type are registered, so that value add services may |
| be provided transparently.</p> |
| |
| <p>Beyond this, however, modern application frameworks are expected to provide |
| standard services (or supported plugins to standard services) out of the box. |
| Struts needs to offer such solutions in areas that are particularly important, |
| yet currently require individual integration by application developers.</p> |
| |
| <hr/><a name="ProposalDetails"></a> |
| <h2>2. Proposal Details</h2> |
| |
| <h3>2.1 Overview</h3> |
| |
| <p>The briefest way to state the proposed architecture is to fulfill the |
| following goal statement:</p> |
| <blockquote><em> |
| Divide the responsibilities of the monolithic Struts 1.x controller into individual layers, |
| whose features may be composed in appropriate combinations based |
| on the requirements of a particular application. |
| </em></blockquote> |
| |
| <p>To that end, the following primary layers are proposed:</p> |
| <ul> |
| <li><strong>Application</strong> - Framework for performing processing |
| that is required on every incoming request, plus a place to plug in |
| application-wide services that are offered as standard plug-ins.</li> |
| <li><strong>Dialog</strong> - Framework for managing a series of individual |
| interactions with the same user, necessary to complete a particular |
| business transaction, plus a mechanism for plugging in predefined |
| dialog services that are offered as standard plug-ins.</li> |
| <li><strong>View</strong> - Framework for elegantly combining a view tier |
| technology that actually composes an individual HTTP response with the |
| corresponding business logic interactions (to retrieve or modify data |
| in the model tier), as well as handle user interface events activated |
| by the user.</li> |
| </ul> |
| |
| <p>The features provided by each of these layers are further described |
| in the following sections.</p> |
| |
| |
| <h3>2.2 Application Controller</h3> |
| |
| <p>There continue to be framework responsibilities that are best discharged |
| by preprocessing (and/or postprocessing) every request, or every request that |
| meets certain criteria. Shale will leverage the <code>Filter</code> APIs of |
| the servlet container to provide mechanisms to plug in individual application |
| level functionality for purposes such as:<p> |
| <ul> |
| <li>Access logging</li> |
| <li>Authentication and authorization</li> |
| <li>Performance statistic gathering</li> |
| <li>Compression of large responses</li> |
| <li>Unwrapping of incoming content types other than the default |
| (<code>application/x-www-form-urlencoded</code>)</li> |
| <li>Remapping of incoming requests to alternate (or locale-specific) URLs</li> |
| </ul> |
| |
| <p>Depending upon the nature of the individual pieces being integrated, it |
| might be more user friendly to configure a single <code>Filter</code> that |
| used a customizable "chain of responsibility" design pattern (like that |
| provided by Commons Chain) to implement the actual behavior performed for |
| each incoming request.</p> |
| |
| <p>In the specific case of authentication and authorization, Shale must |
| interoperate both with applications wishing to utilize container managed |
| security, as well as those providing their own technology. In both cases, |
| it is expected that the outcome of performing authentication and |
| authorization activities will be made visible to the application via return |
| values of the (potentially wrapped) servlet/portlet request methods |
| <code>getRemoteUser()</code>, <code>getUserPrincipal()</code>, and |
| <code>isUserInRole()</code>.</p> |
| |
| <p>Separate from the core of Shale, we should consider supporting a |
| subproject that provides functionally complete plug-ins that implement |
| functionalities of the types described above. In particular, a complete |
| user administration system (with support for "remember me" cookies) would |
| be a popular feature useful in many application environments.</p> |
| |
| |
| <h3>2.3 Dialog Controller</h3> |
| |
| <p>Nearly all modern MVC-based frameworks for web application development |
| provide some level of support for the "application controller" functionality |
| described in the previous section, as well as the "view controller" capabilities |
| described next. However, relatively few of them deal with an intermediate |
| requirement to manage a "dialog" or "conversation" with the application user |
| that spans multiple HTTP requests. Dealing with this complexity is left as |
| an "exercise left for the reader" -- a state of affairs that Struts 2.x should |
| change.</p> |
| |
| <p>Although this portion of the "Shale" proposal is the least fleshed out in |
| terms of an thinking through a possible implementation approach, it offers an |
| opportunity for substantially improving the productivity of developers building |
| applications based on Struts. Therefore, let us define the requirements that |
| must be met by an implementation of a controller for dialogs:</p> |
| <ul> |
| <li>It must be possible to maintain a set of state information for a |
| dialog across multiple HTTP requests.</li> |
| <li>It must be possible for an application user to engage in more than one |
| dialog simultaneously (for example a non-modal pop-up wizard dialog |
| running at the same time as the main line application's dialog, perhaps |
| with a third dialog rendering context-sensitive help in another window). |
| </li> |
| <li>It must be possible to describe the set of views involved in a dialog |
| (and, implicitly, their corresponding event handlers in a backing bean) |
| in such a manner that navigation can be performed by an event handler |
| for one view, without having to be aware of the details of the overall |
| structure of the entire dialog.</li> |
| <li>Description of a dialog should include not only support for navigation |
| (first, previous, next, last, and so on) but also some mechanism for |
| scripting the entire dialog's flow. Examples of descriptions might be |
| some scripting language that supports "continuations" (i.e. the ability |
| to suspend execution and restart it later), or Java APIs that make state |
| saving and restoring easy to perform in view-specific event handlers.</li> |
| <li>Dialog descriptions must be self documenting enough for tools to be |
| able to produce high quality user experiences at design time.</li> |
| <li>In addition to generic navigation, the dialog controller |
| must support one or more mechanisms to exit from the dialog (typically |
| via "finish" and "cancel" controls, but not limited to these).</li> |
| <li>To the maximum degree feasible, the dialog controller must manage the |
| browser's "back" and "forwards" buttons, treating them as if the |
| corresponding navigation controls had been utilized (in terms of |
| undoing and redoing changes to the state information being maintained). |
| Clearly, this will require restrictions on persistent changes to model |
| tier data performed as each step of the dialog is executed, but those |
| restrictions should be explicitly documented and easy to obey.</li> |
| </ul> |
| |
| <h3>2.4 View Controller</h3> |
| |
| <p>Shale will support a mechanism that provides a 1:1 relationship between |
| a view tier presentation technology responsible for creating an HTTP response |
| (such as a JSP page), and a corresponding Java class containing event handling |
| logic, (optionally) values used in the dynamic rendering of the response, and |
| (optionally) bindings to the individual user interface components included in |
| the response page. Such a Java class is known (in JSF terminology) as a |
| "backing bean," and will in most circumstances be registered as a managed |
| bean in the JSF configuration resources.</p> |
| |
| <p>JSF does not require that a backing bean implement any particular interface, |
| or extend any particular base class. Therefore, Shale should not impose any |
| such restriction either. It should merely promise to ensure that a bean of the |
| appropriate class (selected by a pluggable mapper that translates the JSF |
| view identifier into a class name) will be present -- normally in request |
| scope -- when needed to process an incoming form submit, or to render a newly |
| created view.</p> |
| |
| <p>However, if an application's backing bean happens to implement a lightweight |
| <code>ViewController</code> interface defined by Shale, several lifecycle |
| related methods will be called by the framework:</p> |
| <ul> |
| <li>The backing bean will possess the following properties useful in |
| conditionally performing application logic based on the current |
| processing state: |
| <ul> |
| <li><strong>dialog</strong> - The <code>DialogController</code> instance |
| for the dialog that this view is a participant in, if any.</li> |
| <li><strong>postBack</strong> - Boolean property indicating whether this |
| view (and corresponding backing bean) will be processing an incoming |
| form request, or only rendering output for a newly created view.</li> |
| </ul></li> |
| <li>The following lifecycle methods will be called by the framework at the |
| indicated times: |
| <ul> |
| <li><strong>init()</strong> - Called after a backing bean instance has been |
| created and framework-defined properties (see above) have been set. |
| This is a useful place to acquire resources that will be needed for |
| either a form submit or for rendering a new view.</li> |
| <li><strong>prepare()</strong> - Called immediate before the currently |
| selected view is rendered (in JSF terms, this happens at the beginning |
| of <em>Render Response</em> phase, before the <code>encode()</code> |
| methods of the components have been called). This method is only |
| called for a view that is actually going to be rendered, in the |
| case where the view being rendered is different from the view that |
| responded to a form submit. As such, it is a useful place to acquire |
| references to model data that is required in the rendering of |
| this view.</li> |
| <li><strong>destroy()</strong> - Called after rendering has been completed, |
| for all <code>ViewController</code>s that have had their |
| <code>init()</code> method called during this request.</li> |
| </ul></li> |
| </ul> |
| |
| <p>Other than implementing a Shale-defined interface, a |
| <code>ViewController</code> need not have any other dependence on the |
| framework. Thus, it remains easy to unit test such a bean outside of |
| a servlet container environment.</p> |
| |
| <p>When coding the action method corresponding to a form's submit button, |
| Shale should encourage best practices in terms of delegating business |
| logic to the model tier, rather than implementing it directly in the action |
| method. One approach to this might be to provide helper methods that make |
| it easy to encapsulate the current request state (including the current |
| instance of the backing bean, which would include all the incoming input |
| field values) into a context that is then passed to a "chain of responsibility" |
| implementation such as Commons Chain for performing the actual business logic |
| processing.</p> |
| |
| <p>Best practices for JSF include storing backing beans in request scope, |
| rather than in page scope. Because such beans are instantiated anew for each |
| request, and are accessed only by a single thread, there are no thread safety |
| concerns (as there are with Struts 1.x Actions) related to instance variables. |
| However, this also means that state required across more than one request |
| needs to be stored elsewhere (because the backing bean will be thrown away |
| at the end of the request).</p> |
| |
| |
| <h3>2.5 Functionality Not Included In The Shale Core</h3> |
| |
| <p>Compared to Struts 1.x, support for client side validation and layout |
| management (Tiles) are explicitly excluded from the core controller framework. |
| This is not based on any belief that the functionality is not valuable -- it |
| belongs properly in the view tier, and should be managed there as a separate |
| subproject.</p> |
| |
| |
| <hr/><a name="Infrastructure"></a> |
| <h2>3. Infrastructure</h2> |
| |
| <p>A key aspect of designing a framework is to choose which features it |
| implements itself, and which capabilities it imports as dependencies. The |
| "Shale" proposal contemplates the following dependency choices, with |
| individual implementations proposed for some of them. Shale will then |
| provide its own APIs in the controller tier that leverage these capabilities. |
| </p> |
| |
| <h3>3.1 Java2 Standard Edition APIs</h3> |
| |
| <p><em>Proposal</em>: JDK Version 1.4</p> |
| |
| <p>Picking a base J2SE platform is a tradeoff between wanting to use all |
| the latest and greatest features of the most recent platform (for the |
| purposes of this discussion, JDK 5.0) and the realities of how many |
| developers will have the possibility of deploying applications based on |
| that platform when we release the initial version of Shale. Currently, |
| Struts 1.x requires a minimum of JDK 1.2 (because it uses the collection |
| classes extensively).</p> |
| |
| <p>JDK 1.4 represents a slightly aggressive choice given the current state |
| of the market, but relies on a reasonable assumption that JDK 1.4 will |
| become widely deployed over the next 12-18 months (in particular because |
| JDK 1.4 is a required baseline for the upcoming generation of J2EE 1.4 |
| platform application servers). The key technological reasons for this |
| choice (over a more conservative choice of JDK 1.3) include:</p> |
| <ul> |
| <li>Integration of JAXP (XML parsing and transformations) into the base |
| platform, eliminating the need to worry about providing such libraries |
| as part of a web application or separate plugin to a web container.</li> |
| <li>New I/O APIs allow the applications that leverage the potentially |
| higher performance access to the filesystem.</li> |
| <li>Inclusion of critical security APIs (JSSE for "https" protocol access, |
| and JAAS for authorization and authentication) into the base |
| platform.</li> |
| <li>JDBC 3.0 integration, including connection pools (data sources) |
| and rowsets.</li> |
| <li>Assertion facility, allowing developers to create assertions that can |
| be conditionally compiled.</li> |
| <li>Chained exceptions, which (if used correctly) allows underlying causes |
| to be included in a business tier exception, without tying to specific |
| APIs unnecessarily.</li> |
| <li>Internationalization improvements, particularly support for |
| Unicode 3.0.</li> |
| <li>Performance improvements in areas critical to the framework (such as |
| reflection and object creation/garbage collection).</li> |
| </ul> |
| |
| <h3>3.2 Java2 Enterprise Edition APIs</h3> |
| |
| <p><em>Proposal</em>: J2EE Version 1.4 Platform APIs</p> |
| |
| <p>For Struts, the most important platform API is the Servlet Specification. |
| Although Servlet 2.4 (the version included in J2EE 1.4) was fairly modest |
| in the scope of its changes, several of them are important to the architecture |
| of a web application framework:</p> |
| <ul> |
| <li>Lifecycle and event listeners for requests (as well as sessions |
| and the entire application).</li> |
| <li>Filters can be applied across RequestDispatcher calls, not only |
| on the original request.</li> |
| <li>Ability to specify a servlet path as a welcome file, without needing |
| an actual artifact.</li> |
| <li>Clarifications in ordering of event handler calls ensure consistent |
| behavior across implementations.</li> |
| </ul> |
| |
| <h3>3.3 View (Presentation) Tier APIs</h3> |
| |
| <p><em>Proposal:</em>: JavaServer Faces 1.1</p> |
| |
| <p>Prior to the development of JavaServer Faces, web application frameworks |
| were on their own in terms of supporting mechaisms for user interface components |
| and the corresponding request processing lifecycle. The standardization of JSF |
| provides an opportunity to build on top of a functionally capable API that is |
| slated to become part of the J2EE 5.0 platform, and which provides useful |
| (from the viewpoint of a framework) functionality in many areas beyond just |
| the user interface components themselves, such as:</p> |
| |
| <ul> |
| <li>Well-defined request processing lifecycle with appropriate |
| extension points for inserting application framework functionality.</li> |
| <li>Built-in support for page navigation based on logical outcomes |
| from event handlers.</li> |
| <li>Managed beans facility that provides on-demand creation of |
| JavaBeans, including setter injection to configure their |
| properties.</li> |
| <li>Powerful expression language evaluation mechanisms, allowing |
| dynamically scripted value retrievals, value settings, and |
| method calls.</li> |
| <li>Expression evaluation is extensible in two ways ... through |
| plug-in variable resolvers (can provide linkage into existing |
| hierarchies of data) and plug-in property resolvers (can |
| redefine what the "." operator in an expression does, based |
| on the type of object it is being applied to).</li> |
| </ul> |
| |
| <p>Without JSF, we would likely have to reinvent much of this functionality |
| (or leverage the similar, but more primitive, implementations of these ideas |
| in existing Struts code or other framworks). With JSF, we can leverage the |
| extensibility of the basic framework to enable the division of controller |
| responsibilities at the view (page), dialog, and application level that is the |
| key feature of the entire proposal.</p> |
| |
| |
| <h3>3.4 Model Tier and Persistence APIs</h3> |
| |
| <p>Struts should remain agnostic about technologies to be employed for |
| representing business logic, model data, and persistence. However, |
| functional examples should be provided that encourage the use of best |
| practices in application design.</p> |
| |
| <h3>3.5 Service Provisioning APIs</h3> |
| |
| <p>Inversion of Control (IoC) containers (the techniques are also referred |
| to as Dependency Injection) are becoming a popular mechanism for assembling |
| the required services and logic of an application. If Struts included such |
| a framework, it would provide a solid basis for building maintainable apps, |
| as well as allowing the framework to configure itself using the same |
| capabilities.</p> |
| |
| <p>Rather than building such a container ourselves, we should seek to |
| incorporate an existing one that is license-compatible and which can |
| be integrated into the JSF managed beans facilities (so that value binding |
| and method binding expressions can leverage the facilities of this |
| container transparently). From my research so far, I like Spring's |
| capabilities in this area the best, but am open to other suggestions.</p> |
| |
| <h3>3.6 Authentication and Authorization APIs</h3> |
| |
| <p>In order to support reasonably complete solutions for applications that |
| wish to provide their own authentication and authorization services (as well |
| as interact with container managed security), we need APIs available for |
| performing user registration, implementing "remember me" features, and |
| represent the results via a wrapped request (so that apps depending on |
| getRemoteUser(), getUserPrincipal(), and isUserInRole() will still work). |
| Using JDK 1.4 as a base platform would allow us to integrate mechanisms |
| like JAAS. Other alternatives include plugins like SecurityFilter.</p> |
| |
| <h3>3.7 State Management APIs</h3> |
| |
| <p>The proposed solutions for dialog management require a framework for |
| managing state across multiple HTTP requests. This is likely to be an |
| area where considerable investigation is needed before picking a fundamental |
| technology. Things that seem feasible based on my initial review are:</p> |
| <ul> |
| <li>Modified Rhino with support for continuations (as used in |
| <a href="http://cocoon.apache.org/2.1/userdocs/flow/">Cocoon Flow</a> |
| and Don Brown's <a href="http://struts.sourceforge.net/struts-flow/"> |
| Struts Flow</a> plugin). I'll feel better about this if/when the |
| modifications are part of a mainstream Rhino release, however.</li> |
| <li>An updated version of <a href="http://jakarta.apache.org/commons/sandbox/workflow/"> |
| Commons Workflow</a> that leverages the expression language APIs |
| of either JSF or something like JEXL, but also supports continuations.</li> |
| <li>Working with the <a href="http://jakarta.apache.org/commons/jelly">Jelly</a> |
| folks to add continuations support.</li> |
| <li>Giving up on explicit continuations support, and providing Java APIs |
| that make explicit saving and restoring of state easier.</li> |
| </ul> |
| |
| <h3>3.8 Logging APIs</h3> |
| |
| <p><em>Proposal</em>: Commons Logging</p> |
| |
| <p>Logging is an important feature of both an application framework itself |
| (to help developers understand the dynamic behavior of the framework) and |
| for building high quality applications. If the proposal for JDK 1.4 is |
| accepted, we could potentially mandate using the java.util.logging APIs; |
| however, many Struts users prefer to use alternative logging implementations |
| such as Log4J. Commons Logging provides a portable adapter layer that allows |
| the use of different logging implementations under the covers.</p> |
| |
| </body> |
| </html> |