<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Technical Notes &#187; web</title>
	<atom:link href="http://blog.anthonychaves.net/tag/web/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.anthonychaves.net</link>
	<description>Life is software and jujitsu</description>
	<lastBuildDate>Tue, 16 Feb 2010 22:15:16 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>User authorization in RESTful Spring</title>
		<link>http://blog.anthonychaves.net/2010/02/06/user-authorization-in-restful-spring/</link>
		<comments>http://blog.anthonychaves.net/2010/02/06/user-authorization-in-restful-spring/#comments</comments>
		<pubDate>Sat, 06 Feb 2010 17:46:00 +0000</pubDate>
		<dc:creator>Anthony Chaves</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[interceptor]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.anthonychaves.net/?p=181</guid>
		<description><![CDATA[I&#8217;m having a lot of fun with the new RESTful features in Spring 3.0.  I&#8217;m sure you could tell by the number of RESTful Spring posts lately.
Last night I wrote a user authorization interceptor that makes sure there is a user associated with each resource request that requires it.  I&#8217;m structuring most of [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m having a lot of fun with the new RESTful features in Spring 3.0.  I&#8217;m sure you could tell by the number of RESTful Spring posts lately.</p>
<p>Last night I wrote a user authorization interceptor that makes sure there is a user associated with each resource request that requires it.  I&#8217;m structuring most of my new web apps in such a way that user authorization is required for almost all actions.  I had to make a choice of how to enforce user authorization in the app.  The two choices were between a Servlet filter and a HandlerInterceptor.</p>
<p>A Servlet Filter is part of the Java EE Servlet package.  Most of my Java web projects use Servlet Filters in some way so I wasn&#8217;t immediately opposed to using one to make sure there is a logged in user associated with a request.  Because I wanted possible errors to be properly rendered in my different view types using Spring I decided to use a HandlerInterceptor.</p>
<p>A HandlerInterceptor is a Spring interface that is pretty much analogous to a Servlet Filter in terms of structure, though it&#8217;s a little more focused in purposed.  The HandlerInterceptor is mostly concerned with text-based content, where Filters can be applied to any content type.  Filters are also more appropriate for setting headers and gzipping responses.  The Handler Interceptor is targeted for application logic.</p>
<p>This interceptor only checks to see that there is a user object associated with an resource request before passing it on to the handler (a controller).  In practice this may include more detailed authorization checks but for the example just checking for a user is fine.</p>
<pre name="code" class="java">
@Component
public class UserAuthorizationInterceptor extends HandlerInterceptorAdapter {

  private static final String UNAUTHORIZED_MSG = "You are not logged in.  You must log in or supply an API token.";

  @Override
  public boolean preHandle(HttpServletRequest request,
                        HttpServletResponse response,
                        Object handler) throws Exception {

    String uri = request.getRequestURI();
    User user = (User) request.getSession().getAttribute("user");

    if (user != null || uri.indexOf("login") != -1) {
      return true;
    } else {
      response.sendError(HttpServletResponse.SC_FORBIDDEN, UNAUTHORIZED_MSG);
      return false;
    }
  }
}
</pre>
<p>Initially I wanted any error messages to be rendered by my Atom, RSS and JSON views.  Any error message generated by the application should come back to the user in the requested data format.  But this is a RESTful app.  The REST philosophy already addresses the only error message that should come out of an authorization check with <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">HTTP status codes</a>.  The only error message that should come out of this interceptor is an &#8220;unauthorized&#8221; message.  HTTP supplies the 401 status code to indicate a user is unauthorized.  </p>
<p>The implication of using the 401 code is that the user should use HTTP authentication, either basic or digest.  That&#8217;s not appropriate for an application using OpenID and API tokens for user authentication.  Instead the 403 status code is more appropriate.  This means the client is forbidden from accessing the requested resource.  The server understood the request but the client is not allowed to access the resource, which is exactly the case when there is no logged in user associated with the request.  </p>
<p>Because HTTP already provides plenty of status codes for things that can go wrong we should rely on those codes when building RESTful applications.  There is no reason to supply an application-generated error message when the protocol supplies everything we need to deal with the problem.  The REST philosophy actually makes it much easier to write web apps because we&#8217;re using HTTP as it is intended to be used which takes a lot of responsibility off of our application code.  </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.anthonychaves.net/2010/02/06/user-authorization-in-restful-spring/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spring 3.0 Web MVC and JSON</title>
		<link>http://blog.anthonychaves.net/2010/02/01/spring-3-0-web-mvc-and-json/</link>
		<comments>http://blog.anthonychaves.net/2010/02/01/spring-3-0-web-mvc-and-json/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 14:24:55 +0000</pubDate>
		<dc:creator>Anthony Chaves</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[web mvc]]></category>

		<guid isPermaLink="false">http://blog.anthonychaves.net/?p=175</guid>
		<description><![CDATA[Over the weekend I got a chance to use Spring 3.0&#8217;s MappingJacksonJsonView and ContentNegotiatingViewResolver.  I&#8217;m very happy with how easy it was to integrate with my code.  I didn&#8217;t have to do very much at all to get JSON out of my web app.
Why would I want JSON out of the app instead [...]]]></description>
			<content:encoded><![CDATA[<p>Over the weekend I got a chance to use Spring 3.0&#8217;s MappingJacksonJsonView and ContentNegotiatingViewResolver.  I&#8217;m very happy with how easy it was to integrate with my code.  I didn&#8217;t have to do very much at all to get JSON out of my web app.</p>
<p>Why would I want JSON out of the app instead of HTML?  Interoperability is one reason.  Now instead of being bound to one web app, my own, my data can be shuttled to other apps in a commonly understood notation without screen scraping.  Of course we can also use Atom and RSS for data that can be massaged into those formats with the ContentNegotiatingViewResolver as well.  For stuff that can&#8217;t coerced into standardized XML, JSON is a great choice.</p>
<p>If you don&#8217;t know what JSON is, it&#8217;s basically a JavaScript text representation of a map that drills down into your object hierarchy if you have one.  Let&#8217;s say I want to get my user information.  The JSON representation is:</p>
<pre name="code" class="js">
{ "firstname":"Anthony", "lastname":"Chaves", "userid":"123456", "address":{ "street":"A Fake Street", "city": "Bradford", "state":"MA" } }
</pre>
<p>This JSON is valid JavaScript and parsed by the library of your choice.  The first three fields are just string data.  The address field is another map that contains data about my address.  This is produced because my Java class User has a field of class Address.  Address contains the street, city and state fields.  </p>
<p>To get the JSON output we should use a MappingJacksonJsonView.  This view uses the Jackson library to map our Java objects to JSON.  We  need the Jackson core and mapper jars on our classpath to make this view work.  I just copied them into my WEB-INF/lib directory.  </p>
<p>It should be noted that I could not get any combination of configuration and Jackson jar files to work using Glassfish 2.1.1.  Deploying the app failed due to a java.lang.VerifyError with the message &#8220;Cannot extend a final class.&#8221;  Duh.  The same app worked right from the start on Tomcat 6.0.24.  </p>
<p>Because we want to preserve the functionality of the web app and its HTML output we can&#8217;t cut out the UrlBasedViewResolver completely.  We want the app to function as normal when we get requests for .html files but return JSON when we get requests for .json files.  So user.html would be used to get the HTML output of a user page and user.json would be used to get the above JSON output for a different app.  </p>
<p>Spring 3.0 has a ContentNegotiatingViewResolver that does just this.  Based on the client accept header and the file extension, this view resolver determines the best view resolver to pass the request on to after the controller does its processing.  </p>
<pre name="code" class="xml">
&lt;bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
  &lt;property name="mediaTypes">
    &lt;map>
      &lt;entry key="html" value="text/html"/>
      &lt;entry key="json" value="application/json"/>
    &lt;/map>
  &lt;/property>
  &lt;property name="viewResolvers">
    &lt;list>
      &lt;bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        &lt;property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        &lt;property name="prefix" value="/WEB-INF/jsp/"/>
        &lt;property name="suffix" value=".jsp"/>
      &lt;/bean>
    &lt;/list>
  &lt;/property>
  &lt;property name="defaultViews">
    &lt;list>
      &lt;bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
        &lt;property name="prefixJson" value="true"/>
      &lt;/bean>
    &lt;/list>
  &lt;/property>
&lt;/bean>
</pre>
<p>For text/html content the ContentNegotiatingViewResolver sends requests on to the old UrlBasedViewResolver after the controller method returns.  For application/json or application/javascript requests the ContentNegotiatingViewResolver passes the request on to the MappingJacksonJsonView.  This view parses the object tree into JSON and gives us the output we want.  </p>
<p>The object tree is based on the objects in the Spring Web MVC model.  This means we have to add them to a ModelMap object in the controller.  In an HTML-based web app we might store data in the HttpSession object.  For JSON we need it in the ModelMap.  Let&#8217;s say we&#8217;re adding a tag to something.</p>
<pre name="code" class="java">
@RequestMapping(method=RequestMethod.GET)
public String getBookmarksWithTag(@RequestParam(value="tag") String tag, HttpSession session, ModelMap model) {
  User user = (User) session.getAttribute("user");

 doSomethingUseful(user);

  model.addAttribute(user);
  return "tags";
}
</pre>
<p>By placing the User object into the ModelMap, Spring has a reference to it when it comes time to make some JSON.  We still return a string, &#8220;tags&#8221;, so the UrlBasedViewResolver still returns the same jsp for text/html content.  After this controller method returns, Spring takes the result and sends it to the ContentNegotiatingViewResolver.  The &#8220;tags&#8221; return value is not used if the request is sent to the MappingJacksonJsonView.  It has no use for jsps.  If the request were for text/html the &#8220;tags&#8221; string would be used by the UrlBasedViewResolver.</p>
<p>Like I said, I&#8217;m happy with the new REST support in Spring 3.0 Web MVC.  It&#8217;s certainly lagging behind Rails in trendy features but it&#8217;s far more flexible overall.  There is a certain &#8220;style&#8221; to writing web apps that Rails guys have.  I&#8217;m convinced it&#8217;s just as easy to use this style in Spring as it is to do it in Rails but the huge amount of extraneous documentation and classes in Spring makes it more difficult than it should be to get down to business.  I&#8217;m not making a statement about the Spring framework itself, it&#8217;s certainly possible to do everything I want and need.  I just haven&#8217;t seen a good style guide or cookbook for RESTful web apps.  Maybe it&#8217;s because some of the features are still so new, being just added to the 3.0 branch.  Maybe we just haven&#8217;t found the right idioms yet.  </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.anthonychaves.net/2010/02/01/spring-3-0-web-mvc-and-json/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Login Tokens with Java Servlets</title>
		<link>http://blog.anthonychaves.net/2010/01/28/login-tokens-with-java-servlets/</link>
		<comments>http://blog.anthonychaves.net/2010/01/28/login-tokens-with-java-servlets/#comments</comments>
		<pubDate>Fri, 29 Jan 2010 02:32:04 +0000</pubDate>
		<dc:creator>Anthony Chaves</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[servlet]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.anthonychaves.net/?p=164</guid>
		<description><![CDATA[If you don&#8217;t want to read the whole thing, here is the short version: I wrote a servlet filter to log a user in from a token cookie that does not contain a user name and password.  It is released under the GPLv3 license.  It&#8217;s on github.  Please use it, please test [...]]]></description>
			<content:encoded><![CDATA[<p>If you don&#8217;t want to read the whole thing, here is the short version: I wrote a servlet filter to log a user in from a token cookie that does not contain a user name and password.  It is released under the GPLv3 license.  It&#8217;s on github.  Please use it, please test it, please send feedback and bug fixes.</p>
<p>Let&#8217;s talk about user authentication in web apps.  When a web app keeps track of my data, whether it&#8217;s bookmarks, book orders or bank data, I expect to log in with a reasonably secured username and password.  If I&#8217;m authenticated the web app sets up a cookie to track my session.  There are two parts to a session, the client side &#8211; a cookie is placed in my browser with a session id, and the server side &#8211; the app server uses a map with my user data keyed by my session id stored in the cookie sent back to me.</p>
<p>Once my browser has a session cookie it sends that cookie back to the web app with every HTTP request I make.  The app server uses the session id in that cookie to load my user data and, say, add a book to my shopping cart.  My user data is updated in the session and the web page I requested is sent back to the browser.  The next time I make a request for a web page the session cookie is sent back to the web app and again my user data is loaded from the session map.  Though this approach violates a strict RESTful architecture it&#8217;s the best we&#8217;ve got for now.</p>
<p>As long as I keep requesting web pages while my session is active I keep delaying the session timeout on the app server.  A session typically times out on an app server due to the cost of keeping all user data in memory in a session map.  With limited memory we have to timeout inactive user sessions so that the app server can serve active users more effectively (i.e. without crashing).  If I wait 5 minutes between web requests I&#8217;m likely to find my bank session timed out and I have to log in again.  When ordering books that timeout period may be 30 minutes or longer.  It seems like the more valuable the data, the shorter the session timeout.  This is to prevent another user from coming in and reusing a session tracking cookie for &#8220;bad things&#8221; like transferring all my money to his account.</p>
<p>This brings up the point that though I still have a session id in my browser, the session on the server side no longer exists.  What if I wasn&#8217;t done shopping for books and computer parts?  I have to log in again and start a new session &#8211; my browser gets a new cookie with a new session id and the app server starts a new session keyed by my session id.  My user data, hopefully my up-to-date shopping cart, is loaded into my new session and I may continue shopping with another 30 minute or so timeout.  If I keep requesting web pages my session timeout keeps moving to expire 30 minutes after my last page request.  I say 30 minutes but it could be any arbitrary period.  </p>
<p>Expiring user sessions is a good practice because it forces users to authenticate themselves every so often.  One user doesn&#8217;t always use one browser and one browser doesn&#8217;t always serve one person.  But what if that statement is close enough to true that it might as well be?  What if I&#8217;ve got 5 browsers where I&#8217;m the only user?  Sometimes I don&#8217;t want to be required to use the login form every time I use a web app.  </p>
<p>GMail can remember my login for two weeks.  Yahoo! Mail can, too.  I don&#8217;t have to log in every time I got to those web apps.  I wanted the same functionality for a Java-based web app I wrote and I couldn&#8217;t find anything to do something similar through the search engines.  The Java packages I found stored the user&#8217;s login information in the cookie in plain text.  The next time the user goes to the web app the form data is auto-populated by the plain-text username and password stored in the cookie.  This is a very bad &#8220;security&#8221; practice and the user *still* needs to visit a login page.  </p>
<p>Rather than storing a username and password in a cookie we can do a little better.  We can store a &#8220;token&#8221; in the cookie that is associated with the user.  This token does not store the user&#8217;s username or password, either in plain-text or encrypted. Instead the token is generated by the web app and placed in a cookie that does not track the user&#8217;s session.  This means the web app sends one more cookie, the login token, in addition to the session tracking cookie.</p>
<p>Any time after a user is authenticated we can set the login token cookie.  This could be as part of the login process if a login form has a &#8220;remember me&#8221; check box or at the user&#8217;s explicit request any time after authentication.  How does this work in practice?  Let&#8217;s look at some code.  First we&#8217;ll look at the TokenService class.  </p>
<pre name="code" class="java">
@Service
public class TokenService {

  @PersistenceUnit(unitName="bookmarksPU")
  EntityManagerFactory emf;

  public String setupNewLoginToken(User user) {
    PersistentLoginToken tonaken = new PersistentLoginToken();
    EntityManager em = emf.createEntityManager();

    em.getTransaction().begin();
    User u = em.find(User.class, user.getId());
    token.setUser(u);
    em.persist(token);
    em.getTransaction().commit();

    return token.getId();
  }

  public User loginWithToken(String tokenId) {
    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin();
    PersistentLoginToken token = (PersistentLoginToken) em.find(PersistentLoginToken.class, tokenId);

    User user = null;
    if (token != null) {
      user = token.getUser();
      em.remove(token);
      em.getTransaction().commit();
    } else {
      em.getTransaction().rollback();
      //TODO this is a forgery attempt
      throw new RuntimeException("Attempted login token cookie forgery");
    }
    return user;
  }
}
</pre>
<p>TokenService#setupNewLoginToken is called when we have a User object &#8211; sometime after authentication or when the user requests it.  TokenService#loginWithToken is called in a servlet filter before an HTTP request even makes it to our code.  In order for this to work we need to tie a login token to a user.  We do that through PersistentLoginToken.</p>
<pre name="code" class="java">
@Entity
@Table(name="persistentLoginTokens")
public class PersistentLoginToken {
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO, generator="uuid-hex")
  private String id;

  @ManyToOne
  private User user;

  public void setUser(User user) {
    this.user = user;
  }

  public User getUser() {
    return user;
  }

  public void setId(String id) {
    this.id = id;
  }

  public String getId() {
    return id;
  }
}
</pre>
<p>The table required (or generated) by this entity has an id column and a user_id column.  We have our JPA provider generate a 128-bit UUID to serve as the token id.  The user id is obtained from the user associated with this token.  Notice how we do not constrain the number of valid tokens a user can have at any particular time.  This means I can have valid login tokens across 5, 10 or 100+ browsers.  Each browser would get a new unique token when I log in using that browser.  </p>
<p>Back to the setupNewLoginToken method &#8211; this works by creating a new PersistentLoginToken object and associating it with a user.  When it PersistentLoginToken object is saved the JPA provider generates its UUID and makes an entry in the database.  Now that the PersistentLoginToken has a generated UUID we put that UUID into the loginToken cookie and add that cookie to the HttpResponse object.  We set the cookie&#8217;s expiration time to 1 week, though this can be set to whatever your web app requires.</p>
<p>This login token cookie is sent back to the browser at the end of this response.  The browser then sends this loginToken cookie to the web app on every subsequent request.  Though this is useless when I have an active session, I really want this cookie around when my session expires on the server side or my session tracking cookie expires on the browser side.  Let&#8217;s see what happens when I don&#8217;t have an active session and I visit the web app.</p>
<pre name="code" class="java">
@Component
public class PersistentLoginFilter implements Filter {

  @PersistenceUnit(unitName="webappPU")
  EntityManagerFactory emf;

  @Override
  public void doFilter(ServletRequest request,
                       ServletResponse response,
                       FilterChain chain) throws IOException, ServletException {

    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    Cookie tokenCookie = getCookieByName(httpRequest.getCookies(), "loginToken");

    HttpSession session = httpRequest.getSession();
    User user = (User) session.getAttribute("user");

    if (user == null &#038;&#038; tokenCookie != null) {
      user = tokenService.loginWithToken(tokenCookie.getValue());
      String tokenValue = tokenService.setupNewLoginToken(user);

      httpRequest.getSession().setAttribute("user", user);
      tokenCookie.setMaxAge(0);
      httpResponse.addCookie(tokenCookie);

      tokenCookie = new Cookie("loginToken", tokenValue);
      tokenCookie.setPath("/bookmarks");
      tokenCookie.setMaxAge(168 * 60 * 60);
      httpResponse.addCookie(tokenCookie);
    }

    chain.doFilter(httpRequest, httpResponse);
  }
// other methods omitted
}
</pre>
<p>The doFilter method looks for a User associated with the current web session.  The absence of a User and the presence of a login token cookie indicate it&#8217;s time to perform a user lookup and login based on the token cookie.  After finding the user based on a valid token the filter gives the user a new login token that is valid for another week.  This may or may not be ok for your web app.  I just didn&#8217;t feel like writing the code to set expiration of the new cookie to the remaining time on the original cookie.  </p>
<p>With our User in hand, we set it on the current session and let the request finish processing.  All this code is available at <a href="http://github.com/anthonychaves/bookmarks">http://github.com/anthonychaves/bookmarks</a> under the GPLv3 license.  Feel free to modify it, use it and submit feedback.  I know it&#8217;s not as generic as it could be &#8211; feel free to use it as a template for your own code.  </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.anthonychaves.net/2010/01/28/login-tokens-with-java-servlets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spring Web MVC and the benefits of pagination</title>
		<link>http://blog.anthonychaves.net/2008/03/14/spring-web-mvc-and-the-benefits-of-pagination/</link>
		<comments>http://blog.anthonychaves.net/2008/03/14/spring-web-mvc-and-the-benefits-of-pagination/#comments</comments>
		<pubDate>Fri, 14 Mar 2008 08:05:06 +0000</pubDate>
		<dc:creator>Anthony Chaves</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[criteria]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[pagination]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.anthonychaves.net/java/2008/03/14/spring-web-mvc-and-the-benefits-of-pagination</guid>
		<description><![CDATA[Lately I&#8217;ve been working on a project that keeps my web bookmarks sync&#8217;d across multiple computers and different web browsers.  The project is implemented in Java using JBoss 4.2.2, MySQL 5.0 and Spring 2.0.  It&#8217;s not a very big project right now, only about 40 class files and some small number of configuration [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I&#8217;ve been working on a project that keeps my web bookmarks sync&#8217;d across multiple computers and different web browsers.  The project is implemented in Java using JBoss 4.2.2, MySQL 5.0 and Spring 2.0.  It&#8217;s not a very big project right now, only about 40 class files and some small number of configuration files, but the amount of data the application deals with can get fairly large.<br />
<span id="more-48"></span><br />
Since this app isn&#8217;t the only way to manage ones bookmarks that everyone has used since the dawn of the web, a feature to import bookmarks from browsers was very high on the to-do list.  So across the set of different browsers I&#8217;ve used on the different computers, and the backed up bookmarks that survived system formats I have around 700 bookmarks in total.  That probably isn&#8217;t a whole lot, but that many spread across thousands of users can add up quickly.</p>
<p>I used jhat to find out that each bookmark object uses 1.5 kilobytes of memory.  It doesn&#8217;t take much to see that a LOT of bookmarks will fit into 8 gigs of memory on a medium sized server.  It would take hundreds of thousands of users to generate enough bookmark data to fill that memory.  At this point it&#8217;s clear the application server box can handle the data load (that isn&#8217;t to say that it can handle the network load, however).</p>
<p>I spent some time coming up with a nice data model and ORM design so accessing the data once it&#8217;s in memory is lightning fast, maybe even faster.  But what about when it&#8217;s on a hard disk, deep in the database?  Dragging my 700 bookmarks out of the database when I only want to view the 25 most frequently visited is a bit overkill, especially when you consider dragging everyone else&#8217;s bookmarks out at the same time.  Even though this is still a small-time application I decided to be nice to the database anyway and implement some kind of paging solution.  Spring Web MVC doesn&#8217;t offer much that I&#8217;m aware of in regard to pagination help so it looks like I&#8217;m on my own.</p>
<p>Pagination is something that must take place in the model with the help of the view.  Right away we&#8217;ve got two things to deal with, though it&#8217;s best to deal with them in isolation.  The first thing I did was get the model right.  I&#8217;m using Hibernate for ORM and the Criteria API makes it easy to set offsets and limits.  That is, I can ask for the 50 next items (limit) starting at row 20 (offset).</p>
<p>The Criteria API is great at getting your data into a workable format without HQL or SQL (not that either of them is a bad thing.  I enjoy working with them).  Let&#8217;s take a look at the method that gets some new bookmarks.</p>
<p class="java" align="left">
<table bgcolor="#ffffff" border="0" cellpadding="3" cellspacing="0">
<tr>
<td align="left" nowrap="nowrap" valign="top"><code><br />
<font color="#ffffff">  </font><font color="#7f0055"><strong>public </strong></font><font color="#000000">List&lt;Bookmark&gt; getNewestBookmarks</font><font color="#000000">(</font><font color="#7f0055"><strong>int </strong></font><font color="#000000">offset, </font><font color="#7f0055"><strong>int </strong></font><font color="#000000">numBookmarks</font><font color="#000000">) {</font><br />
<font color="#ffffff">    </font><font color="#000000">DetachedCriteria c = DetachedCriteria.forClass</font><font color="#000000">(</font><font color="#000000">Bookmark.</font><font color="#7f0055"><strong>class</strong></font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">    </font><font color="#000000">c.addOrder</font><font color="#000000">(</font><font color="#000000">Order.desc</font><font color="#000000">(</font><font color="#2a00ff">"createdDate"</font><font color="#000000">))</font><font color="#000000">;</font><br />
<font color="#ffffff">    </font><font color="#7f0055"><strong>return </strong></font><font color="#000000">getHibernateTemplate</font><font color="#000000">()</font><font color="#000000">.findByCriteria</font><font color="#000000">(</font><font color="#000000">c, offset, numBookmarks</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">  </font><font color="#000000">}</font></code></td>
</tr>
</table>
<p>So this method gets the model for us, but where do the offset and limit come from?  From the controller, of course.  This method is called from the controller like so:</p>
<p class="java" align="left">
<table bgcolor="#ffffff" border="0" cellpadding="3" cellspacing="0">
<tr>
<td align="left" nowrap="nowrap" valign="top"><code><br />
<font color="#ffffff">  </font><font color="#7f0055"><strong>public </strong></font><font color="#000000">ModelAndView newest</font><font color="#000000">(</font><font color="#000000">HttpServletRequest request, HttpServletResponse response</font><font color="#000000">) {</font><br />
<font color="#ffffff">    </font><font color="#7f0055"><strong>int </strong></font><font color="#000000">numberOfBookmarks = requestUtils.getSafeValueFromRequest</font><font color="#000000">(</font><font color="#000000">request, </font><font color="#2a00ff">"numberOfBookmarks"</font><font color="#000000">, </font><font color="#990000">250</font><font color="#000000">, defaultNumberOfNewest</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">    </font><font color="#7f0055"><strong>int </strong></font><font color="#000000">offset = requestUtils.getSafeValueFromRequest</font><font color="#000000">(</font><font color="#000000">request, </font><font color="#2a00ff">"offset"</font><font color="#000000">, </font><font color="#990000">300</font><font color="#000000">, </font><font color="#990000">0</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">    </font><br />
<font color="#ffffff">    </font><font color="#000000">List bookmarks = bookmarkService.getNewestBookmarks</font><font color="#000000">(</font><font color="#000000">offset, numberOfBookmarks</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">    </font><br />
<font color="#ffffff">    </font><font color="#000000">Map model = requestUtils.generateBookmarkModel</font><font color="#000000">(</font><font color="#000000">offset, numberOfBookmarks, </font><font color="#990000">300</font><font color="#000000">, bookmarks</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">    </font><font color="#000000">model.put</font><font color="#000000">(</font><font color="#2a00ff">"bookmarkListName"</font><font color="#000000">, </font><font color="#2a00ff">"Newest Bookmarks"</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">    </font><font color="#7f0055"><strong>return new </strong></font><font color="#000000">ModelAndView</font><font color="#000000">(</font><font color="#2a00ff">"index"</font><font color="#000000">, model</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">  </font><font color="#000000">}</font></code></td>
</tr>
</table>
<p>After sanity checking the offset and limit received from the request they are passed on to the getNewestBookmarks method to create and execute a somewhat unsightly query.  At this point, rather than gathering up all 700 of my bookmarks only 25 or so are returned.  What if I one day want to view the top 50 most visited bookmarks though?  Or what if I want to scroll through them one page at a time?  Passing in 0, 25 for the offset and limit of every method call won&#8217;t cut it.  The view needs to tell us how many bookmarks to retrieve and where to start the search.</p>
<p>Let&#8217;s say I&#8217;m viewing the top 25 bookmarks in my collection and I want to view 26-50.  Somehow the view has to tell the controller to tell the model about the  desired offset and limit.   This can be done by passing them in as request parameters.  In the code sample above, the HttpServletRequest object passed in to the controller contains values for offset and limit (numberOfBookmark) variables.  The JSP code below shows how to pass these parameters when a user clicks a link. (Actually I&#8217;m having a hard time getting the JSP to show up right when the code is rendered as HTML.  Just click the link and view the entire file instead.)</p>
<p><a href="http://blog.anthonychaves.net/wp-content/uploads/2008/03/operations.jsp" title="operations">JSP Pagination Operations</a></p>
<p>This page uses the JSTL core tag library to build the links that display the &#8220;previous/next/more/less&#8221; options.  Right after the body tag there is code to create four URLs, one for each action.  Each one starts off with a name and a value.  c:url var=&#8221;viewMoreUrl&#8221; value=&#8221;" creates a page-scoped variable called viewMoreUrl.  This variable will later be used to display the link that allows me to display five more bookmarks when I view the list.  The value is left blank which tells the tag to use the current base URL in creating the new one.  If I&#8217;m on a page that is located at /bookmarks/pages/viewUserBookmarks.html the new URL will start off as /bookmarks/pages/viewUserBookmarks.html.</p>
<p>Adding parameters to a URL is easy.  Using the c:param tag we get c:param name=&#8221;numberOfBookmarks&#8221; value=&#8221;${numberOfBookmarks + 5}&#8221;.  This tag appends a variable called numberOfBookmarks to the base URL described in the previous paragraph.  The value is a JSP expression that uses the numberOfBookmarks value passed in the model and increases it by five to pass back in the request.  Because we want the link only to display five more bookmarks and not change the offset that value will remain the value passed out in the model.  That gives us a URL that looks like /bookmarks/pages/viewUserBookmarks.html?numberOfBookmarks=30&amp;offset=0.</p>
<p>When this URL is accessed the request values for offset and numberOfBookmarks are exposed in the HttpServletRequest object for use by the controller.  When the getNewestBookmarks method is called the offset and limit are 0 and 30 instead of 0 and 25.</p>
<p>Obtaining a new offset value is done like getting a new limit value.  We start off with the same base URL and leave the numberOfBookmarks value unchanged.  We need to change the offset value though. c:param name=&#8221;offset&#8221; value=&#8221;${offset + numberOfBookmarks}&#8221; creates the offset value of the URL.  If we are viewing the newest bookmarks (offset 0)  and we are viewing 30 bookmarks when we click the link we should see bookmarks 31-60.</p>
<p>Here is an interesting thing to consider: what if a user goes to the second page using the default values.  The user will be viewing bookmarks 26-50.  The user then clicks the &#8220;view more&#8221; link three times and is now viewing 40 bookmarks.  The &#8220;previous&#8221; will now request that the offset be -15.  Unfortunately we can&#8217;t have negative bookmarks.  In this case the controller has some sanity checking built in to it.  The input parameter values must always be validated before they are used.  The controller uses a utility method to get a safe value for the offset and limit and ensures that neither can be a negative value.  This safe value is then passed back to the view once the model has been built.  Even though the offset in the request says -15 the controller will only go as low as 0.  More interesting work takes place in the generateBookmarksModel method, which I will talk about more next week.</p>
<p>What did I learn from making this effort?  Well, giving 8GB of RAM to an application server is a little overkill for a domain model like this.  The pagination that I came up with is still rudimentary, but a little more work could add more features, namely displaying page number links and the ability to change the number of bookmarks added at a time.</p>
<p>What is gained from this effort?  Being nice to the database opens up a few doors.  It dramatically improves scalability because it allows these requests to be stateless.  If an app server queried the database for all of my bookmarks then my session would have to be directed to that app server every time I made a request in order to not incur the cost of hitting the database again by another app server.  If round-robin load balancing is used the Hibernate session on each app server would contain a copy of my data and that&#8217;s a waste of resources, most notably it&#8217;s a hit to the database that didn&#8217;t have to happen.</p>
<p>Reducing the load on the database by getting only what we need and stateless sessions gives me the option of scaling the database with less difficulty.  A mostly-read application can get by with fewer hits to the write master and do a majority of their work from read-only slaves.   Spreading complex queries over multiple read slaves is much preferable to every app server hitting one database for every query.  By having stateless requests I can have more app servers (using less memory) hitting more database servers without maxing out the CPU utilization due to the cost of complex queries.</p>
<p>What should I do with the unused memory in the app server boxes?  Rather than give it to one app server instance for use as a cache it should be given to the pool of application servers for use as a cache.  One way to do that is with memcached.  I&#8217;ll talk about that more in the future too.</p>
<p>As always please leave comments.  I enjoy getting feedback on what I&#8217;ve written.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.anthonychaves.net/2008/03/14/spring-web-mvc-and-the-benefits-of-pagination/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
