Return-Path: Delivered-To: apmail-jakarta-httpclient-dev-archive@www.apache.org Received: (qmail 48204 invoked from network); 13 Feb 2006 09:37:09 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 13 Feb 2006 09:37:09 -0000 Received: (qmail 51950 invoked by uid 500); 13 Feb 2006 09:37:08 -0000 Delivered-To: apmail-jakarta-httpclient-dev-archive@jakarta.apache.org Received: (qmail 51701 invoked by uid 500); 13 Feb 2006 09:37:06 -0000 Mailing-List: contact httpclient-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Help: List-Post: List-Id: "HttpClient Project" Reply-To: "HttpClient Project" Delivered-To: mailing list httpclient-dev@jakarta.apache.org Received: (qmail 51688 invoked by uid 99); 13 Feb 2006 09:37:06 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 13 Feb 2006 01:37:06 -0800 X-ASF-Spam-Status: No, hits=0.0 required=10.0 tests= X-Spam-Check-By: apache.org Received-SPF: neutral (asf.osuosl.org: local policy) Received: from [195.186.19.65] (HELO mail20.bluewin.ch) (195.186.19.65) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 13 Feb 2006 01:37:05 -0800 Received: from [192.168.0.4] (83.76.227.208) by mail20.bluewin.ch (Bluewin 7.2.071) id 43E4A57700222B49 for httpclient-dev@jakarta.apache.org; Mon, 13 Feb 2006 09:36:43 +0000 Subject: Re: [HttpCore] mutability and immutability no more? From: Oleg Kalnichevski To: HttpClient Project In-Reply-To: <43EF7B5A.90600@dubioso.net> References: <43EF7B5A.90600@dubioso.net> Content-Type: text/plain Date: Mon, 13 Feb 2006 10:36:45 +0100 Message-Id: <1139823406.9612.2.camel@localhost.localdomain> Mime-Version: 1.0 X-Mailer: Evolution 2.4.1 Content-Transfer-Encoding: 7bit X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N On Sun, 2006-02-12 at 19:15 +0100, Roland Weber wrote: > Hi Oleg, hi all, > > I'm not quite happy with the way http-core currently handles > mutable vs. immutable messages, in particular requests. There > is an instanceof check in HttpRequestExecutor: if a request > is an instance of HttpMutableRequest, it is preprocessed. If > it is not an instance of that interface, preprocessing is > skipped. This has some questionable implications: > > - the default implementations we have (HttpGet, HttpPost) > implement the mutable interface and can not be protected > from being modified (out of the box) > > - if an application implements the non-mutable interface, > the skipping of preprocessing will most likely result in > an invalid request being sent. In other words: > > - although the signature of HttpRequestExecutor.execute > declares to expect an immutable request, it actually > requires a mutable request to function properly > > - the design is not "fair", meaning: we implicitly expect > applications to respect immutability if we declare a > return value with an immutable interface, but our code > does not show the same respect towards the application > > Yes, the last three points are more or less the same. > That just shows you how many facets my unhappiness has :-) > One other point which seems unrelated at first sight is > the distinction between auto-generated headers and headers > provided by the application. In HttpClient < 4.0, this is > used to "undo" modifications to a request before retrying, > I think in the method director. > This design restricts our request interceptors to adding > headers. Removing a header, or changing a header value, > are operations that can not be undone. Even if we might > not provide interceptors that modify header values, the > mechanism is meant for use by application developers too. > Not allowing modifications or removal of headers is a > significant restriction. Some headers for which modifications > can be useful are Cookie, Connection, Content-Encoding. > > An alternative way to address mutability and immutability > is through the use of wrappers. I have seen this technique > applied in similar scenarios. The Servlet API added wrappers > for requests and responses with version 2.3: > http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/package-summary.html > > The idea is as follows: instead of an instanceof check to > decide whether request preprocessing should be performed, > a mutable wrapper is created for the request. Preprocessing > is *always* performed, modifications apply only to the > wrapper. The auto-generated flag for Headers is pointless, > modifications are undone by forgetting about the wrapper. > Wrappers that implement only the non-mutable interfaces > can be used to protect against unintentional modifications > of objects. > This change is based on a different interpretation of > "immutable". To me, immutable doesn't mean that a request > is sent without being processed by the interceptors. > It means that the object in memory is not modified. > > If you feel like you've got a deja vu now, here's why: > http://mail-archives.apache.org/mod_mbox/jakarta-httpclient-dev/200503.mbox/%3cOFF61E99BB.5D1DEACB-ONC1256FD3.003C83FB-C1256FD3.003EF2AF@de.ibm.com%3e > > Based on the result of this discussion, I will try to come > up with a patch next weekend - or not. > There would be some followup issues because the distinction > between entity enclosing and header-only requests is currently > based on another instanceof check. This can be addressed by > implementing plenty of different wrapper classes, or by > removing the instanceof check in favor of a flag that can be > queried. (We don't have different response classes either.) > But that is a secondary issue to the big question: > to wrap or not to wrap? > Roland, Frankly, I do not think this would be a better solution. There are situations where one does want the original request object to mutate in order to be able to examine its post-execution state. If we wrapped the original request object all mutations to it would be lost along with the wrapper. I have a more radical change to suggest. I am beginning to suspect the whole concept of mutable/immutable HTTP messages while being conceptually nice does not seem to bring any tangible benefits in practical terms. In the very beginning I still thought we might want to stick some of the protocol logic into HttpRequest/HttpResponse class hierarchy (for instance 'Host' header), which would require some complex methods mutating the state of the request objects. This proved unnecessary. Now we have all HTTP protocol logic neatly encapsulated in the request/response interceptors and the control logic encapsulated in various HTTP processors. HTTP messages have been reduced to being pure value objects, which is great. Probably we ought to start thinking of HttpRequest/HttpResponse classes as representing value objects, which are always mutable. I suggest we just do away with HttpMutable* interfaces Oleg > > I'm signing off now, it's been a long day. Looking forward > to read your comments tomorrow. > > cheers, > Roland > > --------------------------------------------------------------------- > To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org > For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org > > --------------------------------------------------------------------- To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org