Author: admin

  • Jetty @ Eclipse – 7.0.0.M0

    I am pleased to announce the availability of the first milestone build of jetty7 @ eclipse!
    Download Jetty 7.0.0.M0!
    It has been a crazy few weeks getting all of this together but it finally happened and we crossed a big initial hurdle in our efforts to move through incubation. We are still in the parallel ip verification process which is proceeding well, as expected. The process of getting accustomed to bugzilla and the eclipse infrastructure is also chugging along and as our milestone builds progress we will slowly enable more functionality to the eclipse community. Things like update sites and increased support for osgi are all coming over the next months.
    Best make one quick note in case folks are not aware, with the delaying of the servlet 3.0 spec we are altering the development path for jetty7 and dropping support for the 3.0 api and instead jetty7 is the initial release of jetty that has org.eclipse package changes, a base jdk requirement of java5 and other improvements that you will hear about as they crop up. Jetty8 will be the first version of jetty that will support the servlet 3.0 api and builds of that will be available as well soon.
    Lastly, I would like to give a quick thanks to the folks within the Eclipse Foundation that have helped us immeasurably to get to this point.
    [edit]
    I would be remiss to not note to our maven brethren that the location of jetty artifacts has changed within the central maven repository.

    Maintenance releases of Jetty6 will still remain in the org/mortbay/jetty location within the central repository. In fact jetty 6.1.16 was released today and is available.

  • Maven, m2e and the Nexus Repository manager

    Jetty-7 is moving to eclipse, cometd-java is moving from jetty to
    cometd.org and the maven build system for dojo has been moved out of
    the main dojo tree. So I’m involved in some major refactoring of
    three interdependent projects at the same time. This refactoring
    would be impossible to contemplate without the tools support for
    these projects. Maven, m2e and nexus are making my life a lot easier.

    Maven

    Apache Maven
    is a build tool of the

  • Jetty @ EclipseRT

    The jetty @ eclipse project is now in incubation at the eclipse foundation as part of the EclipseRT runtime project. On Tuesday 24th March, the Jetty-7 code base was converted to org.eclipse.jetty package space and checked  into the eclipse jetty svn repository!!!

    What is changing?

    It is only the core components of Jetty that are moving to eclipse. The project will also remain at codehaus and it will be at codehaus the the jetty@eclipse components are packaged into distributions of an application server, potentionally mixing in other OS projects (eg. cometd.org, Atomikos JTA and activeMQ JMS).   Thus Jetty will be able to be consumed as components from either maven or eclipse repositories, or as a complete product from codehaus downloads.

    Some components previously built and released with Jetty are being spun out to their own projects or at least modules with their own release cycles.  The cometd implementation has already moved from the contrib repository to the cometd.org project of the Dojo Foundation.

    Jetty will remain apache 2.0 licensed, but the ECL will be added as a dual license so that Jetty may be used and distributed under the terms of either.

    Why the change?

    The move to eclipse was motivated for a variety of reasons that affect all parties concerned:

    Good for Jetty:

    New Ideas and Requirements

    Change is good! It prevents a project from becoming static and complacent. Exposing jetty to new communities, new requirements and new environments will give us an opportunity to continue to improve jetty or validate that it is still relevant and well targeted.

    Improved process

    The eclipse foundation offers jetty improved processes for building and distributing components. The improvements are both legal and technical. Legally, The IP status of Jetty will be greatly improved by the rigour of the eclipse contribution processes. Technically, the eclipse packaging processes have highlighted a number of issues:

    • Too much software was included in each jetty release. Every release was releasing everything from utility libraries and protocol engines, through the servlet container and to specific servlets frameworks like cometd. Many of these components need their own release lifecycles.
    • The module inter dependencies had some issues like the jetty HTTP client depended on the Jetty HTTP server.
    • Some java package where split over multiple jars, preventing reasonable OSGi usage.

    Community

    The move to eclipse will grow the jetty community. The OSGi and eclipse runtime community, already significant jetty users, will be brought into the process of developing and enhancing Jetty. Hopefully new contributions, contributors an corporate sponsorship will result.

    Publicity

    The move generates publicity for the project, which is good in attracting attention to the latest features and developments.  Publicity also helps the commercial interests that sponsor the development of Jetty and of those who use Jetty.  We would like to use this publicity to increase awareness of the asynchronous HTTP client components with in jetty, so that the jetty project is seen as the source of a HTTP server, HTTP client and Servlet container.

    Good for eclipse:

    New Ideas and Requirements

    The Jetty project and community will bring new ideas and requirements to the eclipse runtime community and through it to the OSGi community. For example, the OSGi HTTP Service has been stuck at servlet 2.2 level for a number of years and the Jetty project is keen to see how we can help move equinox and/or the standard onto a more recent HTTP feature set.

    Validate process

    The extensive processes of eclipse are tested by the contribution of a large project like Jetty. The issues already found and fixed in Jetty validate these processes, while the pain points of the process (ipzilla) reveal where they may need to be improved.

    Community

    Jetty will bring hundreds of thousand of new users to the eclipse community, many of whom would have been unaware that eclipse is more than just an IDE and that there is a foundation behind it and that the foundation has an already significant runtime project.

    Publicity

    Eclipse is much more than the eclipse IDE. The eclipse foundation is an open source community focused on building an open development platform comprised of
    extensible frameworks, tools and runtimes for building, deploying and managing software across the lifecycle. By joining the eclipse runtime project, Jetty will help improve awareness of the eclipse offerings above and beyond the IDE.

    What next?

    The Jetty 6.x version of Jetty will remain at codehausand will continueu to be maintained and supported for some time.  The Jetty 7 code base has now been moved to eclipse and will initially be focused on providing repackage version of the capabilities of Jetty 6.x. Due to the delays in the release of a stable 3.0 servlet API, Jetty 7 will now implement the 2.5 servlet specification and is targetting a Q2 2009 stable release.  In parallel, a Jetty 8.x development branch will be created that will allow continued development of the servlet 3.0 api version, which will now target Q1 2010 stable release.

    In parallel with the jetty development efforts, the Jetty project team intends to engage the OSGi and eclipse equinox community to work to improve, modernize and standardize the OSGi HTTP service for deploying OSGi bundles as web applications that can access the full features of Jetty without the need to assemble a java EE war file.

    Thanks to all contributors and users of Jetty who continue to make this an evolving and dynamic project.

  • Cometd Acknowledged Message Extension

    With the release of the latest cometd-jetty in Jetty 6.1.15, the oft requested feature of reliable message delivery is now supported by the Acknowledged Message Extension in the jetty server and in the dojo and jquery clients.

    The initial concept of cometd was to provide "web quality" communications between the server and the browser, ie it was not intended to provide a reliable, transactional and/or atomic delivery of messages. The premise was that if your network failed, then messages can be lost. While this is sufficient for many applications, it is not sufficient for many others. Luckily, the Bayeux protocol implemented by cometd provides for an extension mechanism, which cometd-jetty, cometd-dojox and cometd-jquery have now used to provide an acknowledged message mechanism for reliable message delivery.

    Server side

    To enable cometd-jetty support for acknowledged messages, the extension must be added to the bayeux instance during initialization:

      bayeux.addExtension(new AcknowledgedMessagesExtension());

     

    The AcknowledgedMessageExtension is a per server extension that monitors handshakes from new clients, looking to see if they also support the acknowledged message extension and then adds the AcknowledgedMessagesClientExtension to each client on handshake.

    Once added to a client, the AcknowledgedMessagesClientExtension prevents messages being delivered on any request other than a /meta/connect so to prevent the possibility of out of order delivery. The extension also maintains a list of unacked messages and intercepts the /meta/connect traffic to insert and check ack IDs.

    Dojox Client

    The clients side for dojo is provided by dojox/cometd/ack.js which was released in dojo 1.3.0b2 (but can also be applied to dojo 1.2.x). To enable client side the dojo requires mechanism is used:

      dojo.require("dojox.cometd.ack");

    This is sufficient to enable the extension, however it may then be programmatically disable/enabled before initialization by setting the ackEnabled boolean field:

      dojox.cometd.ackEnabled = (dojo.query("#ackInit").attr("checked") == "true");
    dojox.cometd.init(cometdUrl);

     

    JQuery Client

    The client side for jquery is enabled by including the jquery.cometd-ack.js file (bundled with jetty 6.1.15):

      <script type="text/javascript" src="../../jquery/jquery.cometd.js"></script>

     

    Details

    In order to enable message acknowledgement, both client and server must indicate that they support message acknowledgement. This is negotiated during handshake. On handshake, the client sends "ext":{"ack": "true"} to indicate that it supports message acknowledgement. If the server also supports message acknowledgment, it likewise replies with "ext":{"ack": "true"}.

    The extension does not insert ack IDs to every message, as this would impose a significant burden on the server for messages sent to multiple clients (which would need to be reserialized to json for each client). Instead the ack id is inserted in the ext field of the /meta/connect messages that are associated with message delivery. Each /meta/connect request contains the ack ID of the last received ack response: "ext":{"ack": 42}. Similarly, each ack response contains an ext ack ID that uniquely identifies the batch of responses sent.

    If a /meta/connect message is received with an ackId lower that any unacknowledged messages held by the extension, then these messages are requeued prior to any more recently queued messages and the /meta/connect response sent with a new ack ID.

    Demo

    There is an example of acknowledged messages in the dojox chat demo that comes bundled with cometd-jetty.

    To run the demo, download the Jetty implementation of cometd, then:

      cd contrib/cometd/demo
    mvn jetty:run

    Point your browser to http://localhost:8080/examples/chat/ and make sure to check "Enable reliable messaging?".

    Use two different browsers instances to initial a chat session, then briefly disconnect one browser from the network (work offline option will do this). While one browser is disconnected, type some chat in the other browser and this will be received when the disconnected browser is reconnected to the network.

    Note that if the disconnected browser is disconnected for in excess of maxInterval (default 10s), then the client will be timed out and the unacknowledged queue discarded.

  • jetty @ eclipse updates

    As avid users of jetty are bound to have caught wind of, jetty7 is in the process of migrating to the Eclipse Foundation as a component of the Eclipse Runtime. We even already have our own happy little news group which we need to get into the habit of checking and using more. The milestone in the process we have in sight right now is the next Creation Review date which is March 11, 2009. We are ironing out the requirements for a successful review and all indications are positive on that note. Oh, and one of the requirements that we have two mentors that are on the Architectural Council, the first already being Jeff McAffer of EclipseSource fame and the most recent being Bjorn Freeman-Benson of the Eclipse Foundation itself. Couldn’t be happier having them on board for this process, makes life ever so much more straight forward.
    Regardless, once we have the source in its new home we’ll have to adjust to some new processes and work out some sort of arrangement for managing jetty7 and jetty6 across two svn repositories and two bug tracking systems. It shouldn’t be terrible as we are planning on slowing feature additions to jetty6 and get it into a more methodical maintenance release schedule. Of particular interest is how we are going to manage snapshot development for jetty7 as eclipse doesn’t have the infrastructure for that maven setup, at least as far as I have seen. Could be we make use of Nexus at oss.sonatype.com for that as it has been quite useful for dojo and cometd as of late.
    A big thing that I think is important to note over and over again is that Jetty will be dual licensed once it goes into the Eclipse Foundation, taking on both the EPL and the ASL as options for use. So no bait and switch tactics or anything like that going on here, it is only adding an additional option to the mix.
    It is probably also good to note that we have started the IP review process up for the lion share of jetty that will be going to eclipse. In preparation for that we recently shifted around the basic structure of jetty in svn trunk to a new flatter structure that is more typical of maven projects. We also started factoring out some of the larger jetty artifacts, creating jetty-io and jetty-http artifacts that allow us to clean up the dependency tree a little bit since we added in the asynchronous jetty-client a while back.
    Not all jetty artifacts of old will be going to the Eclipse Foundation. A lot of the third party integrations and things like that will be remaining at The Codehaus and will be packaged into another form of jetty distribution…likely something similar to the existing Hightide release which rolls together jetty integrations into an easy download bundle. A lot of those details will be worked out shortly after we get jetty into eclipse svn and the jetty7 development environment stabilizes some. We are still targeting to get our first jetty7 release out along with the release of the servlet-api 3.0 release sometime around JavaOne. Obviously we have a lot of details to iron out with jetty7’s new home and how it integrates with the packages remaining at The Codehaus. One thing that will not change is jetty releases being in the central maven repository. Jetty7 will be available in the central repository, simply under different coordinates.
    Amoung the other issues we have to work out is JSP. While it is not critical for the initial import of jetty into eclipse, eventually we are going to need to offer jsp support from jetty in the osgi bundles that we are going to produce. Sadly there is currently no ‘perfect’ solution for this that I at least know of. Currently in jetty we are checking out the glassfish jsp api and implementation, applying some patches and fixed it up to work with the jetty logging mechanics and then releasing those artifacts in the org.mortbay.jetty:jsp-api-2.1-glassfish coordinates. To do that under the eclipse umbrella we would have get the glassfish jsp source run through the eclipse IP verification process, which is not a task I particularly relish at the moment. Perhaps in a month or two I won’t be quite as leery of the idea, but for now that is an issue we are firmly passing on until we have the host of other process related issues resolved.
    Anyway, once any or all of these details clear up we’ll make sure people know via the mailing lists, blogs and of course our handy dandy shiny eclipse.jetty newsgroup.

  • w00t! netcraft survey results

    The results are in for the Febuary 2009 Netcraft Survey and the news is great for Jetty! In January the sites reported using Jetty was at 258k and this month it is at over 289k! That is an increase of over 31k sites in just a month. Sure results vary from month to month as different hosting solutions change back and forth between competing technologies, but it is always nice to see a solid increase for Jetty.
    For comparison, Netcraft now lists Jetty at about 70 percent of Tomcat, and 120% of Resin. Sometimes we get asked if jetty is used in production deployment…um. YES!
    Anyway, wonderful news for Jetty especially on the cusp of the migration of Jetty7 to the Eclipse Foundation which I’ll give an update on the status for in a subsequent blog entry soon.

  • Cometd Grails plugin

    Mingfai Ma has created a grails cometd plugin that combines grails 1.1, jetty-6.1 and cometd 6.1.12 to provide spring based grails application environment.
    Because of the great integration between groovy and java, the java server side Bayeux API may be used to subscribe to channels and have messages delivered to groovy handlers.
    For more details see http://www.grails.org/Cometd+Plugin

  • Servlet 3.0 Public Review : Update

    After my blog on the Servlet 3.0 Public Review, I have been working on an implementation of the Servlet-3.0 asynchronous servlets with some the fixes/extensions I suggested in my previous blog and from some continuing discussion within the EG.  Specifically:

    • A new ASYNC DispatcherType for redispatched asynchronous requests 
    • The isAsyncStarted() method is false when a request is redispatched.
    • An IllegalStateException is thrown is startAsync() or startAsync(request.response) are called if getReader() or getOutputStream() have been called.  This restricts asynchronous handler to the simpler cases.
    • If asynchronous mode was started with startAsync(request,response), then it is an IllegalStateException to use any of the forward(…) methods on AsyncContext. This avoids the complication of redispatching wrappers, but allows wrappers to be used by asynchronous handlers.
    • The forward(path) and forward(context,path) methods have not been implemented.

    This code is checked into a branch of Jetty and branch of the servlet-api. It includes implementations of following asynchronous filters/servlets:

    • The ChatServlet demo provides a simple chat room in a single class, using startAsync() and forward().
    • The Cometd implementation and AsyncRestServlet demo have also been updated to use startAsync() and forward().
    • The AsyncProxyServlet used the startAsync(request,response) and complete() style, together with the jetty asynchronous client.
    • The QoSFilter has been updated to use startAsync() and forward()
    • The GzipFilter has been updated to handle down stream code calling either startAsync() or startAsync(request,response).
    • The Dump servlet has a number of async test parameters used in automated and manual tests.

    This implementation has been vastely more succesful than my abandoned attempt to implement the pure PR proposal. It shows that with a few reasonable extensions and restrictions, that a capable and usable asynchronous API is possible (albiet a little more complex than truly neccessary).   Highlights of this implementation include:

    • It supports both wrapper-less startAsync() to forward() style
    • It supports wrapper preserving startAsync(req,res) to complete() style.
    • The GzipFilter can be applied to the ChatServlet (or similar apps) and will successfully gzip responses above a configured size, even on redispatched requests.  You can test it with short chat sentances being sent in the clear and longer ones being gzipped.
    • The GzipFilter can be applied to the AsyncProxyServlet, so that wrappers are preserved and responses obtained from the proxied server are gzipped as they are proxied.
    • QoSFilter can be applied to normal code or asynchronous code.
    • The Dump servlet async tests word even when accessed via RequestDispatcher forwards calls.

    While more testing is needed, this implementation demonstrates that significant asynchronous behaviour can be implemented without the complexities of redispatching wrapped requests or the forward(path) methods.  I believe it represents a reasonable compromise for 3.0.  If additional features are required, surely they can be added in 3.1 after we have gained experience with a simpler subset from 3.0?
    To criticize my own work, I would say that the use of ISE to restrict behaviour is a little ugly.  It would better if startAsync() and startAsync(req,res) had different return types to represent the different styles, but I have used ISE to keep this as a minimal set of changes to the PR proposal to achieve the desired semantics.
     
     

  • Servlet 3.0 Public Review

    JSR-315: JCP Failings

    JSR-315 has produced a Public Review (PR) of the servlet 3.0 specification, which unfortunately is a poor document and the product of a discordant expert group (EG) working within a flawed process.  I  know this article will be read as a criticism of my fellow EG
    members, however I genuinely feel that the failings are mostly those of the
    process that we have been put in, combined with a touch of arrogance on
    all our parts to believe that strength of our experience and opinions alone can overcome
    the deficiencies of the process.  However, whatever the deficiencies of process, JSR-315 has produced a draft specification that has some significant technical flaws, not the least with pluggability and asynchronous servlets. The EG is desperately in need of community feedback and probably another round of Public Review after a beta RI is made available.

    Thought Experiments: No working prototypes.

    Unlike the IETF RFC tradition of  pragmatic, experience-driven, after-the-fact
    standards authorship, the JCP as applied to JSR-315 has no such tradition nor is a reference implementation required by the JCP until after the public review is completed and just before sending the
    specification to the responsible EC for final approval. This public draft of the servlet-3.0 represents a thought experiment in API design unhindered by the complexities of implementation, trial usage or community feedback.  As a member of this Expert Group, I’ve been as guilty as the other members by looking at uncompiled/untested APIs and believing them to solve the issues at hand, only to later discover that these APIs prove to be unworkable when implemented and/or used. It is entirely unacceptable that such a significant revision of one of the corner stones of Java Application development is being put forward almost completely untried and untested. Requests for test implementations have been denied and my own partial implementation in a jetty branch, has revealed significant unresolved problems.

    Consultation: these are not the droids…

    There is no open or considered mechanism to collect requirements from the community and precious little community consultation. The deliberations of the EG are not open and it is difficult to obtain community feedback. Any feedback received on the jsr-315-comments@jcp.org list have been kept private and not shared even with the EG, despite several requests. Without any true representation of community concerns, it is too easy for concerns to be discounted. For example, several EG members and community feedback raised concerns about the security and ordering aspects of the automatic deployment possible with the  Annotations and Pluggability feature (see below).  The response was not the “How can we address these concerns” discussion that I was expecting.   Instead the response was more along the lines of Obe-wan Kenobi saying “these are not the concerns you are looking for. Move along!”
    Alternately, some unsubstantiated requirements (eg. wrapped asynchronous requests) have been included at a late stage without any use-cases or user demand, which have introduced whole new dimensions of complexity so that discussions have been ratholed for months chasing marginal edge cases.

    Precision: ambiguous language

    When one reads a IETF JSR the language used is precise and codified, and they are full of state machines and interaction diagrams.  This is not the style of most JCP produced specifications, which are instead full of prose that frequently looks like it has been written by engineers for whom a two line comment is a challenge (myself included). Within the servlet EG, our efforts to formulate the future of the specification are often hampered by our inability to fully comprehend what we wrote last time around.  This lack of precision works to prevent true consensus being formed, as participants often think that an approach has been agreed, only to later discover that that multiple conflicting interpretations of the proposals exist and that issues thought to be resolved are not.

    JCP or JSR Failings?

    I am only a member of the JSR-315 EG, so I do not know if these failings are truly general to the JCP or just specific problems for the Servlet JSR. However, whatever their generality, these failings have resulted in a seriously compromised Public Draft specification and I suspect the problems I describe below are only the tip of the iceberg and that more issues will be revealed by real testing.

    Annotations and pluggability

    The ED of JSR-315 introduced three new mechanisms designed to make it simpler to plugin web frameworks to a web application so that placing a JAR file into WEB-INF lib is all that is required to instantiate a web framework and to initialize a default configuration:

    1. Additional annotations
      have been defined so as to be able to configure filters and servlets entirely
      from annotations of classes contained within WEB-INF/lib or
      WEB-INF/classes
    2. Support for web.xml
      fragments to be included in the /META-INF directory of jar files within
      WEB-INF/lib.  These web fragments are combined with the web.xml with
      well defined merging rules (already mostly defined when arbitrary
      element ordering was supported in 2.5 web.xml)
    3. Programmatic
      configuration of Filters and Servlets via new methods on
      ServletContext.  These methods are only active when called from a
      Listener class defined either in a web.xml fragment or discovered TLD
      file (but can execute arbitrary code as well as calling the new APIs).

    These are good new features and could address some long standing pain points of web application development, not least the contention of editing multiple concerns into a single web.xml. Unfortunately the many concerns raised with the early draft have not be addressed and the EG members and community who have raised them have simply been told not to be concerned with issues such as:

    • Accidental Deployment: Web applications can
      contain many many third party jars and a annotation, web fragment or TLD listener in any them will result in arbitrary code being executed and the deployment of servlet and filters. These servlets and filters may well be harmless debugging aids or admin UIs that the framework developers thought useful or they may be hacker attacks buried deep inside jars imported as transitive dependencies. The automagic nature of the pluggability features now requires that deployers perform a whole new level of due diligence before deploying or upgrading any jars within a web application. Tools will not be able to
      greatly assist with this process as the analysis of the programmatic
      configuration of listeners is a NP-complete problem and never again will we be 100% sure of what servlets can be deployed unless we 100% understand all the source code of all the jars within a web application! 
      These features do not give attackers any new ways of injecting hostile code into a web application, however they do provide  new mechanisms to execute  any code they manage to inject and that code will be able to easily open access through corporate firewalls or filter all web traffic!
      The only solution available to those concerned about accidental deployment is to turn off all these features with meta-data complete and get no benefit from them at all.
    • Slow Deployment: Web applications can
      contain many many third party jars. Already with TLD scanning, web containers need horrible NO TLD JARs configuration to reduce the time to deploy a web application to something reasonable. Now with scans of every class for annotations, such hacks will become even more important. 
    • Ordering:
      The ordering of auto discovered configuration was not defined in the ED. Those that raised the concern were told that their proposed solution was too complex and that a solution was in the works.  After months of waiting, the solution was finally revealed with this text from the PD: “The order in which configuration settings of web fragments are added to those in the main web.xml is undefined.”!  Great! So if you wish to plug in a security framework (eg acegi) with a Ajax framework (eg DWR), then you cannot specify order unless you disable pluggability and copy all the configuration into a single web.xml
    • Parameterization: WAR files have often been criticized for having configuration baked into the jar file, with a frequent complaint being that a war file needs to be unzipped, simply to change a few parameters within the web.xml and then zipped up again. Apart from being a PITA, this need to edit a deployment unit is bad practice!   These features exacerbate this issue, as configuration can now be baked into a jar file that itself is baked into a WAR file.  If the default configuration is unacceptable, then a deployer can either disable the features and copy everything into a web.xml (assuming they know what “everything” is), or they can unzip the war to unzip the jar to edit the webfragments contained within.  Of course such editing will blow away any attempts to use checksums or signatures to check for any changes that might result in accidental deployments!

    When raising these concerns, several EG members proposed several solutions based on giving the web application the optional ability to participate via a standard configuration in the selection of which jars to scan and/or ignore and to possibly pass parameters to those jars.  Such proposals would address all the concerns listed above and such mechanisms ALREADY exist in most containers, yet it was decided it
    was too complicated to expose users to such choice, and far better to
    keep such configuration buried in static code or non-standard
    configuration
    .
    It is not sufficient to respond to such concerns by saying we need not be concerned.  I am concerned, members of the jetty community are concerned, obviously those that implemented noTldJars in Tomcat and Glassfish are concerned, many commenters on The Server Side are concerned.  Yet all proposals to address these concerns were dismissed simply as not needed and/or too complex. No counter proposals were forthcoming, so these potentially useful features will be disabled by a large proportion of users and should be disabled by many more.
    Note that these are only the issues discovered by reading the specification.
    I’m sure if somebody actually implements these features and tries to
    test them, additional issues will be discovered. Unfortunately, the one
    framework developer on the EG was denied when he offered to test these
    features before their inclusion in the spec, since there is no available implementation.

    Asychronous Servlets

    Early Draft Version

    The early draft of JSR-315 Servlet 3.0 specification contained a proposal for asynchronous servlets that was developed based on my experience with Jetty Continuations and has been available as a trial implementation in the pre-releases of Jetty-7 since March 2008 which has been tested by many frameworks and applications, including cometd, DWR, JSF and BlazeDS.   The proposal involved new methods on the ServletRequest class:

    interface ServletRequest{    void suspend(long timeoutMs);    void suspend();    void resume();    void complete();    boolean isSuspended();    boolean isResumed();    boolean isTimeout();    boolean isInitial();    ...}

    As well as the specification and javadoc, I’ve demonstrated the usage of these methods in Jetty-7 and in my blogs on asynchronous use-cases and patterns. As far as I know (and I have asked), no negative feedback at all was received on the jsr-315-comments@jcp.org, while I have seen some very positive public feedback (eg DWR, JSF and BlazeDS).  While the proposal could certainly have been improved (see below), it was a very encouraging start.
    However, after Javaone,  a campaign was begun for an alternative asynchronous proposal. While I welcome alternatives, this one was based on criticisms of the ED proposal that were factually incorrect (eg. that all requests would need to be wrapped or that redispatching is new and unnecessary behaviour). Even though these criticisms were  completely rebutted (not least by Sun’s own JSF project providing a lifecycle to use suspend/resume without the need for any framework changes) and later retracted, they were used as an basis of an effective veto of the ED proposal, based on it’s use of redispatch semantics.

    I would have expected to have
    been given the opportunity to refine the ED proposal, but for a period of time any proposal that included redispatch semantics was completely rejected. This veto resulted in the bizarre positions that asynchronous servlets would have been able to generate a response using any technique they liked EXCEPT by dispatching to a servlet engine.  Of course this argument could not be sustained and eventually redispatch semantics has come back into the all active proposals, but only after the ED proposal had been killed off.

    So rather than building on the tried and tested ED proposal,  the proposal in the PR proposal represent a snapshot of one of the alternative proposals that have been developed as thought experiments without any implementations or test code. In my desire to find consensus, I have been supportive of some of the alternative proposal and have participated in the thought experiments. Unfortunately I had fallen victim to the same hubris that I
    criticize the EG of, and subsequent attempts to implement these proposal have revealed significant problems.

    Public Review Version

    The proposal in the Public Review grew out of a failed attempt to use RequestDispatchers as the asynchronous redispatch mechanism. Significant effort has been put into the PR proposal to try to make it handle all concerns raised but  unfortunately it has become a Frankenstein monster, cobbled together from eviscerated good ideas and misguided best intentions. The 8 methods of the ED proposal that were rejected as being too
    complex and confusing have been replaced by 20 methods and 3 new
    interfaces!
    The PR proposal is based on a AsyncContext class that is obtained from a request by calling a startAsync method together with a slightly torturous timeout mechanism:

    interface ServletRequest{    boolean isAsyncSupported();    AsyncContext startAsync();    AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse);    boolean isAsyncStarted();
        AsyncContext getAsyncContext();    void addAsyncListener(AsyncListener listener);    void addAsyncListener(AsyncListener listener,ServletRequest servletRequest,ServletResponse servletResponse);    void setAsyncTimeout(long timeout);    ...}
    interface AsyncContext{       ServletRequest getRequest();    ServletResponse getResponse();    boolean hasOriginalRequestAndResponse();    void forward();    void forward(String path);    void forward(ServletContext context, String path);    void complete();    void start(Runnable run);}
    interface AsyncListener{       void onComplete(AsyncEvent event) throws IOException;    void onTimeout(AsyncEvent event) throws IOException;}
    class AsyncEvent{    ServletRequest getRequest();    ServletResponse getResponse();}

    The key features that this proposal is based on are:

    • that asynchronous filters/servlets should have the option to preserve the request/response wrappers applied to a request for use either by asynchronous handlers or by a redispatched request.
    • that redispatch asynchronous requests should use RequestDispatcher forward semantics and may be dispatched to  different contexts and/or paths than the original request.

    These features were added as requirements without any supporting use-cases and without any user demand. At best they can be looked at as nice to haves.  Yet they both introduce incredible complexity that we have only just started to fathom.  The result has been that discussions have been ratholed for months chasing these unjustified edge cases.

    Why keep wrappers?
    One of the prime motivations of asynchronous programming – indeed THE prime motivation, is to avoid holding resources when you are not doing anything! So why keep wrappers during asynchronous handling of a HTTP request?  They will only be holding resources (buffers, Gzip encoders, JDBC connections, UserTransactions etc.) that would be better off returned to a pool or GC.  If the redispatched request needs those wrappers, then reapply them during redispatch.  If it is too expensive to wrap twice, then suspend the request before you wrap them the first time.
    The cost to support asynchronous wrappers is extreme, as it costs us the sanctity of the try{} finally {}! Typically filters that apply wrappers can clean up those wrappers in finally block, knowing with 100% certainty that their code will be called when the wrapper is no longer applied.  The general pattern of such a filter is:

    class MyFilter implements Filter{  public void doFilter(ServletRequest req,ServletResponse res,FilterChain chain)  {    MyResponseWrapper wres= new MyResponseWrapper(res);    try    {      chain.doFilter(req,wres);    }    finally    {      wres.finish();    }}

    But with the PR proposal, this common pattern is no longer sufficient.  A wrapper can be passed to an asynchronous handler in a startAsync(req,res) call and if so, it should not be “finish”ed in the finally block. Thus all well written filters that wrap request or responses will have to allow for this by code that looks like:

    class MyFilter implements Filter{  public void doFilter(ServletRequest req,ServletResponse res,FilterChain chain)  {    MyResponseWrapper wres= new MyResponseWrapper(res);    try    {      chain.doFilter(req,wres);    }    finally    {      if (request.isAsyncStarted() && !req.getAsyncDispatcher().hasOriginalRequestAndResponse()            {          req.addListener(new MyFilterAsyncListener()           {            public void onComplete(AsyncEvent ev)            {              ((MyResponseWrapper)ev.getServletResponse()).finish();            }           },req,wres);      }      else        wres.finish();    }  }}

    This is for code that does not even use asynchronous features!  It must be implemented by a filter simply so it can work with other filters/servlets that might use asynchronous features and that might want to keep wrappers for some not-as-yet identified use-case!!! The advocates of wrapping asynchronous requests talk about starting producing a respons synchronously in a servlet and then passing control to an asynchronous handler and preserving the state of the wrappers – but they cannot answer the question why one would want to program in such a way or why the servlet spec should support it?
    The sanctity of try{} finally {} should not be broken for such a marginal use-case and wrappers should only be valid within the scope of the filters/servlets they are dispatched to. If the cost is that wrappers cannot be held between async dispatches, then it is a small price to pay keep an important programming paradigm intact!
    Why forward?
    During the development of the PR proposal, at one stage normal RequestDispatchers were proposed as the asynchronous redispatch mechanism.  This initially attractive idea falls down because the threading model is wrong and dispatchers are designed with the assumption that they are called from an already dispatched filter or servlet.  Unfortunately, which the use of RequestDispatchers was dropped, the desire to forward asynchronous requests to another path or another context was not and forward semantics has been adopted as the semantics of asynchronous redispatch.
    Why one would want to forward to another path is beyond me, and forwarding to another context from an asynchronous handler is verging on scary. But if there was a use-case for such a thing (and none has been identified), it would have been trivial with the ED suspend/resume proposal to resume the request and then use the normal RequestDispatcher mechanism to direct the request to the desired handler (there appear to be no efficiency gains from forwarding and then resuming rather than resuming and then forwarding!).
    But the problem is that even if forward() is used and the path is not changed, forward semantics are used for the redispatch. Apart from the wasteful setting of 5 javax.servlet.forward.* attributes, this semantic means that asynchronous dispatches bypass filters that are not marked for FORWARD dispatches.  If in response, you then configure your filters so that they do apply to FORWARD dispatches, then there is no way to tell if a request is being forwarded normally or has been asynchronously forwarded.  For example, if you want a GzipFilter to apply to asynchronous dispatches, it is very difficult to avoid double wrapping normal forwards.  If it was thought that redispatching as a normal request was too confusing for developers, I cannot see how mixing asynchronous dispatches with normal forwards is any less confusing!
    Allowing asynchronous forwards is a feature in search of a use-case.  There is no identified need for it and it is the cause of considerable confusion and complexity in the PR proposal.
    Only Simple examples work!
    With these issues, it is possible to create a few simple examples that work well enough stand alone. However, as soon as you try to combine these examples with other asynchronous concerns (eg QoS) or even simple GzipFilters, these issues soon become apparent and I’ve been unable to reimplement most of the async fuctionality demonstrated   against the ED.

    Improving the Early Draft proposal.

    While I believe the ED proposal was fundamentally sound, the EG did indeed highlight some issues and the alternative proposals do include good ideas.  Thus I’d like to examine what the API could have looked like if we had applied the expertise of the EG towards refining the tried and tested EG solution. The issues with the ED that were identified include:

    • Bad names. While I don’t particularly like “startAsync”, I do concede that “suspend” and “resume” are overloaded terms and could imply behaviour that is not supported. 
    • Dispatch Type. While I’m not 100% convinced and many frameworks
      have coped, I can see the argument that mixing resume dispatches with
      normal request dispatches could be confusing and isInitial() was an
      in-elegant way to deal with separation of those mixed concerns. A
      better approach would be to create an entirely new dispatch type for
      async and timeout dispatches with a method on the request to query the dispatch
      type (which would be generally useful anyway). 
    • Resume Race.  A common programming bug with suspend/resume is to write code that looks like:
      if (shouldSuspend()){  MyAsyncHandler ah = new MyAsyncHandler(request);  request.suspend();  return;}

      but this code contains a race, as the MyAsyncHandler can attempt to resume the request before suspend is called. The fix is to call suspend before creating the async handler, but that can read a little unnaturally. Having the resume method on an object returned by the suspend avoids the possibility of this race.

    • Difficult Debug. Code that was developed before asynchronous servlets could fail in hard to diagnose ways if combined with filters/servlets that are using asynchronous techniques. The PR proposal contains isAsyncSupported mechanism to allow servlets/filters to declare that they have been tested with asynchronous features and to generate meaningful errors if code is unknowingly exposed to asynchronous requests.
    • Wrapped Requests. Asynchronous handlers could be passed references wrapped requests that would be destroyed in their filters finally blocks. The use of AsyncContext bypasses such wrappers.

    These issue can be fixed in ED proposal without throwing out the basic principal: that the servlet spec well defines behaviour within a dispatch to a filter/servlet and that rather than invent a new contexts for application code to execute in, it is far better to dispatch back to the well define servlet container in the most simple manner possible and to thus build on a decade of experience with filters and servlets.   The evolved ED proposal looks remarkably like the PR proposal, but without the distraction of wrappers and forwards.

    interface ServletRequest{    DispatcherType getDispatcherType();    boolean isAsyncSupported();    AsyncRequest startAsync(long timeoutMs);    AsyncRequest startAsync();    boolean isAsyncStarted();    AsyncContext getAsyncContext();    ...}
    interface AsyncContext{      ServletRequest getRequest();    ServletResponse getResponse();        void dispatch();    void complete();}
    public enum DispatcherType {    REQUEST,    ASYNC,    TIMEOUT,    FORWARD,    INCLUDE,    ERROR}

    Note the DispatcherType enum is already part of the PR specification for other reasons, and only the ASYNC and TIMEOUT types have been added to it.
    This evolution of the ED proposal builds on all the testing and experience gained, while fixing some important issues. It does not support wrappers or forwards, but nobody has been able to cite a use case that justified either. If use-cases were identified, then I’m confident that the  ED API could be further revised to meet those use-cases without the need for wrappers or forwards. Surely if wrappers and forwards features prove necessary, they could be introduced in a 3.1 servlet spec after we have gained experience with the core asynchronous principals?
    I plan to have an implementation of this revised ED proposal available in a branch of Jetty within a few days and will be proposing that this be the basis of a second PR of the specification.

    Conclusion

    These are important matters that will have long lasting effects. The API decided by JSR-315 will be with us for many years to come and will affect the evolution of java web applications and potentially the rest of our programming careers.   It’s not something that we want to get wrong, or even just approximately right.
    I believe significant errors are being made in the current PR and that the flaws in the process have been enough to prevent the application of due diligence sufficiently for these flaws to become self evident. While I have received support in the EG with the debate on these issues, I have been unable to convince the spec lead of their validity and I have probably not helped the cause by some over-vigorous participation in the debate.
    However, the JCP is the Java COMMUNITY Process. So where I have failed to make the case, the community now has an opportunity to make it for me (or indeed to correct me in the error of my ways). If you are reading this, then you are part of the community!  If you ever wish to complain about these APIs, then now is your chance to contribute to the process (or at least take the I-told-you-so moral high ground):

    The EG is desperately in need of community feedback and probably
    another round of Public Review after a beta RI is made available.