You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@hc.apache.org by Oleg Kalnichevski <ol...@apache.org> on 2005/04/26 11:05:36 UTC

[http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Folks,

After having spent some time working on the http-common API I would like
to propose some changes to HttpEntity, HttpIncomingEntity &
HttpOutgoingEntity interfaces. 

Presently HttpResponse and HttpEntityEnclosingRequest return a generic
HttpEntity interface in order to be useable on both client and server
side. From the design purism perspective this is probably quite okay. At
the same time in practical terms this approach requires HttpEntity to be
cast to either HttpIncomingEntity or HttpOutgoingEntity all the time to be 
of any use. All these castings get quite irritating quite fast.

(1) Fundamentally the distinction between HttpIncomingEntity and
HttpOutgoingEntity behaviors is not necessary

(2) HttpIncomingEntity interface can be gotten rid of. After all it is
perfectly reasonable for any generic entity to be able produce its
content. getInputStream method gets moved to HttpEntity

(3) Rename HttpOutgoingEntity to HttpStreamableEntity. As far as I am
concerned ability to stream itself is optional behavior for an entity
(akin to HttpEntityEnclosingRequest) which should be treated as such

This approach may create some problems for non-repeatable entities such
as InputStreamEntity but they can be resolved by maintaining the object
state and refusing to stream out the content if it has already been
consumed through getInputStream method. I feel this is a small price to
pay for a much less irritating API

What you think?

Oleg


---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org


Re: [http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Posted by Michael Becke <mb...@gmail.com>.
Casting back and forth can definitely be annoying.  A solution that
fixes this problem would certainly be good.  My only concern is that
we maintain the ability to write directly to the output stream.  The
changes you recently checked in seems to preserve this.

The only other option that comes to mind would be reverse the current
situation and move writeTo(OutputStream) to HttpEntity and
getContent() to HttpStreamableEntity (or somewhere appropriate).  My
thinking here is that all entity types can be written to an output
stream, but not all can produce (at least easily) an input stream.

Mike

On 4/26/05, Oleg Kalnichevski <ol...@apache.org> wrote:
> Folks,
> 
> After having spent some time working on the http-common API I would like
> to propose some changes to HttpEntity, HttpIncomingEntity &
> HttpOutgoingEntity interfaces.
> 
> Presently HttpResponse and HttpEntityEnclosingRequest return a generic
> HttpEntity interface in order to be useable on both client and server
> side. From the design purism perspective this is probably quite okay. At
> the same time in practical terms this approach requires HttpEntity to be
> cast to either HttpIncomingEntity or HttpOutgoingEntity all the time to be
> of any use. All these castings get quite irritating quite fast.
> 
> (1) Fundamentally the distinction between HttpIncomingEntity and
> HttpOutgoingEntity behaviors is not necessary
> 
> (2) HttpIncomingEntity interface can be gotten rid of. After all it is
> perfectly reasonable for any generic entity to be able produce its
> content. getInputStream method gets moved to HttpEntity
> 
> (3) Rename HttpOutgoingEntity to HttpStreamableEntity. As far as I am
> concerned ability to stream itself is optional behavior for an entity
> (akin to HttpEntityEnclosingRequest) which should be treated as such
> 
> This approach may create some problems for non-repeatable entities such
> as InputStreamEntity but they can be resolved by maintaining the object
> state and refusing to stream out the content if it has already been
> consumed through getInputStream method. I feel this is a small price to
> pay for a much less irritating API
> 
> What you think?
> 
> Oleg
> 
> ---------------------------------------------------------------------
> 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


Re: [http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Posted by Ortwin Glück <or...@nose.ch>.
Oleg,

When we started discussing HttpIncomingEntity and HttpOutgoingEntity I 
had already mentioned that their distinction into different interfaces 
was probably not necessary and could be solved by using different design 
patterns. Unfortunately I lacked the time to have a proper look into it. 
So I am more than happy that you have come to the same conclusion, now. 
Get rid of them if you can.

Cheers

Odi

Oleg Kalnichevski wrote:
> Folks,
> 
> After having spent some time working on the http-common API I would like
> to propose some changes to HttpEntity, HttpIncomingEntity &
> HttpOutgoingEntity interfaces. 
> 
> Presently HttpResponse and HttpEntityEnclosingRequest return a generic
> HttpEntity interface in order to be useable on both client and server
> side. From the design purism perspective this is probably quite okay. At
> the same time in practical terms this approach requires HttpEntity to be
> cast to either HttpIncomingEntity or HttpOutgoingEntity all the time to be 
> of any use. All these castings get quite irritating quite fast.
> 
> (1) Fundamentally the distinction between HttpIncomingEntity and
> HttpOutgoingEntity behaviors is not necessary
> 
> (2) HttpIncomingEntity interface can be gotten rid of. After all it is
> perfectly reasonable for any generic entity to be able produce its
> content. getInputStream method gets moved to HttpEntity
> 
> (3) Rename HttpOutgoingEntity to HttpStreamableEntity. As far as I am
> concerned ability to stream itself is optional behavior for an entity
> (akin to HttpEntityEnclosingRequest) which should be treated as such
> 
> This approach may create some problems for non-repeatable entities such
> as InputStreamEntity but they can be resolved by maintaining the object
> state and refusing to stream out the content if it has already been
> consumed through getInputStream method. I feel this is a small price to
> pay for a much less irritating API
> 
> What you think?
> 
> Oleg
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org
> 

-- 
  _________________________________________________________________
  NOSE applied intelligence ag

  ortwin glück                      [www]      http://www.nose.ch
  software engineer
  hardturmstrasse 171               [pgp id]           0x81CF3416
  8005 zürich                       [office]      +41-1-277 57 35
  switzerland                       [fax]         +41-1-277 57 12

---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org


Re: [http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Posted by Ortwin Glück <or...@nose.ch>.

Oleg Kalnichevski wrote:
> I do want such a framework but I am not in favor of tightly coupling it
> with the EntityEnclosingMessage, HttpResponse impl classes.

That's what I am saying.

> I can't help thinking we are trying to come up with a solution for a
> non-existent problem. Design purism aside, the only real issue with the
> current implementation I know of is that _some_ outgoing entities _may_
> have _difficulties_ producing an input stream to represent its content.
> In the extreme case I would rather prefer to see NotSupportedException
> thrown instead of a whole bunch of otherwise unnecessary and/or ugly
> interfaces.

I completely agree! We can not require that an entity be repeatable of 
course, although that would be the nicest: The server response would 
have always to be buffered, which we don't want.

Oh, and don't make an abstract class out of it. I don't want to be 
forced to inherit from a base class. Rather just implement an interface.

---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org


Re: [http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Posted by Michael Becke <mb...@gmail.com>.
Go for it.  Simplicity sounds like the way to go.

Mike

On 5/1/05, Oleg Kalnichevski <ol...@apache.org> wrote:
> Folks,
> 
> How do you feel about moving  writeTo(OutputStream) method from
> HttpStreamableEntity (former HttpOutgoingEntity) to HttpEntity interface
> and removing HttpStreamableEntity interface at all?
> 
> Oleg
> 
> 
> On Fri, 2005-04-29 at 11:50 +0200, Roland Weber wrote:
> > Hi Oleg,
> >
> > > > ifce EntityEnclosingMessage {
> > > >   setOgEntity(HttpOgEntity)
> > > >   HttpIcEntity getIcEntity(Class what)
> > > > }
> > >
> > > Unfortunately I do not think this solves the problem completely. It is
> > > necessary to be able to set HttpIncomingEntity when assembling the
> > > incoming request on the server. Likewise, it is necessary to be able to
> > > have access to the HttpOutcomingEntity when streaming out the request
> > > body on the client side. Effectively the interface would probably have
> > > to be
> > >
> > > ifce EntityEnclosingMessage {
> > >   setOgEntity(HttpOgEntity)
> > >   setIcEntity(HttpInEntity)
> > >   HttpIcEntity getIcEntity(Class what)
> > >   HttpOgEntity getOgEntity()
> > > }
> >
> > I agree that getOgEntity() is required. I had something in mind about a
> > protected accessor, but that would create a dependency on a particular
> > implementation class.
> > I don't see the need to set an IcEntity though. The first one who needs
> > to access the message body specifies the class/interface of the IcEntity.
> > No need to set it.
> >
> > > I am also not in favor of forcing EntityEnclosingMessage impls to know
> > > how to produce entities of different types. This coupling is unjustified
> > > IMO.
> >
> > I agree. A factory - or alternative solution for instantiating entities -
> > can be kept separate. Which makes my idea of having the first accessor
> > select the type of entity pointless.
> >
> > > I believe this problem should be solved through a number of simple
> > > entity consumer classes that "decorate" the Http(Incoming)Entity
> > > interface.
> >
> > Ok, so this probably is the fundamental difference between our views at
> > the problem. To me, an IncomingEntity is a converter that changes it's
> > input, not a decorator that somehow adjusts the view on the underlying
> > data. That's why I didn't want to merge the representation of the "raw"
> > entity with the converted/interpreted entity into the same class hier-
> > archy.
> > I imagine some kind of "ProtoEntity", which basically holds the input
> > stream and maybe some header fields, from which the "real" entities are
> > created. And yes, there is a need to set this "ProtoEntity" on the
> > receiving side of HTTP communication. I am finally getting why you want
> > to set an incoming entity :-)
> > Odi also mentioned the decorator pattern when we discussed the entities
> > for the high level design, so my view seems to be a little off. And I
> > wouldn't like to introduce an extra interface for the "ProtoEntity"
> > either.
> >
> > > I can't help thinking we are trying to come up with a solution for a
> > > non-existent problem. Design purism aside, the only real issue with the
> > > current implementation I know of is that _some_ outgoing entities _may_
> > > have _difficulties_ producing an input stream to represent its content.
> > > In the extreme case I would rather prefer to see NotSupportedException
> > > thrown instead of a whole bunch of otherwise unnecessary and/or ugly
> > > interfaces.
> >
> > Why not go all the way and move writeTo(OutputStream) also to HttpEntity?
> > This would remove the asymmetry that has been created by merging the
> > incoming entity with the base interface. That asymmetry is my only
> > remaining objection.
> >
> > 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


Re: [http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Posted by Ortwin Glück <or...@nose.ch>.
Very much appreciated!

Odi

Oleg Kalnichevski wrote:
> Folks,
> 
> How do you feel about moving  writeTo(OutputStream) method from
> HttpStreamableEntity (former HttpOutgoingEntity) to HttpEntity interface
> and removing HttpStreamableEntity interface at all?
> 
> Oleg


---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org


Re: [http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Posted by Oleg Kalnichevski <ol...@apache.org>.
Folks,

How do you feel about moving  writeTo(OutputStream) method from
HttpStreamableEntity (former HttpOutgoingEntity) to HttpEntity interface
and removing HttpStreamableEntity interface at all?

Oleg


On Fri, 2005-04-29 at 11:50 +0200, Roland Weber wrote:
> Hi Oleg,
> 
> > > ifce EntityEnclosingMessage {
> > >   setOgEntity(HttpOgEntity)
> > >   HttpIcEntity getIcEntity(Class what)
> > > }
> > 
> > Unfortunately I do not think this solves the problem completely. It is
> > necessary to be able to set HttpIncomingEntity when assembling the
> > incoming request on the server. Likewise, it is necessary to be able to
> > have access to the HttpOutcomingEntity when streaming out the request
> > body on the client side. Effectively the interface would probably have
> > to be
> > 
> > ifce EntityEnclosingMessage {
> >   setOgEntity(HttpOgEntity)
> >   setIcEntity(HttpInEntity)
> >   HttpIcEntity getIcEntity(Class what)
> >   HttpOgEntity getOgEntity()
> > }
> 
> I agree that getOgEntity() is required. I had something in mind about a
> protected accessor, but that would create a dependency on a particular
> implementation class.
> I don't see the need to set an IcEntity though. The first one who needs
> to access the message body specifies the class/interface of the IcEntity.
> No need to set it.
> 
> > I am also not in favor of forcing EntityEnclosingMessage impls to know
> > how to produce entities of different types. This coupling is unjustified
> > IMO.
> 
> I agree. A factory - or alternative solution for instantiating entities -
> can be kept separate. Which makes my idea of having the first accessor
> select the type of entity pointless.
> 
> > I believe this problem should be solved through a number of simple
> > entity consumer classes that "decorate" the Http(Incoming)Entity
> > interface.
> 
> Ok, so this probably is the fundamental difference between our views at
> the problem. To me, an IncomingEntity is a converter that changes it's
> input, not a decorator that somehow adjusts the view on the underlying
> data. That's why I didn't want to merge the representation of the "raw"
> entity with the converted/interpreted entity into the same class hier-
> archy.
> I imagine some kind of "ProtoEntity", which basically holds the input
> stream and maybe some header fields, from which the "real" entities are
> created. And yes, there is a need to set this "ProtoEntity" on the
> receiving side of HTTP communication. I am finally getting why you want
> to set an incoming entity :-)
> Odi also mentioned the decorator pattern when we discussed the entities
> for the high level design, so my view seems to be a little off. And I
> wouldn't like to introduce an extra interface for the "ProtoEntity"
> either.
> 
> > I can't help thinking we are trying to come up with a solution for a
> > non-existent problem. Design purism aside, the only real issue with the
> > current implementation I know of is that _some_ outgoing entities _may_
> > have _difficulties_ producing an input stream to represent its content.
> > In the extreme case I would rather prefer to see NotSupportedException
> > thrown instead of a whole bunch of otherwise unnecessary and/or ugly
> > interfaces.
> 
> Why not go all the way and move writeTo(OutputStream) also to HttpEntity?
> This would remove the asymmetry that has been created by merging the
> incoming entity with the base interface. That asymmetry is my only
> remaining objection.
> 
> cheers,
>   Roland


---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org


Re: [http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Posted by Roland Weber <RO...@de.ibm.com>.
Hi Oleg,

> > ifce EntityEnclosingMessage {
> >   setOgEntity(HttpOgEntity)
> >   HttpIcEntity getIcEntity(Class what)
> > }
> 
> Unfortunately I do not think this solves the problem completely. It is
> necessary to be able to set HttpIncomingEntity when assembling the
> incoming request on the server. Likewise, it is necessary to be able to
> have access to the HttpOutcomingEntity when streaming out the request
> body on the client side. Effectively the interface would probably have
> to be
> 
> ifce EntityEnclosingMessage {
>   setOgEntity(HttpOgEntity)
>   setIcEntity(HttpInEntity)
>   HttpIcEntity getIcEntity(Class what)
>   HttpOgEntity getOgEntity()
> }

I agree that getOgEntity() is required. I had something in mind about a
protected accessor, but that would create a dependency on a particular
implementation class.
I don't see the need to set an IcEntity though. The first one who needs
to access the message body specifies the class/interface of the IcEntity.
No need to set it.

> I am also not in favor of forcing EntityEnclosingMessage impls to know
> how to produce entities of different types. This coupling is unjustified
> IMO.

I agree. A factory - or alternative solution for instantiating entities -
can be kept separate. Which makes my idea of having the first accessor
select the type of entity pointless.

> I believe this problem should be solved through a number of simple
> entity consumer classes that "decorate" the Http(Incoming)Entity
> interface.

Ok, so this probably is the fundamental difference between our views at
the problem. To me, an IncomingEntity is a converter that changes it's
input, not a decorator that somehow adjusts the view on the underlying
data. That's why I didn't want to merge the representation of the "raw"
entity with the converted/interpreted entity into the same class hier-
archy.
I imagine some kind of "ProtoEntity", which basically holds the input
stream and maybe some header fields, from which the "real" entities are
created. And yes, there is a need to set this "ProtoEntity" on the
receiving side of HTTP communication. I am finally getting why you want
to set an incoming entity :-)
Odi also mentioned the decorator pattern when we discussed the entities
for the high level design, so my view seems to be a little off. And I
wouldn't like to introduce an extra interface for the "ProtoEntity"
either.

> I can't help thinking we are trying to come up with a solution for a
> non-existent problem. Design purism aside, the only real issue with the
> current implementation I know of is that _some_ outgoing entities _may_
> have _difficulties_ producing an input stream to represent its content.
> In the extreme case I would rather prefer to see NotSupportedException
> thrown instead of a whole bunch of otherwise unnecessary and/or ugly
> interfaces.

Why not go all the way and move writeTo(OutputStream) also to HttpEntity?
This would remove the asymmetry that has been created by merging the
incoming entity with the base interface. That asymmetry is my only
remaining objection.

cheers,
  Roland

Re: [http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Posted by Oleg Kalnichevski <ol...@apache.org>.
Hi Roland

> ifce EntityEnclosingMessage {
>   setOgEntity(HttpOgEntity)
>   HttpIcEntity getIcEntity(Class what)
> }

Unfortunately I do not think this solves the problem completely. It is
necessary to be able to set HttpIncomingEntity when assembling the
incoming request on the server. Likewise, it is necessary to be able to
have access to the HttpOutcomingEntity when streaming out the request
body on the client side. Effectively the interface would probably have
to be

ifce EntityEnclosingMessage {
  setOgEntity(HttpOgEntity)
  setIcEntity(HttpInEntity)
  HttpIcEntity getIcEntity(Class what)
  HttpOgEntity getOgEntity()
}

To me this is hardly any better than having to cast to generic interface
to a super interface. Not to mention that this interface looks kind of
schizophrenic.

I am also not in favor of forcing EntityEnclosingMessage impls to know
how to produce entities of different types. This coupling is unjustified
IMO. I believe this problem should be solved through a number of simple
entity consumer classes that "decorate" the Http(Incoming)Entity
interface. Something of this sort:

http://svn.apache.org/repos/asf/jakarta/httpclient/trunk/http-common/src/java/org/apache/http/entity/BufferedHttpEntity.java

> If we don't want a framework to instantiate different types of
> incoming
> entities, there really is no point in the interface. But then I'd go
> all
> the way and move getInputStream() into the HttpMessage rather than
> wrap
> it in a clumsy entity object.

I do want such a framework but I am not in favor of tightly coupling it
with the EntityEnclosingMessage, HttpResponse impl classes.

I can't help thinking we are trying to come up with a solution for a
non-existent problem. Design purism aside, the only real issue with the
current implementation I know of is that _some_ outgoing entities _may_
have _difficulties_ producing an input stream to represent its content.
In the extreme case I would rather prefer to see NotSupportedException
thrown instead of a whole bunch of otherwise unnecessary and/or ugly
interfaces.

cheers,

Oleg


On Thu, Apr 28, 2005 at 01:57:11PM +0200, Roland Weber wrote:
> Hi Oleg,
> 
> [I had an initial version of this mail almost completed
>  when my computer deadlocked. I really hate computers.]
> 
> > My main point is that HttpEntity that cannot produce its content is
> > COMPLETELY useless unless cast to a more specific interface. Having to
> > cast HttpEntity interface EVERY TIME it is used results in a quite ugly
> > and IMO irritating code.
> 
> I agree. I wrote HttpEntity into the high level design solely to combine
> the two trees of incoming and outgoing entities. I never expected it to
> be used in a method signature.
> 
> > Likewise if HttpEntityEnclosingRequest interface is made to produce
> > an HttpOutpoingEntity on the client side, this interface is no longer
> > useable on the server, because the server expects an HttpIncomingEntity
> > instead. Inevitably one needs two interfaces
> > HttpIncomingEntityEnclosingRequest and
> > HttpOutgoingEntityEnclosingRequest to solve the problem. The same story
> > goes for the HttpResponse interface. One would also need two super
> > interfaces HttpIncomingResponse and HttpOutgoingResponse. For all these
> > interfaces one would need HttpMutable* counterparts. The situation gets
> > completely ridiculous, at least in my opinion, and we end up with a
> > classical over-designed API. 
> 
> I agree. Here is an alternative solution to keeping the number of 
> interfaces
> reasonable: have separate methods for incoming and outgoing entities in 
> the
> same interface. (ic = incoming, og = outgoing)
> 
> ifce EntityEnclosingMessage {
>   setOgEntity(HttpOgEntity)
>   HttpIcEntity getIcEntity(Class what)
> }
> 
> ifce TwoWayEntity implements HttpIcEntity, HttpOcEntity
> 
> class BasicHttpMessage implements EntityEnclosingMessage {
>   boolean i_was_received
>   HttpOgEntity og_entity
>   HttpIcEntity ic_entity
> 
>   setOgEntity(HttpOgEntity oge) {
>     if i_was_received throw "are you kidding?"
>     og_entity := oge
>   }
> 
>   HttpIcEntity getIcEntity(Class what) {
>     if (i_was_received) {
>       if ic_entity is null {
>         ic_entity := (instantiate 'what' from InputStream)
>       } else {
>         if ic_entity not instance of 'what' -> fail
>         if ic_entity not repeatable -> fail
>       }
>       return ic_entity
>     } else { // i was not received
>       if og_entity instanceof (TwoWayEntity, what)
>         return og_entity
>     } else {
>       throw "entity not accessible or non-existant"
>     }
>   }
> } // class BasicHttpMessage
> 
> 
> Instead of having a getEntity() which requires a cast that may or may not
> work on the client or server side, you have to different methods to access
> either what's coming in or going out, which may or may not work on the 
> client
> or server side. This should solve the casting problem.
> 
> > We have long maintained a stance that HttpClient is a content agnostic
> > library. Anything that has to do with content processing should be built
> > on top of HttpClient and should not be a part of the library. We
> > certainly should not get ourselves into the MIME content business. I
> > personally would rather prefer a simple consumer pattern where various
> > HTTP content consumers simply retrieve the content from
> > HttpEntity#getContent as an InputStream, hence the motivation for moving
> > this functionality to the base interface
> 
> If we don't want a framework to instantiate different types of incoming
> entities, there really is no point in the interface. But then I'd go all
> the way and move getInputStream() into the HttpMessage rather than wrap
> it in a clumsy entity object.
> 
> HttpClient as it is supports different ways to provide a request body:
> byte array, string, input stream, and multipart-mime (which we would
> like to move to commons-codec). The idea of the Ic/OgEntity stuff was
> to maintain this capability, and to match it with the complementary
> conversion for incoming message bodies. As a framework, *without*
> providing significantly more than samples for non-trivial content types.
> I have no problem with dropping the idea, but then it should be dropped
> completely so that only HttpOutgoingEntity remains (under whatever name).
> 
> > All these drivels aside I'll be happy to see a patch that keeps
> > HttpEntity/HttpIncomingEntity/HttpOutcomingEntity paradigm (which is
> > quite beautiful from the conceptual standpoint) and addresses the above
> > mentioned shortcomings.
> 
> And I would love to provide one. Alas, as an IBMer I am not allowed to
> post executable code without going through approval hell, involving
> about 6 levels in the functional guidance hierarchy and two levels in
> each the general law and IP law hierarchy. And I don't even have the
> business case to get the approval process started. [I'm serious.]
> 
> > I just _personally_ do not see how this can be
> > done, at least at this point
> 
> The proposal above should deal with your immediate concerns, which were
> the typecasts. The fact that inappropriate methods become available in the
> interfaces - like setOutgoingEntity() on a response on the client side -
> merely exposes a problem that was hidden before by dealing with incoming 
> and
> outgoing entities through the same methods. I believe the problem stems
> from using the same request/response objects on the client and server 
> side,
> although their function (incoming/outcoming) is reversed. I don't think
> you can accurately address this problem by changing the entity interface
> hierarchy. Whether there should be a framework for instantiating different
> types of incoming entities at all is a separate point for discussion.
> 
> cheers,
>   Roland
>  

---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org


Re: [http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Posted by Ortwin Glück <or...@nose.ch>.
Looking at the problem from a semantic point of view:
A "HTTP entity" is the body of a HTTP message.
The "request entity" is the "HTTP entity" in a request
whereas the "response entity" is the "HTTP entity" in a response. On the 
protocol level (as opposed to the API level) the two are not any 
different. The respective headers contain some meta information about 
what is going to be in the enclosed entity (like transfer encoding, 
content type, size, etc.). But the entity looks exactly the same in a 
request and in a response. So the semantics suggest we have only one 
interface to that thing called entity. How such an entity is produced or 
consumed (write / parse) is not in the responsibility of the entity 
object. It rather is the responsibility of entity producers and 
consumers (reader / writer, source / drain).

The only thing we need to do with an entity is read it. At request time 
we read it and stream it to the server (use case A). At response time 
the client reads from it to get the content (use case B). How the 
content of the entity is produced should NOT be part of the interface 
specification. It may be stored as a file on disk, may be the input 
stream from the server, may be a multipart entity consisting of serveral 
files on disk and memory, anything else.

The two use cases are *different* implementations of that one interface.
So why not just make a host of classes that implement this simple 
interface and provide an entity in different ways. Not specifying how 
the entity is produced makes this whole architecture more flexible and 
less complex!

my $0.02

Odi


---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org


Re: [http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Posted by Roland Weber <RO...@de.ibm.com>.
Hi Oleg,

[I had an initial version of this mail almost completed
 when my computer deadlocked. I really hate computers.]

> My main point is that HttpEntity that cannot produce its content is
> COMPLETELY useless unless cast to a more specific interface. Having to
> cast HttpEntity interface EVERY TIME it is used results in a quite ugly
> and IMO irritating code.

I agree. I wrote HttpEntity into the high level design solely to combine
the two trees of incoming and outgoing entities. I never expected it to
be used in a method signature.

> Likewise if HttpEntityEnclosingRequest interface is made to produce
> an HttpOutpoingEntity on the client side, this interface is no longer
> useable on the server, because the server expects an HttpIncomingEntity
> instead. Inevitably one needs two interfaces
> HttpIncomingEntityEnclosingRequest and
> HttpOutgoingEntityEnclosingRequest to solve the problem. The same story
> goes for the HttpResponse interface. One would also need two super
> interfaces HttpIncomingResponse and HttpOutgoingResponse. For all these
> interfaces one would need HttpMutable* counterparts. The situation gets
> completely ridiculous, at least in my opinion, and we end up with a
> classical over-designed API. 

I agree. Here is an alternative solution to keeping the number of 
interfaces
reasonable: have separate methods for incoming and outgoing entities in 
the
same interface. (ic = incoming, og = outgoing)

ifce EntityEnclosingMessage {
  setOgEntity(HttpOgEntity)
  HttpIcEntity getIcEntity(Class what)
}

ifce TwoWayEntity implements HttpIcEntity, HttpOcEntity

class BasicHttpMessage implements EntityEnclosingMessage {
  boolean i_was_received
  HttpOgEntity og_entity
  HttpIcEntity ic_entity

  setOgEntity(HttpOgEntity oge) {
    if i_was_received throw "are you kidding?"
    og_entity := oge
  }

  HttpIcEntity getIcEntity(Class what) {
    if (i_was_received) {
      if ic_entity is null {
        ic_entity := (instantiate 'what' from InputStream)
      } else {
        if ic_entity not instance of 'what' -> fail
        if ic_entity not repeatable -> fail
      }
      return ic_entity
    } else { // i was not received
      if og_entity instanceof (TwoWayEntity, what)
        return og_entity
    } else {
      throw "entity not accessible or non-existant"
    }
  }
} // class BasicHttpMessage


Instead of having a getEntity() which requires a cast that may or may not
work on the client or server side, you have to different methods to access
either what's coming in or going out, which may or may not work on the 
client
or server side. This should solve the casting problem.

> We have long maintained a stance that HttpClient is a content agnostic
> library. Anything that has to do with content processing should be built
> on top of HttpClient and should not be a part of the library. We
> certainly should not get ourselves into the MIME content business. I
> personally would rather prefer a simple consumer pattern where various
> HTTP content consumers simply retrieve the content from
> HttpEntity#getContent as an InputStream, hence the motivation for moving
> this functionality to the base interface

If we don't want a framework to instantiate different types of incoming
entities, there really is no point in the interface. But then I'd go all
the way and move getInputStream() into the HttpMessage rather than wrap
it in a clumsy entity object.

HttpClient as it is supports different ways to provide a request body:
byte array, string, input stream, and multipart-mime (which we would
like to move to commons-codec). The idea of the Ic/OgEntity stuff was
to maintain this capability, and to match it with the complementary
conversion for incoming message bodies. As a framework, *without*
providing significantly more than samples for non-trivial content types.
I have no problem with dropping the idea, but then it should be dropped
completely so that only HttpOutgoingEntity remains (under whatever name).

> All these drivels aside I'll be happy to see a patch that keeps
> HttpEntity/HttpIncomingEntity/HttpOutcomingEntity paradigm (which is
> quite beautiful from the conceptual standpoint) and addresses the above
> mentioned shortcomings.

And I would love to provide one. Alas, as an IBMer I am not allowed to
post executable code without going through approval hell, involving
about 6 levels in the functional guidance hierarchy and two levels in
each the general law and IP law hierarchy. And I don't even have the
business case to get the approval process started. [I'm serious.]

> I just _personally_ do not see how this can be
> done, at least at this point

The proposal above should deal with your immediate concerns, which were
the typecasts. The fact that inappropriate methods become available in the
interfaces - like setOutgoingEntity() on a response on the client side -
merely exposes a problem that was hidden before by dealing with incoming 
and
outgoing entities through the same methods. I believe the problem stems
from using the same request/response objects on the client and server 
side,
although their function (incoming/outcoming) is reversed. I don't think
you can accurately address this problem by changing the entity interface
hierarchy. Whether there should be a framework for instantiating different
types of incoming entities at all is a separate point for discussion.

cheers,
  Roland
 

Re: [http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Posted by Oleg Kalnichevski <ol...@apache.org>.
Hi Roland

I guess I should have been more specific in my initial post.

My main point is that HttpEntity that cannot produce its content is
COMPLETELY useless unless cast to a more specific interface. Having to
cast HttpEntity interface EVERY TIME it is used results in a quite ugly
and IMO irritating code.

Likewise if HttpEntityEnclosingRequest interface is made to produce
an HttpOutpoingEntity on the client side, this interface is no longer
useable on the server, because the server expects an HttpIncomingEntity
instead. Inevitably one needs two interfaces
HttpIncomingEntityEnclosingRequest and
HttpOutgoingEntityEnclosingRequest to solve the problem. The same story
goes for the HttpResponse interface. One would also need two super
interfaces HttpIncomingResponse and HttpOutgoingResponse. For all these
interfaces one would need HttpMutable* counterparts. The situation gets
completely ridiculous, at least in my opinion, and we end up with a
classical over-designed API. 

The solution currently in place however imperfect gets the same job done
with just a few interfaces equally applicable on the server and the
client side. 

> So I would expect a protected getInputStream() in a base class, rather
> than a public one in the interface.

I would *really* like to avoid having to enforce a common base class for
HTTP entities

> My idea was to use a factory pattern for instantiating incoming
> entities:
> 
> StringEntity se = (StringEntity) 
> response.getIncomingEntity(StringEntity.class)

We have long maintained a stance that HttpClient is a content agnostic
library. Anything that has to do with content processing should be built
on top of HttpClient and should not be a part of the library. We
certainly should not get ourselves into the MIME content business. I
personally would rather prefer a simple consumer pattern where various
HTTP content consumers simply retrieve the content from
HttpEntity#getContent as an InputStream, hence the motivation for moving
this functionality to the base interface

All these drivels aside I'll be happy to see a patch that keeps
HttpEntity/HttpIncomingEntity/HttpOutcomingEntity paradigm (which is
quite beautiful from the conceptual standpoint) and addresses the above
mentioned shortcomings. I just _personally_ do not see how this can be
done, at least at this point

Cheers,

Oleg

On Thu, Apr 28, 2005 at 08:20:48AM +0200, Roland Weber wrote:
> Hi Oleg,
> 
> Mike's note made me think about this again...
> 
> > (2) HttpIncomingEntity interface can be gotten rid of. After all it is
> > perfectly reasonable for any generic entity to be able produce its
> > content. getInputStream method gets moved to HttpEntity
> 
> Do we need a public getInputStream() in the generic interfaces anyway?
> My idea was that the InputStream is used internally by the (incoming)
> entity to parse it's content, and that only a stream-type entity would
> provide "raw" access to it. So I would expect a protected getInputStream()
> in a base class, rather than a public one in the interface.
> 
> > (3) Rename HttpOutgoingEntity to HttpStreamableEntity. As far as I am
> > concerned ability to stream itself is optional behavior for an entity
> > (akin to HttpEntityEnclosingRequest) which should be treated as such
> 
> My motivation for distinguishing between incoming and outgoing entities
> was to keep the parsing and generating separate, although that sure is
> overkill for the many simple entity types.
> By moving one of the functionalities into the base interface, it becomes
> mandatory. And thinking of multipart MIME for which there are different
> parser implementations, I'd rather have the generation than the parsing
> mandatory.
> 
> > Presently HttpResponse and HttpEntityEnclosingRequest return a generic
> > HttpEntity interface in order to be useable on both client and server
> > side. From the design purism perspective this is probably quite okay. At
> > the same time in practical terms this approach requires HttpEntity to be
> > cast to either HttpIncomingEntity or HttpOutgoingEntity all the time to 
> be 
> > of any use. All these castings get quite irritating quite fast.
> 
> My idea was to use a factory pattern for instantiating incoming entities:
> 
> StringEntity se = (StringEntity) 
> response.getIncomingEntity(StringEntity.class)
> 
> whereas the outgoing entities have a generic writeTo(OutputStream). On the
> client side, entity enclosing requests would allow setting an outgoing 
> entity,
> and responses provide incoming entities. On the server, it's the requests
> that provide the incoming entity and the responses expect an outgoing 
> entity
> to be set. The opposite operations could either be forbidden, or they 
> could
> be implemented conditionally for "two-way" entities.
> 
> So I'd keep the incoming and outgoing entities as distinct attributes
> in the base class for HttpMessage, rather than casting a single attribute
> to either side. Again, sorry for not having the time to look into the 
> code.
> 
> cheers,
>   Roland

---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org


Re: [http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Posted by Roland Weber <RO...@de.ibm.com>.
Hi Oleg,

Mike's note made me think about this again...

> (2) HttpIncomingEntity interface can be gotten rid of. After all it is
> perfectly reasonable for any generic entity to be able produce its
> content. getInputStream method gets moved to HttpEntity

Do we need a public getInputStream() in the generic interfaces anyway?
My idea was that the InputStream is used internally by the (incoming)
entity to parse it's content, and that only a stream-type entity would
provide "raw" access to it. So I would expect a protected getInputStream()
in a base class, rather than a public one in the interface.

> (3) Rename HttpOutgoingEntity to HttpStreamableEntity. As far as I am
> concerned ability to stream itself is optional behavior for an entity
> (akin to HttpEntityEnclosingRequest) which should be treated as such

My motivation for distinguishing between incoming and outgoing entities
was to keep the parsing and generating separate, although that sure is
overkill for the many simple entity types.
By moving one of the functionalities into the base interface, it becomes
mandatory. And thinking of multipart MIME for which there are different
parser implementations, I'd rather have the generation than the parsing
mandatory.

> Presently HttpResponse and HttpEntityEnclosingRequest return a generic
> HttpEntity interface in order to be useable on both client and server
> side. From the design purism perspective this is probably quite okay. At
> the same time in practical terms this approach requires HttpEntity to be
> cast to either HttpIncomingEntity or HttpOutgoingEntity all the time to 
be 
> of any use. All these castings get quite irritating quite fast.

My idea was to use a factory pattern for instantiating incoming entities:

StringEntity se = (StringEntity) 
response.getIncomingEntity(StringEntity.class)

whereas the outgoing entities have a generic writeTo(OutputStream). On the
client side, entity enclosing requests would allow setting an outgoing 
entity,
and responses provide incoming entities. On the server, it's the requests
that provide the incoming entity and the responses expect an outgoing 
entity
to be set. The opposite operations could either be forbidden, or they 
could
be implemented conditionally for "two-way" entities.

So I'd keep the incoming and outgoing entities as distinct attributes
in the base class for HttpMessage, rather than casting a single attribute
to either side. Again, sorry for not having the time to look into the 
code.

cheers,
  Roland

Re: [http-common] RFC: HttpEntity, HttpIncomingEntity, HttpOutgoingEntity revisited

Posted by Roland Weber <RO...@de.ibm.com>.
Hi Oleg,

sounds reasonable. Go ahead. Do you want
to add a method to HttpEntity for checking
whether a non-repeatable entity has already
been consumed?

I'm sorry that I currently don't have the time
to dig into the new code.

cheers,
  Roland

Oleg Kalnichevski <ol...@apache.org> wrote on 26.04.2005 11:05:36:

> Folks,
> 
> After having spent some time working on the http-common API I would like
> to propose some changes to HttpEntity, HttpIncomingEntity &
> HttpOutgoingEntity interfaces. 
> 
> Presently HttpResponse and HttpEntityEnclosingRequest return a generic
> HttpEntity interface in order to be useable on both client and server
> side. From the design purism perspective this is probably quite okay. At
> the same time in practical terms this approach requires HttpEntity to be
> cast to either HttpIncomingEntity or HttpOutgoingEntity all the time to 
be 
> of any use. All these castings get quite irritating quite fast.
> 
> (1) Fundamentally the distinction between HttpIncomingEntity and
> HttpOutgoingEntity behaviors is not necessary
> 
> (2) HttpIncomingEntity interface can be gotten rid of. After all it is
> perfectly reasonable for any generic entity to be able produce its
> content. getInputStream method gets moved to HttpEntity
> 
> (3) Rename HttpOutgoingEntity to HttpStreamableEntity. As far as I am
> concerned ability to stream itself is optional behavior for an entity
> (akin to HttpEntityEnclosingRequest) which should be treated as such
> 
> This approach may create some problems for non-repeatable entities such
> as InputStreamEntity but they can be resolved by maintaining the object
> state and refusing to stream out the content if it has already been
> consumed through getInputStream method. I feel this is a small price to
> pay for a much less irritating API
> 
> What you think?
> 
> Oleg
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org
>