|Summary:||Order of ServletRequest parameters is not preserved|
|Component:||Servlet & JSP API||Assignee:||Tomcat Developers Mailing List <dev>|
Description corythearchitect 2013-09-20 21:14:32 UTC
The ServletRequest interface provides two methods to iterate through request parameters: Enumeration<String> getParameterNames(), and Map<String, String> getParameterMap() Unfortunately, the underlying implementation in Tomcat is a HashMap, which fails to preserve the order of parameters as they are specified in the request. An alternate implementation should be used to preserve request order. LinkedHashMap, for example, is capable of preserving insertion order. The Servlet Specification (v3.0) speaks only to the relative ordering of query string data and post body data. However, section 17.13.3 of the HTML specification (v4.01) titled "Processing form data", clearly states that "control names/values are listed in the order they appear in the document." Therefore, I do not see a valid interpretation of either specification to rationalize Tomcat's implementation. To receive a request with an ordered list of parameters and represent them in an implementation that is guaranteed not to preserve this order is difficult to rationalize.
Comment 1 Mark Thomas 2013-09-23 13:48:18 UTC
The Servlet specification does defer to W3C for all HTML matters. The text quoted above regarding ordering only applies when application/x-www-form-urlencoded is being used. Strictly, it applies only to the order that the client provides the data. It could be argued that if the client is required to provide the parameters in order in this case then the getParamererXXX() methods should respect that order. Further, if the order needs to be maintained for this one case, it is easier to maintain it for all. However, there is nothing that I can see in either the Servlet or HTML specifications that strcitly requires the Servlet API to present the parameters in the same order as they were received. There is no major performance difference (I am aware of) between HashMap and LinkedHahsMap so I am not against making this change but neither (at this point) do I really see the need for it. One concern I do have is that given that there is not a requirement for this, other containers may not implement it and that could cause portability issues. I am curious as to the use case that supports it. Can you elaborate on why it might be important for the parameters to be returned in the same order as they appear on the form.
Comment 2 Christopher Schultz 2013-09-23 15:08:45 UTC
(In reply to Mark Thomas from comment #1) > I am curious as to the use case that supports it. Can you elaborate on why > it might be important for the parameters to be returned in the same order as > they appear on the form. Somewhat related: http://host/resource?op=add&op=update&op=delete If the application expects left-to-right ordering when fetching "op" (which IMO is reasonable) then the ordering of the values is quite important. It seems like extending the above use case to parameters with different names would be reasonable, though I can't really envision a use case where the order of unknown request parameter names would be important.
Comment 3 corythearchitect 2013-09-23 16:10:06 UTC
Thomas, thank you for your rapid evaluation and response on this matter. The general use case is the servicing of a request in which the order of parameter evaluation is significant. http://host/resource?country=CA&postalcode=N7T5R4 Let's assume this is in context of a general infrastructure that evaluates each parameter in the order received (field validation being just one example of potential triggers). postalcode validation is dependent on the value of country. The specific scenario I am currently dealing with is porting a web service implementation from ASP/IIS to Java/Tomcat. The Microsoft IRequestDictionary.QueryString implementation respects order of insertion, while Tomcat scrambles the order as a result of the backing HashMap collection. I respect your position that there is no explicit specification of the server-side evaluation of HTML parameters. However, I also see no significance to the client-side specification of parameter order beyond the implication that the ordering is also significant to the processing server that consumes it. What other purpose could such an ordering possibly serve? Assuming equivalent performance, what portability issues could arise from a MORE determinate collection implementation? If anyone is currently relying on the iteration order of the existing HashMap implementation, a) they are in for a surprise anyhow, and b) the ServletRequest interface, unfortunately, provides no guarantees, relying on the generic Map and Enumeration interfaces, both of which defer to the implementation for behaviour in this regard. This decision could only be interpreted as an improvement in compliance (with the HTML specification).
Comment 4 Christopher Schultz 2013-09-23 16:30:47 UTC
(In reply to corythearchitect from comment #3) > The general use case is the servicing of a request in which the order of > parameter evaluation is significant. > > http://host/resource?country=CA&postalcode=N7T5R4 > > Let's assume this is in context of a general infrastructure that evaluates > each parameter in the order received (field validation being just one > example of potential triggers). postalcode validation is dependent on the > value of country. Isn't "postalcode validation is dependens on the value of country" part of your business logic? If so, you should always be fetching the country first, then the postalcode. Or are you building a system where the order of the parameters in the request dictates the way validation is performed? In any case, I am +1 for changing HashMap->LinkedHashMap to preserve parameter ordering.
Comment 5 corythearchitect 2013-09-23 18:18:39 UTC
"Or are you building a system where the order of the parameters in the request dictates the way validation is performed?" Essentially, yes.
Comment 6 mgrigorov 2013-09-23 20:17:18 UTC
In my opinion this requirement and the use case are weak. In the best case I'd try to avoid depending on any ordering in the application. But if ordering is really required then I would encode the parameter values and parse them myself and not rely on some container specific feature. E.g.: ?ops=op1|op2|op3&something=else, or any other encoding that will work for my use case. With URL encoded value the syntax could be quite rich. On the other hand replacing HashMap with LinkedHashMap will not cause performance degradation so I don't mind such change.
Comment 7 Mark Thomas 2013-09-23 21:06:13 UTC
Fixed in 8.0.x for 8.0.0-RC4 and 7.0.x for 7.0.45.