Skip to main content

[jsr339-experts] Re: General rule for exposing/manipulating header values

  • From: Bill Burke <bburke@...>
  • To: jsr339-experts@...
  • Subject: [jsr339-experts] Re: General rule for exposing/manipulating header values
  • Date: Tue, 28 Feb 2012 11:03:54 -0500

On 2/28/12 4:53 AM, Marek Potociar wrote:

On 02/24/2012 10:01 PM, Bill Burke wrote:
This is related to my last comment on:

Any interface that manipulates or exposed header values the client and server 
side and within Filter or Interceptors has
to follow certain guidelines.  You have to be extremely careful on whether 
the header manipulation api deals with header
values that are strings or java.lang.Object.

A ReaderInterceptorContext the header values can ONLY be strings as they are 
ALWAYS provided from an HTTP message
(request on server side, response on client side). Vice-versa for 
WriterInterceptorContext. Header values may be actual
Objects rather than strings as they are provided by user-code. This is 
specifically what I was referring to in previous

Both RequestHeader and ResponseHeader instances can either be populated 
through an HTTP message or from user code since
they can be used on both client and server.  Therefore their interfaces that 
manipulate or expose header values must be
more generic and return java.lang.Object.

Furthermore, header values must not be marshalled into string values until 
you are about to send the bits on the wire.
And the following must be true:

FooHeader fh = new FooHeader();

Request/Response r = builder.header("foo", fh).build();
Object value = r.getReXXXXHeaders().getHeader("foo");

value == fh

Same reference equality must be true if the header value was set via the 
Invocation.Builder interface.  Why is this
important?  Well, consider a digital signature header like DKIM.  You really 
can't complete the header until you
calculate the signature of the entity and you might need information 
contained in the header object to calculate the
signature (i.e. a private key).

You can store the extra information needed for producing a signature in the 
request properties and then add the header
only once it's fully calculated. Or am I missing something?

In general, I lean towards the idea of exposing headers for reading only as 
strings (which is in line with your earlier
request on this mailing list) as I assume that the most prevalent use-cases for 
manipulating headers are "set-once" and

What you are suggesting is akin to marshalling the request before it is finished being built.

You have a point about using properties, but app developers will still want to be able to use a Java type to set header values in client request filters, message body writers, writer interceptors, and server response filters. Plus my intuition tells me that you will want to access the Java types instead of marshalling them into strings. I can see many cases where parsing/unparsing is a performance hit, or just burdensome on the developer.

Also, for the other use cases, I'm worried about the end-user experience and 
ability to write correct code.

I find it ironic that in this specific case you are worried about the end-user experience. The current filter/interceptor/request/response API is *littered* with these awkward end-user experiences. Please be consistent.

Since you
can set the value of the header using an arbitrary Java type, it is hard to 
make sure that the Object you're getting
from the map is of the type that you expect. In cases where the headers are 
used or modified by multiple filters the
correct defensive coding boilerplate is simply too much imho:

Object h = request.getHeader("Foo");
Foo foo;
if (h instanceof Foo) {
     foo = (Foo) h;
} else {
     hdOld = RuntimeDelegate.getInstance().createHeaderDelegate(h.getClass());
     hdFoo = RuntimeDelegate.getInstance().createHeaderDelegate(Foo.class);
     foo = hdFoo.fromString(hdOld.toString(h));

But how is the requirement of parsing and unparsing a String to access/modify a header better when the object is available? The only thing you are really saving is the first 3 lines of code.

Actually this is VERY USEFUL information. If the header value is a String, you know that the header value was created by the user. If it is a java type, you know that the user expects JAX-RS to handle the marshalling.

At last, this would once again open a problem in unified request/response. 
Note that having unified req/resp is not just
for the sake of nice API. It's a practical thing that lets users write common 
filters for the client and server side.

Well, you still have these exact same semantics in MessageBodyWriters where the headers are expressed as <String, Object>. So, I don't understand what your beef is. Be consistent with the semantics of MessageBodyWrtiers, IMO. If header values could be set with Java types, make those Java types available.

Bill Burke
JBoss, a division of Red Hat

[jsr339-experts] General rule for exposing/manipulating header values

Bill Burke 02/24/2012

[jsr339-experts] Re: General rule for exposing/manipulating header values

Marek Potociar 02/28/2012

[jsr339-experts] Re: General rule for exposing/manipulating header values

Bill Burke 02/28/2012
Please Confirm