Page 6
About interface abuse, DI-infestation and interfaceitis
Page 7
Index
See this article in english 
 

Comments on JSR 315 (Servlets 3.0)

Alexander Hristov

 

23 - Dec- 2008

Recently JSR 315 (Aka "Servlets 3.0") entered its final draft review, and while it is overall good, I have some gripes with it.

General Issues

1) Programmatic parameter manipulation - There are many use cases in which parameter manipulation should be allowed. For example, when we'd like to transparently reuse an existing servlet by dispatching a request to it that happens to need the same processing but lacks some of the parameters that the servlet expects.

Think specifically about a servlet that does a generic search in a database using a very flexible search criterion that comes through parameters. If we later want to predefine some of these searches for the user, we cannot reuse directly that servlet because the expected parameters are not going to be there. Instead, we must resort to complicating the code by storing this data in the request and having the target servlet look for it, or by resorting to clumsy string concatenation to form a new query string when calling getRequestDispatcher(). All this would be solved with the simple addition of a new method to ServletRequest and/or RequestDispatcher:

public void setParameter(String parameterName, String parameterValue);

(if operating on ServletRequest, the scope of the new parameter is the request; if operating on the RequestDispatcher, the scope is only the target servlet)

2) Programmatic login is long overdue. There are literally countless applications that do not use a specific login form, but actually provide user/password fields on any page so that the visitor can log-in at any stage without going to a different form. My success using JAAS for programmatic login has been unequal (some containers recognizes the login, some don't).

I believe the best and most harmless solution would be to specify that the servlet container should process j_security_check requests at any stage. Furthermore, since the servlet container does not have any idea about where to go after a correct login validation takes place, possibly a new parameter (e.g. j_target) could be introduced for these situations. An alternative to this situation would be adding a method for programatic login to ServletRequest, namely

// For common scenarios
public void login(String username, String password); 		

// For generalized scenarios that use other authentication method
public void login(javax.security.auth.Subject subject); 

public void logout();

These methods could throw a security exception if the action cannot be performed (for example, invalid password in the first method)

3) I believe the introduced annotations are a missed oportunity for freeing servlets from the necessity of inheriting a specific class. The rest of the world (even EJB) is moving towards resource injection and POJOs, yet the Servlet specification remains anchored in "extends HttpServlet". This should be reconsidered, and at least an interface should be used instead (or in addition to), but I'm afraid it's too late.

4) Annotatios for security (lack of) . Having said that, @WebServlet should have attributes for restricting the roles of the users that may invoke it and the conditions under which this happens. It would be even more helpful if there was an additional @Security annotation with that info, AND if that annotation could also be specified at package-level (in package-info.java), so that for example one could separate all administrative tasks of some web application into a separate package and annotate that package with a security restriction.

5) I also believe the lame "*" wildcard used in url-patterns should have been replaced long ago by full-fledged regular expressions. To preserve compatibility, I believe the best option would be to add a "regexp" attribute to url-pattern and make it false by default. In this scenario, I could either write

<url-pattern> /admin/* </url-pattern> 

or

<url-pattern regexp="true"> /admin/.*  </url-pattern>
 


6) Ordering of web fragments. Section 8.2.1 - "Modularity of web.xml" of the spec states . "The order in which configuration from web-fragment.xml and annotations should be applied is undefined.". This is completely unacceptable :-( Not only because of all the obvious reasons, but also because defining an order allows some libraries to purposely "overwrite" URLs or filters by other libraries, and thusly provide extended functionality.

7) There should be some mechanism for controlling the inclusion/exclusion of items in web-fragments. I believe that neither the all-or-nothing nor the "copypaste to web.xml" approaches are very useful. Sometimes some servlets or filters may need to be disabled. Some other times I don't have the source code of the framework I'm deploying and I don't necessarily want to trust a .jar blindly. I believe web.xml should be augmented with <include> and <exclude> elements (supporting wildcards) so that I can specify precisely what it is to be included and what not. For example:

<fragments>
   <include path="lib/*.jar" />
   <exclude path="lib/sourceless.jar" />
   <exclude path="lib/fantasticframework.jar">
   <servlet-name>Admin</servlet-name>
   <servlet-name>Install</servlet-name>
   </exclude>
</fragments>
 

8) I believe the programatic deployment of servlets and filters should be removed. It poses a security risk (especially when combined with fragment discovery), and together with JSR 199 (Java Compiler API, which is included in the base java platform) it makes some threats all but undetectable, both manually and by tools. Besides that, in all the time I've programmed web applications (10+ years), I've yet to meet a use case for these methods.

Whatever Struts, Faces, JAXWS or some other framework needs to have mapped, they can do it using the web fragments mechanism.

I also don't buy the nonargument that Rajiv provides on his blog that since there have been no previous problems with JAX-WS, therefore there won't be any problems with this one either. This argument is similar to "we've never had viruses or exploits on MacOSX in the past, therefore there's no need to require permission from the superuser to install kernel mode drivers", and a disaster waiting to happen, not to mention that it conflicts with many existing and established security policies.

The Servlet API is orders of magnitude more popular and used than the JAX-WS API, and used by much less literate programmers than EJBs, not to mention that the market for third-party deployable EJBs is about zero (as opposed to the market for third-party web components and frameworks). While some due diligence is expected on behalf of developers, there comes a point where the provider of an insecure technology is as guilty as those improperly using it.

If, regardless of the previous comments the EG decides to keep those methods anyway, it's been always my experience that whenever there's the need to add stuff, just a bit later the need to remove stuff appears. Therefore if the spec allows filters and servlets to be added, it should also allow for :

removeFilter(...)
removeFilterMappingForUrlPatterns(...)
removeFilterMappingForServletNames(...)
removeServlet(...)

Also, it makes no sense to have add methods but keep getServlets() and such deprecated.

9) I don't understand the big deal with AsyncContext. Ok, I understand it, but I don't see how the most popular use case (Ajax push with thread reuse) is implemented using AsyncContext. Must I manage my own queue of "suspended requests" and walk that queue manually each time something interesting happens? This is akin to coding wait() and notifyAll() by hand. Shouldn't the spec provide a bit of a higher level support for this kind of use case?

10) I miss some support for multipart (specifically, file upload) forms. I believe this is pretty baseline and low-level and it isn't reasonable in 2008 to rely on third-party components for supporting a 1995 RFC.

Specific Issues

And now some specific gripes with the text of specification as released. The numbers below specify the corresponding section of the specification

2.3.3.3, page 11 - "AsycListener" - replace with AsyncListener

2.3.3.3. The "AsyncEvent" class is used twice in the whole spec but never really defined or explained. It is in the Javadoc, but I don't think this is enough.

3.2 - Request Attributes. Method removeAttribute() is not referenced, but it should, in order to be consistent with 4.5, for example ("Context Attributes").

4.4 - Configuration Methods. If they are kept, the specification should clearly say what happens when one tries to add a servlet or a filter that is already present.

5.1 - "The isCommitted method returns a boolean value indicating whether any response bytes have been returned to the client.". This is inconsistent with the JavaDoc, which states
that "Returns a boolean indicating if the response has been committed. A committed response has already had its status code and headers written", and it is also contrary to the
common interpretation of isCommitted. According to the spec, isCommitted() == true does not prohibit sending additional headers, but according to JavaDoc, it does. IMHO it should be redacted to align it with the JavaDoc explanation. If instead you decide that the JavaDoc is incorrect, then there should be a different method to clearly state that the HTTP headers section has not been closed yet and further addition of headers is possible. Actually, I think it would be good to separate the whole committed thing into three different methods:

   - isStatusCommitted()
   - isHeadersCommitted()
   - isContentCommitted()
 

5.1 - "If this is the first data that is sent to the client, the response is considered to be committed.". This should be redacted to match the above comment. After all, a buffer might be filled with only headers (consider a protocol that merely uses HTTP as a transport and greatly expands the HTTP headers section). Buffer flushing should not automatically equate response commitment.

5.3 "The sendRedirect method will set the appropriate headers and content body to redirect the client to a different URL.". IMHO the specification should pin down whether status code 301 or 302 is used. Also, sendRedirect should raise an IllegalStateException if the request is not a GET o HEAD request, since as per the HTTP Spec ( http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.2 ), clients MUST NOT honor redirections in these cases.

In the same page, the last sentence says "If data is written to the response after these methods are called, the data is ignored.". In my experience, servlet containers have behaved in very different ways regarding this. I believe this sentence should be rewritten to the stronger "If data is written to the response after these methods are called, the data MUST BE ignored"

8.2.2.g.iv) "<welcome-file> declarations are additive.". This is ambiguous. Since order processing for web-fragments is undefined, but the Welcome Files *are* order-sensitive anyway (as per 10.10- "The welcome file list is an ordered list of partial URLs with no trailing or leading /."), this leads to a clear conflict. If fragment A specifies a welcome file of "a.html" and fragment B specifies a welcome file of "B.html", and both files are present, which one gets delivered?

 

Comments

 

Add a Comment

Name (optional)
EMail (optional, will not be displayed)

Text