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.


23 Comments

Greg Wilkins · 15/12/2008 at 19:47

  • Jetty will of course implement the standard no matter what.
  • Users of existing Jetty supported async frameworks (eg Cometd, DWR) will be shielded from any API changes.
  • Regardless of the API, Jetty will continue to have the best implementation under the hood!

Eduardo Pelegri-Llopart · 16/12/2008 at 05:56

Hi Greg, and other readers – Rajiv will be providing an overview of the Servlet 3.0 PRD this Thursday at [1]. It is not the ideal forum, in part because the time is 11am PT – too early for you – and in part because the slot is short, but I’d encourage you to post questions and concerns to the Wiki page and chat. Even if we can just record them they may be a way to queue in longer discussions later.
– eduard/o
[1]http://wikis.sun.com/display/TheAquarium/JavaEE+6+And+Servlet+3.0

Rajiv Mordani's Blog · 16/12/2008 at 07:35

[Trackback] Someone just pointed me to Greg Wilkin’s latest blog entry. I tried posting my response in his comments however it was tagged as spam and not displayed. So I am making the comments available her. I am REALLY surprised at…

Rajiv Mordani · 16/12/2008 at 07:37

This is Rajiv Mordani, the specification lead for Servlet 3.0. I tried to answer some of the issues that Greg has raised in this blog via his comments however it was tagged as spam by the software cos it was more than 1000 characters. I have posted my response in my blog

Maxim Moldenhauer · 16/12/2008 at 18:09

I too had difficultly posting a reasonable sized response so go see my full response here.
We have discussed some of the use cases on the EG for things you have said do not have use cases. However, they are not in the Servlet spec and I think they should be. Also, I think your criticism of the JCP should be separate from your arguments about the Servlet spec. They are two different issues and when they are put together it just invites more defensiveness on the part of folks who have a higher interest in making JCP successful. Fixing the JCP is not something that’s going to be fixed before we decide on a Final Draft, so I hope we can simply focus on the servlet issues at hand…

Bill Burke · 16/12/2008 at 22:52

I agree that it is ridiculous that you don’t get the TCK (and sometimes RI) until after the spec is released. There are many weird things that pop up when you certify that could be corrected before the spec goes out. Its also a huge disadvantage commercially for vendors who aren’t the RI. I even waited 77 days to receive the JAX-RS TCK even after it was released because it took forever to amend and then approve our EE license.
All that said though, I don’t think the JCP is a bad place. Maybe now that Sun has embraced OSS, we’ll start to see things open up. I know JAX-RS (aside from the TCK issues) was an excellently run JSR.

Bill Burke · 16/12/2008 at 22:59

Maybe a completely separate API needs to exist for asynchronous servlets. Both an asynchronous filter api and an asynchronous servlet api. Maybe I’m wrong, but it seems that the additions of your original proposal and the new proposal will break existing Filters anyways.

Greg Wilkins · 16/12/2008 at 23:23

Bill,
I definitely think that there should be new separate APIs for asynchronous HTTP (and some are being developed), because any async added to the intrinsically blocking servlet API will always be compromised.

However, there is a large investment in servlets and servlet based technology that can benefit from some asynchronous techniques, and thus I believe it is warranted to add something to the servlet spec.

Hence my focus on the servlet spec has been for the redispatch use-cases, because those are the ones that want to use servlet technology to generate responses. If an async handler can be written without dispatching to a servlet, then perhaps it should be written against new API that has nothing to do with servlets.

Rajiv Mordani · 18/12/2008 at 05:30

Bill,
While I do think that a new API should be there for Async support, it should not be done in a way independent of the NIO2 work. We have talked about this in the EG and have punted on this because we would end up defining a lot of what NIO2 is trying to address and it would be YET another API. Hence in the EG we decided on punt on that in this release from standardizing it in the servlet spec.
Greg however that does NOT translate into the redispatch use cases ONLY. A very simple use case is you want a logging filter to work across the entire life time of the request. I am not sure how that can be done with the redispatch and not using request properties. We have talked about how the use of request attributes becomes an intrinsic part of the solution for the re-dispatch cases and makes the code more complicated in my opinion to maintain for the developer.

Greg Wilkins · 18/12/2008 at 09:00

With the PR proposal, it is indeed difficult to have a logging filter. This is because it mixes async redispatch with forward dispatch, with no way to tell the difference between them.

With the EG proposal, there was isInitial(), so a logging filter could log either initial and/or redispatched requests.

What I’m proposing now is a new dispatch type for ASYNC that would also allow a logging filter to be clear about what kind of requests it was logging, and no request attributes would be needed.

Maxim Moldenhauer · 18/12/2008 at 13:52

I agree we need a new dispatch type at least for filters to differentiate, if not for what the actual dispatch mechanism uses. This is something I proposed a long time ago, and was originally going to be included, but when resume was changed to forward, it was scrapped.

Julian Reschke · 19/12/2008 at 17:09

Hi,
I have tried many times in the past to find out whether the EG is going to work on the servlet API’s inability to properly support the HTTP Expect header, but never got any kind of response. Does anybody happen to know whether there’ll by improvements with respect to that?
Julian

Greg Wilkins · 19/12/2008 at 17:39

Julian,
Jetty currently supports the Expect 100 continue and Expect 102 processing.
For expect 100, we do not send a 100 continue until the servlet actually accesses the input stream. Thus the servlet can consult the headers and send an alternate response without 100 continue.

We support 102 with response.sendError(102) if it is expected.

I have proposed these to JSR-315 and there was some discussion. Unfortunately while there was some support, there was also a few rejections (without suggested alternatives). So it may be in the too hard basket for now, although I’m hopeful that it is on the list of things to consider before final. I’d send your interest again along with any proposed solutions.

Rajiv Mordani · 19/12/2008 at 22:05

GregWilkins: What you are proposing of the ASYNC dispatch type came up in the initial idea and then we talked about it after handing off the PR to include a dispatcher type of ASYNC. So yes that is on the table. However if you don’t keep the wrappers you still don’t get the logging of any kind in the async handler that operates on the request and response.

Rajiv Mordani · 19/12/2008 at 22:06

Julian: Yes we have this on the plate and even though Greg is classifying it in the “too hard” bucket I think we will have something in the spec before it goes final.

Anonymous · 20/12/2008 at 09:14

In an earlier post of yours, you asked for input on autodeploy. I gave this idea.
It seems like it didn’t get much comment – I however still think it has some merit.

Rajiv Mordani · 22/12/2008 at 08:33

Greg Wilkins: Not sure how the ASYNC dispatcher type solves the logging problem. How does the logging filter work WITH forward if you don’t keep the wrappers in the async handler? Effectively you are saying that no logging of any actions on req, res would occur in the async handler?

Greg Wilkins · 22/12/2008 at 15:24

Rajiv,
The ASYNC dispatcher is not intended to help with the issues with wrappers or your suggested logging filter.

It is intended to help with the problem that if you are using startAsync() + forward() and want filters like gzip or logging to apply to the redispatched request, then currently the PR forces you to map your filters to FORWARD. But then there is no way to tell if the request is a real forward or an async forward, so real forwards end up getting 2 gzip wrappers.

Try writing your logging filter against the PR APIs and you will soon see the issue.

Maxim Moldenhauer · 29/12/2008 at 14:25

Endre: I think your idea is reasonable. However, I do not see the need for the config directory you speak of when you can always override in the web.xml. Seems like that is overkill.

Anonymous · 02/01/2009 at 13:56

(NB: I apparently hit some intelligent char count-based “spam detection” stuff. The next posts are one comment)

@Maxim: The config directory is to enable a config file per module.

The reason for this being a good idea is that handling “xml snippets” which then typically will have to be cut and pasted into a huge global config file makes for mess and problems. This happens often for example when you are helping a customer with an installation, tweaking a module’s config, or something like that. Think of the email “Cut and paste the following fragment in the web.xml between the tags such and so”, compared to “stick the included file into the config directory”. It also makes it easier to make suggestions and examples: “this file will do so, while this file will do this”. In a nutshell, it makes this dead simple “modularization by convention” system feel slightly more consistent and “real”: each module has a separate config file.

Anonymous · 02/01/2009 at 13:58

If order is of importance (shouldn’t be often, IMO), using alpha sort and then simply renaming the modules like Unix System V style init (“xxx-smbd”, where xxx is a number) is a simple solution.

Per every parameter, the “path” to its end value can be recorded and displayed in some debug mode and in a “monitor” style servlet.

I implemented this module-suggestion in a “module based” EIP (“Business Portal”) Server I made in a previous job, based on experience with the previous, more “web.xml” like logic that was employed. It worked out pretty well.

Anonymous · 02/01/2009 at 14:00

A little extension to the config dir idea is that only files that have the same name as a module in “autodeploy” will be included, so that forgotten duplicate module configs (with different names) won’t be included – only one config file per module. Indeed, it is possible to implement the value-logic (along with the “path recording” above) so that a certain parameter could only be overridden once in the config dir, and then once in web.xml – duplicate overrides in any stage will not be allowed.

Rounding off, I believe steps towards a way more modular approach to servlets is way overdue. The present idea is a pragmatic and simple stop-gap solution that makes very little change to how it already works by introducing some convention-based startup-logic on the existing system.

Anatole Tartakovsky · 14/01/2009 at 19:54

Greg,
Thank you for your effort to keep async http simple. We are early adopters of that technology for real projects and appreciate your simple and working solutions. While Tomcat API seemed more attractive, we wasted time, money and talent on something that definitely was not finished much less tested or proven to work on ANY real world application. I would rather agree on evolutionary approach driven by real apps:ED now and then extending it in 3.1 in orchestrated OS effort of adding 2-way sockets to the browsers and more control over async process (including QoS layer, message numbering, heartbeats,etc.) to remove all over engineering from the application code.
We will test the claims of new RIs (GlassFish and JBoss) next week as we have client that really need this technology now, but judging from the comments to this thread chances are that implementation will be jetty-based.
Sincerely,
Anatole Tartakovsky

Comments are closed.