How to insert the size and response time into the page itself, at least partially?

I understand that this is a problem with the chicken and the egg and that it is impossible to accurately determine the time required to display the page (or the size of the response) and insert this number into the page itself without affecting any of the measures. However, I’m looking for a way to partially insert any number into the JSF / Facelets / Seam application page.

For example, at the bottom of the .jsf page:

<!-- page size: 10.3Kb --> <!-- render time: 0.2s --> 

I came across JSFUnit JSFTimer , which is very convenient. However, the phase listener approach does not allow the insertion of the results of the RENDER_RESPONSE phase into the page. Not sure how to access the size of the encrypted response so far.

Is there a quick and dirty way to connect to any event after processing at the end or after the end of RENDER_RESPONSE and enter both numbers in the page to be rendered? One way to get closer to this is perhaps through servlet filters, but I'm looking for something simpler; perhaps a trick with Seam or Facelets ...

Thank,
-A

+13
java servlets facelets jsf seam rendering
Jul 10 2018-10-10T00:
source share
3 answers

This is an ideal use case for Apache Commons IO CountingOutputStream . You need to create a Filter that uses an HttpServletResponseWrapper to replace the OutputStream with that answer and replace Writer and also wrap the wrapped OutputStream . Then take an instance of HttpServletResponseWrapper in the request area to get getByteCount() from CountingOutputStream .

Here is an example of running CountingFilter :

 public class CountingFilter implements Filter { @Override public void init(FilterConfig arg0) throws ServletException { // NOOP. } @Override public void doFilter(ServletRequest request, final ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpres = (HttpServletResponse) response; CountingServletResponse counter = new CountingServletResponse(httpres); HttpServletRequest httpreq = (HttpServletRequest) request; httpreq.setAttribute("counter", counter); chain.doFilter(request, counter); counter.flushBuffer(); // Push the last bits containing HTML comment. } @Override public void destroy() { // NOOP. } } 

CountingServletResponse :

 public class CountingServletResponse extends HttpServletResponseWrapper { private final long startTime; private final CountingServletOutputStream output; private final PrintWriter writer; public CountingServletResponse(HttpServletResponse response) throws IOException { super(response); startTime = System.nanoTime(); output = new CountingServletOutputStream(response.getOutputStream()); writer = new PrintWriter(output, true); } @Override public ServletOutputStream getOutputStream() throws IOException { return output; } @Override public PrintWriter getWriter() throws IOException { return writer; } @Override public void flushBuffer() throws IOException { writer.flush(); } public long getElapsedTime() { return System.nanoTime() - startTime; } public long getByteCount() throws IOException { flushBuffer(); // Ensure that all bytes are written at this point. return output.getByteCount(); } } 

CountingServletOutputStream :

 public class CountingServletOutputStream extends ServletOutputStream { private final CountingOutputStream output; public CountingServletOutputStream(ServletOutputStream output) { this.output = new CountingOutputStream(output); } @Override public void write(int b) throws IOException { output.write(b); } @Override public void flush() throws IOException { output.flush(); } public long getByteCount() { return output.getByteCount(); } } 

You can use it on any page (not even JSF) as follows:

 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>Counting demo</title> </h:head> <h:body> <h1>Hello World</h1> </h:body> </html> <!-- page size: #{counter.byteCount / 1000}KB --> <!-- render time: #{counter.elapsedTime / 1000000}ms --> 
+22
Jul 11 '10 at 1:36
source share

I wrote a blog post explaining how you could create an Interceptor that will measure each method by invoking your suture components where they are used.

You can find the blog post here . You need to scroll to the second part.

Basically, all you have to do is annotate the method you want to measure with @MeasureCalls and it will be automatically captured by the interceptor

 @Name("fooBean") @MeasureCalls public class FooBean 

The result will be something like this, showing the time it took in milliseconds, and how many times each method was called:

 284.94 ms 1 FooBean.getRandomDroplets() 284.56 ms 1 GahBean.getRandomDroplets() 201.60 ms 2 SohBean.searchRatedDoodlesWithinHead() 185.94 ms 1 FroBean.doSearchPopular() 157.63 ms 1 FroBean.doSearchRecent() 42.34 ms 1 FooBean.fetchMostRecentYodel() 41.94 ms 1 GahBean.getMostRecentYodel() 15.89 ms 1 FooBean.getNoOfYodels() 15.00 ms 1 GahBean.getNoOfYodels() 9.14 ms 1 SohBean.mainYodels() 1.11 ms 2 SohBean.trackHoorayEvent() 0.32 ms 1 FroBean.reset() 0.22 ms 43 NohBean.thumbPicture() 0.03 ms 18 FooBean.getMostRecentYodels() 0.01 ms 1 NohBean.profilePicture() 0.01 ms 1 FroBean.setToDefault() 0.01 ms 1 FroBean.getRecentMarker() 
+2
Jan 21 '11 at 15:53
source share

Or is there an asynchronous Javascript call that receives the response time and size from the server after it is ready? Treat it like a callback that needs to be completed after the page has loaded, and the values ​​are ready to be inserted.

0
Jul 10 '10 at 21:16
source share



All Articles