Hi
On 14/03/13 02:59, Steve Karlovic wrote:
Hello,
I am using CXF for RESTful services. I would like to capture the time it takes 
to marshal the response separately from the time it takes to write the response 
and send it to the client. It seems like the JAXRSOutInterceptor is responsible 
for the marshalling. Immediately after marshalling it appears that the write 
occurs as well. Is there a way to have a method I write in my own class to be 
called as soon as the response is marshalled but before the data is sent? Is 
there another interceptor I should be looking at as well? We are using 2.6.1.

Assuming it is JAXB, what you can do is to register a custom XMLStreamWriter which will calculate the time between writeStartDocument and writeStartDocument.

The custom writer can be registered from the out CXF interceptor or ResponseHandler filter, like this:

http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/XmlStreamWriterProvider.java

(see the two lines within the 'if' branch), on the trunk it is JAX-RS 2.0 ContainerResponseFilter which does it, but the same two lines will work in CXF 2.6.2 when done from the interceptor or ResponseHandler filter.

The actual custom interceptor may look like this:
http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/XmlStreamWriterProvider.java

except that all you will have to do is to override writeStartDocument & writeEndDocument instead

This will give you the time it takes to marshal.

Catching the actual time when the response has been sent can be trickier I guess. In JAX-RS 2.0 one can use

http://jax-rs-spec.java.net/nonav/2.0-SNAPSHOT/apidocs/javax/ws/rs/container/CompletionCallback.html

CXF will actually callback on it when the relevant async servlet callback is called, so it can be really close.

but that will work for the code using 2.0 AsyncResponse only, starting from 2.7.x.

I guess, what you can try to do is to replace an OutputStream on the message,

OutputStream os = outMessage.getContent(OutputStream.class);
and wrap it with some filtered output stream that will catch when say flush() is called, I'm not exactly sure how precise the data you can get with this approach. Another option may be is to replace HttpServletResponse with a wrapper (can be done from a servlet filter or even from CXF interceptor, it is registered on the inbound message as "HTTP.RESPONSE"), and override its ServletOutputStream, etc.

HTH, Sergey

Thanks,
Steve

Reply via email to