users@jax-rs-spec.java.net

[jax-rs-spec users] [jsr339-experts] Re: Heads Up: Severe problem when rewriting responses! Is our Filter API suitable?

From: Markus KARG <markus_at_headcrashing.eu>
Date: Thu, 11 Oct 2012 23:25:00 +0200

Bill,

thanks for chiming in.

> Markus, in a response filter you can:
> * change the status
> * change/add/remove headers
> * change the Java Object entity (even set it to null)
> So I don't understand your problem.

the problem is that the response filter (or an interceptor, or a combination
- I actually don't care as long as it works) must change the entity
*representation* (the XML, not the Java Object).

Example: A JAX-RS resource method produces an XML String (as the filter must
work with any kind of resource method, let's assume that the filter just
does not know whether the method returns the String directly, or whether a
MBW is producing that XML by serializing any kind of Java Object). The
response filter must modify that XML if the request was sent by a particular
agent (in the real world use case: a particular Microsoft product that just
expects a particular BUGGY XML syntax, which JAXB just doesn't like to
produce for good reasons, as the filter solely exists to workaround a this
Microsoft bug).

(This filter actually exists and is working well, but so far it was a
Servlet Filter. As JAX-RS does not enforce Servlet containers, we want to
turn it into a JAX-RS filter and / or interceptor to make it run with any
kind of JAX-RS container).

So, how to capture that original XML production to transform it on demand?

When you try it using a container response filter, you know whether the
client was that Microsoft product, but you will notice that there is no way
to get the original XML inside of a container response filter to transform
it.

When you try it using an entity interceptor, you will get that XML easily by
capturing the subsequent chain element's production into a replacement
buffer output stream and you can send a different representation to the
client using the original output stream (just like the original Servlet
filter works like), but you have no chance to know whether the client
actually is that particular Microsoft product (and you don't want to
transform always as this would break all non-Microsoft agents).

So one must use both, a response filter plus an entity interceptor, write a
property ("Interceptor: You are needed!") into the context, check that
context in the interceptor, do the rewrite there. That's a rather hack, but
it is actually working, but you will notice that the client will never
receive the new XML completely if it is longer than the original XML. Why?
Simply because the RI 2.0 M08-1 sets a "Content-Length" header using the
original XML's length, and ignores the actual length produced by the
interceptor, so the client stops to read (at least cURL does and complains
about the rest of the bytes in the stream). A nice way to produce a buffer
overrun in the agent. And as you don't know the length produced by the
interceptor inside of the response filter, you cannot overwrite the header
there...

As you see, it is simply not working. That is my problem. :-(

Maybe I oversee a really simple solution?

Regards
Markus