1

I'm generating page content like:

// index.jsp
<%
    List<Horse> horses = database.getHorses();
    for (Horse it : horses) {
        %>
        <div><%= it.getName() %></div>
       <%
    }
%>

is it possible to grab the entire page content at the end of the jsp file, and dump it into a String, like:

String page = this.getPrintWriter().toString();

I'm just curious if this is possible. I might try caching the page as a String, but would need to rewrite my page generation to build everything in one StringBuilder like:

StringBuilder sb = new StringBuilder();
sb.append("<div>"); sb.append(it.getName()); sb.append("</div>");
...
<%= sb.toString() %>
String cached = sb.toString();

Thanks

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
user246114
  • 50,223
  • 42
  • 112
  • 149
  • Why? What do you want to do with the "cached" value? The answer depends on that. – BalusC Jul 10 '10 at 03:04
  • I'm using google app engine, which has a memcache - I could take the String value of the entire page content, and put it in the memcache. Next time the a user requests that page, I can just immediately dump the entire content from memcache. I could of course cache the individual Horse objects, and regenerate the content, it will at least save me from hitting the database - just not sure what is a better practice - thanks – user246114 Jul 10 '10 at 03:09
  • Is it user-specific content? I.e. data is specific to each visitor. Or is it application-wide constant? I.e. just load once during webapp's startup and use forever without reloading it? – BalusC Jul 10 '10 at 03:28
  • Yeah it is data specific to each user - each user will have a different set of horses - they can modify that list, but won't happen frequently - so I'm thinking it could be cool to just cache the entire page content. – user246114 Jul 10 '10 at 03:47
  • 1
    Duplicate :/ http://stackoverflow.com/questions/3217589/basic-caching-strategy-for-a-simple-page – BalusC Jul 10 '10 at 04:08

2 Answers2

2

Since it's user-specific data, you can't use GAE's memcache for this. It's an application wide cache. I'd just store it in the session scope.

HttpSession session = request.getSession();
List<Horse> horses = (List<Horse>) session.getAttribute("horses");
if (horses == null) {
    horses = database.getHorses();
    session.setAttribute("horses", horses);
}

That said, try to avoid using scriptlets as much as possible. The above can perfectly be done in a Servlet class and you can display them using JSTL c:forEach as follows:

<c:forEach items="${horses}" var="horse">
    <div>${horse.name}</div>
</c:forEach>

Capturing generated page content can't be done by simply calling PrintWriter#toString(). The StringBuilder idea is funny, but it's really not worth it. Caching dynamic content has very little benefits for the purposes as you mention.

Best what you in this case can do with regard to page caching is just to leverage the webbrowser's default task to cache GET requests.

See also

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I might be misunderstanding, but gae doesn't care if it's user-specific data - I would just put it in a unique key like: cache.put(username+'_horses', stringOfHorses);. I think it's ok? Yeah I need to stop using the scriptlets for page generation. – user246114 Jul 10 '10 at 04:22
  • Or the session ID as obtained by `session.getId()`. After all, I don't think that it's beneficial. You risk duplicating `Horse` objects in cache and you would still like to remove it from the cache when the session expires, else the cache might blow. Cache makes more sense for applicationwide data. E.g. constant values which you'd like to display in dropdowns and so on. You can also put **all** `Horse` objects in a `Map` in the cache during webapp's startup and obtain them from there instead of the DB. I in turn only question the speed of retrieving *specific* `Horse` objects from it... – BalusC Jul 10 '10 at 04:38
1

I would create a HttpServlet which just retrieves page content from a real page (any kind of page, also JSP). Then cache it.

Next time the user makes the same request it would try to get the data from memcache and if present, retrieve only the mem cache content. Of course you have to check parameters, user id, e.t.c. which would change the content on cached page.

This way you could also have a full control of cache size (you can set cache expiration during PUT, limit cached page count e.t.c.)

BTW.. the answer with session data storage won't work!!. Session data is persisted only on single server. As appengine is running on some seriously large cluster (many-many machines), it won't ensure that two same request, from the same client would be served by the same machine - therefore the session data won't be accessible!

Learned this the hard way when i tried to do progress bars ;)

EDIT Seems like sessions are working now with appengine and are shared across all servers (as google states they are using memcache internaly)

Community
  • 1
  • 1
Marek Halmo
  • 2,181
  • 2
  • 15
  • 18