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