<?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; Java</title>
	<atom:link href="http://blog.anthonychaves.net/tag/java/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>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>The Evil Query</title>
		<link>http://blog.anthonychaves.net/2008/03/18/the-evil-query/</link>
		<comments>http://blog.anthonychaves.net/2008/03/18/the-evil-query/#comments</comments>
		<pubDate>Tue, 18 Mar 2008 16:21:47 +0000</pubDate>
		<dc:creator>Anthony Chaves</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[criteria]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[query]]></category>

		<guid isPermaLink="false">http://blog.anthonychaves.net/java/2008/03/18/the-evil-query</guid>
		<description><![CDATA[Here is the use case: I want to search all of my bookmarks by multiple tags with an &#8220;and&#8221; operation.  That means I want to see bookmarks that are tagged with Java AND JavaEE, not just Java and not just JavaEE.  I want to see bookmarks tagged with C# AND 3.5 not just [...]]]></description>
			<content:encoded><![CDATA[<p>Here is the use case: I want to search all of my bookmarks by multiple tags with an &#8220;and&#8221; operation.  That means I want to see bookmarks that are tagged with Java AND JavaEE, not just Java and not just JavaEE.  I want to see bookmarks tagged with C# AND 3.5 not just C# and not just 3.5.  For most of the project I&#8217;m using Hibernate and the Criteria API with a lot of success.  In this case I was not able to massage Hibernate into creating the correct query and that&#8217;s fine.  Hibernate has its uses and it is acceptable to write custom SQL when the need arises.  I wrote a method to build up the query and execute it.  Here is part of the method that builds up the query:</p>
<table bgcolor="#ffffff" border="0" cellpadding="3" cellspacing="0">
<tr>
<td align="left" nowrap="nowrap" valign="top"><code><font color="#000000">StringBuilder sqlString =<br />
</font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong>new </strong></font><font color="#000000">StringBuilder</font><font color="#000000">(<br />
</font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#2a00ff">                                "select distinct(b.id)<br />
</font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#2a00ff">from bookmarks b "</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">    </font><font color="#7f0055"><strong>int </strong></font><font color="#000000">counter = </font><font color="#990000">0</font><font color="#000000">;</font><br />
<font color="#ffffff">    </font><font color="#7f0055"><strong>for</strong></font><font color="#000000">(</font><font color="#000000">Tag tag : tags</font><font color="#000000">) {</font><br />
<font color="#ffffff">      </font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#000000">String alias = </font><font color="#2a00ff">"j" </font><font color="#000000">+ Integer.toString</font><font color="#000000">(</font><font color="#000000">counter</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">      </font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#000000">String joinFragment = </font><font color="#2a00ff">" inner join bookmarks_to_tags {alias}<br />
</font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#2a00ff"> on b.id = {alias}.bookmark_id<br />
</font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#2a00ff"> and {alias}.tag_id = ? "</font><font color="#000000">;</font><br />
<font color="#ffffff">      </font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#000000">joinFragment = joinFragment.replace</font><font color="#000000">(</font><font color="#2a00ff">"{alias}"</font><font color="#000000">, alias</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">      </font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#000000">sqlString.append</font><font color="#000000">(</font><font color="#000000">joinFragment</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">      </font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#7f0055"><strong> </strong></font></code><code><font color="#000000">counter++;</font><br />
<font color="#ffffff">    </font><font color="#000000">}</font></code></td>
</tr>
</table>
<p>Right away it looks like this query will get very expensive for large tag sets.  For smaller sets the query performs in a reasonable amount of time but more than 12 tags makes the query take quite a while.  This is exacerbated by the fact that this query will be executed multiple times if there is a sufficiently large result set (default is over 25) to give the user a paginated view.  This totally flies in the face of being nice to the database.  Hammering it with a complex query over and over won&#8217;t do the users any favors.</p>
<p>What are my options here?  I can work on making this query less complex (something that I will certainly do), but there is still the problem that, no matter how nice this query becomes, the query will be executed over and over as a user pages through the results.  The complexity of the query and its repeated execution makes the result set a good candidate for caching.  Caching the result set in memory with a key tied to the user or their session will allow the expensive query to be executed once with the bookmarks stored in a cache.  When the user pages through the results the cache will be consulted first where the result set will be stored.  I&#8217;m in the process of selecting a caching package for this project so I will post my selection and integration process soon.</p>
<p>Until then, I&#8217;d be happy to hear any suggestions on making this query a little nicer while preserving its &#8220;andness&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.anthonychaves.net/2008/03/18/the-evil-query/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>
		<item>
		<title>Spring Web MVC lists</title>
		<link>http://blog.anthonychaves.net/2008/02/13/spring-web-mvc-lists/</link>
		<comments>http://blog.anthonychaves.net/2008/02/13/spring-web-mvc-lists/#comments</comments>
		<pubDate>Wed, 13 Feb 2008 17:42:49 +0000</pubDate>
		<dc:creator>Anthony Chaves</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[coupling]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[frameworks]]></category>
		<category><![CDATA[lists]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[webapps]]></category>

		<guid isPermaLink="false">http://blog.anthonychaves.net/java/2008/02/13/spring-web-mvc-lists</guid>
		<description><![CDATA[I recently came across a blog post describing how *not* to use the Spring Web MVC form tag library.  Spring Web MVC is one of those things that has a high learning curve but it pays off big once you get the hang of it.  The form tag library is no exception.  [...]]]></description>
			<content:encoded><![CDATA[<p>I recently came across a blog post describing how *not* to use the Spring Web MVC form tag library.  Spring Web MVC is one of those things that has a high learning curve but it pays off big once you get the hang of it.  The form tag library is no exception.  The original blog poster seems to want to display a list of things the form user can manipulate and then send the changes back to the app server.  There are a few different ways we can do this with Spring Web MVC and some JSTL libraries so let&#8217;s take a look at the way I prefer to do it.<span id="more-47"></span></p>
<p>Spring Web MVC utilizes the ModelAndView class to encapsulate the M and V of MVC.  The model part is simply a map of objects associated with a request.  The key is the string name that you will use to access the object via the tag libraries.  Placing an object with a key of &#8220;userPrefs&#8221; into the map will make the UserPrefs object available to the HttpServletRequest and eventually part of the implicit request object that is part of JSPs.  In order to display any user data in a JSP it has to be part of the request object and it gets there by placing it in the Map used by ModelAndView.</p>
<p>In my experience with Spring Web MVC I&#8217;ve found that most form controller classes extend SimpleFormController.  SimpleFormController derives most of its lifecycle from AbstractFormController, which provides us with a few interesting methods.  There is one method in particular that is interesting.  The referenceData(HttpServletRequest request) method returns a Map and this method is called during the showForm(&#8230;) method.  showForm returns a ModelAndView object which will include whatever data is included in the Map returned by referenceData.  The default implementation of referenceData returns null, so we have to override it in our class that extends SimpleFormController.</p>
<p>Here is some example code from my controller class which extends SimpleFormController.  The point here is to provide a list of Bookmark objects to the form for a user to delete.</p>
<p><code><br />
<font color="#ffffff">  </font><font color="#646464">@Override</font><br />
<font color="#ffffff">  </font><font color="#7f0055"><strong>protected </strong></font><font color="#000000">Map referenceData</font><font color="#000000">(</font><font color="#000000">HttpServletRequest request</font><font color="#000000">) </font><font color="#7f0055"><strong>throws </strong></font><font color="#000000">Exception </font><font color="#000000">{</font><br />
<font color="#ffffff">    </font></code><code><font color="#000000"> </font></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code><font color="#000000">List userBookmarkList = </font></code><code><font color="#000000"> </font></code><code><font color="#000000"> </font></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code><font color="#000000">bookmarkService.getUserBookmarks</font><font color="#000000">(<br />
</font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code><font color="#000000">request.getUserPrincipal</font><font color="#000000">()</font><font color="#000000">.toString</font><font color="#000000">())</font><font color="#000000">;<br />
</font></code><code></code><code></code><code></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code><font color="#000000"><br />
</font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code><font color="#000000">Map model = </font><font color="#7f0055"><strong>new </strong></font><font color="#000000">HashMap</font><font color="#000000">()</font><font color="#000000">;</font><br />
<font color="#ffffff">    </font></code><code><font color="#000000"> </font></code><code><font color="#000000"> </font></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code><font color="#000000">model.put</font><font color="#000000">(</font><font color="#2a00ff">"userBookmarks"</font><font color="#000000">, userBookmarkList</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">    </font></code><code><font color="#000000"> </font></code><code><font color="#000000"> </font></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code><font color="#7f0055"><strong>return </strong></font><font color="#000000">model;</font><br />
<font color="#ffffff">  </font><font color="#000000">}</font></code></p>
<p>This is pretty simple example.  It&#8217;s first getting the user from the request object.  This is an authenticated session where a user has provided a login name and password.  That name is retrieved from the request object and used to get a List of all of their bookmarks.  The List is then put into a HashMap with the key &#8220;userBookmarks&#8221;.</p>
<p>After referenceData returns the Map those entries are then passed on to the view by the showForm method.  We can use a couple JSTL tag libraries to iterate over the list and display each bookmark while building the form.  The following is an excerpt from the view (NOTE – This is pre-Spring 2.5):</p>
<table border="0">
<tr>
<td nowrap="true"><code> <font color="#000000">&lt;%</font><font color="#646464">@ </font><font color="#000000">taglib prefix=</font><font color="#2a00ff">"form" </font><font color="#000000">uri=</font><font color="#2a00ff">"http://www.springframework.org/tags/form" </font><font color="#000000">%&gt;</font><br />
<font color="#000000">&lt;%</font><font color="#646464">@ </font><font color="#000000">taglib prefix=</font><font color="#2a00ff">"c" </font><font color="#000000">uri=</font><font color="#2a00ff">"http://java.sun.com/jsp/jstl/core" </font><font color="#000000">%&gt;</font><br />
<font color="#000000">...</font><br />
<font color="#000000">&lt;form:form&gt;</font><br />
<font color="#ffffff">  </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code><font color="#000000">&lt;c:forEach items=</font><font color="#2a00ff">"${userBookmarks}" </font><font color="#000000">var=</font><font color="#2a00ff">"bookmark"</font><font color="#000000">&gt;</font><br />
<font color="#ffffff">    </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code><font color="#000000">&lt;form:checkbox path=</font><font color="#2a00ff">"bookmarkIds" </font><font color="#000000">value=</font><font color="#2a00ff">"${bookmark.id}"</font><font color="#000000">/&gt;&lt;c:out value=</font><font color="#2a00ff">"${bookmark.id}"</font><font color="#000000">/&gt; -- &lt;c:out value=</font><font color="#2a00ff">"${bookmark.title}" </font><font color="#000000">escapeXml=</font><font color="#2a00ff">"true"</font><font color="#000000">/&gt;&lt;br/&gt;</font><br />
<font color="#ffffff">  </font></code><code></code><code></code><code></code><code></code><code></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code><font color="#000000">&lt;/c:forEach&gt;</font><br />
<font color="#ffffff">  </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code><font color="#000000">&lt;input type=</font><font color="#2a00ff">"submit" </font><font color="#000000">value=</font><font color="#2a00ff">"Delete checked bookmarks"</font><font color="#000000">/&gt;</font><br />
<font color="#000000">&lt;/form:form&gt;</font></code></td>
</tr>
</table>
<p>This view uses two tag libraries, one from JSTL, the other being the Spring form tag library.  Within the form tags the JSTL forEach tag is used to iterate over the list of bookmarks.  The list is obtained via the ${userBookmarks} variable.  This calling convention takes advantage of the search order for finding request parameters used by JSTL.  Part of the search includes looking in the request object that is part of every JSP.  The items attribute is the object we want to iterate over, that being the object keyed by userBookmarks.</p>
<p>That object is the List of bookmarks we got from the business tier.  By iterating over the bookmarks we have access to each Bookmark object and each of it&#8217;s fields.  The checkbox tag is used to build up the HTML view of the each bookmark with a check box next to it for the user to click.  When the user is done selecting bookmarks to delete the onSubmit method is called back in the controller.</p>
<p>So how does Spring know which bookmarks have been checked in the form?  The form object bound to the form keeps track of the checked bookmarks.  This form object is very simple, it encapsulates an array of Strings and provides a getter and setter for the array.</p>
<p><code><br />
<font color="#7f0055"><strong>package </strong></font><font color="#000000">net.anthonychaves.bookmarks.dataobject;</font></code></p>
<p><font color="#7f0055"><strong>public class </strong></font><font color="#000000">DeleteBookmarksForm </font><font color="#000000">{</font><br />
<font color="#ffffff"> </font><br />
<font color="#ffffff">  </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><font color="#7f0055"><strong>private </strong></font><font color="#000000">String</font><font color="#000000">[] </font><font color="#000000">bookmarkIds;</font></p>
<p><font color="#ffffff">  </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code> <font color="#ffffff">  </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><font color="#7f0055"><strong>public </strong></font><font color="#7f0055"><strong>void </strong></font><font color="#000000">setBookmarkIds</font><font color="#000000">(</font><font color="#000000">String</font><font color="#000000">[] </font><font color="#000000">bookmarkIds</font><font color="#000000">) {</font><br />
<font color="#ffffff">  </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code> <font color="#ffffff">  </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code> <font color="#ffffff">    </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><font color="#7f0055"><strong>this</strong></font><font color="#000000">.bookmarkIds = bookmarkIds;</font><br />
<font color="#ffffff">  </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code> <font color="#ffffff">  </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><font color="#000000">}</font></p>
<p><font color="#ffffff">  </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><font color="#ffffff">  </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><font color="#7f0055"><strong>public </strong></font><font color="#000000">String</font><font color="#000000">[] </font><font color="#000000">getBookmarkIds</font><font color="#000000">() {</font><br />
<font color="#ffffff">  </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code> <font color="#ffffff">  </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code> <font color="#ffffff">    </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><font color="#7f0055"><strong>return </strong></font><font color="#000000">bookmarkIds;</font><br />
<font color="#ffffff">  </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code> <font color="#ffffff">  </font><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><code></code><code><font color="#000000"> </font></code><font color="#000000">}</font><br />
<font color="#000000">}</font></p>
<p>The “value” part of our checkbox contains the bookmark ID.  When the checkbox is checked and the form is submitted the Spring dispatcher servlet collects all of the checked values of the same path into an array and puts them into the DeleteBookmarksForm object.  The form object is then passed to the DeleteBookmarksController via the onSubmit method.  We don&#8217;t have to implement the entire onSubmit method, though.  The default implementation calls doSubmitAction which takes only our command object, in this case DeleteBookmarksForm, as an argument.  Once we have a list of bookmark IDs to delete we can call the business tier to remove them from the database (after appropriate error checking, of course).</p>
<p>Spring 2.5 introduces the form:checkboxes tag which eliminates the need to use the JSTL forEach tag to iterate over the list of objects.  The checkboxes tag takes care of that for you.</p>
<p>There is more to working with lists in Spring Web MVC than the material presented here.  I&#8217;ve included a few references below in case you&#8217;re interested in finding out more.  Thanks for reading and as usual let me know if you have any questions or comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.anthonychaves.net/2008/02/13/spring-web-mvc-lists/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Response to Web Application: To Couple or Not to Couple?</title>
		<link>http://blog.anthonychaves.net/2008/02/08/response-to-web-application-to-couple-or-not-to-couple/</link>
		<comments>http://blog.anthonychaves.net/2008/02/08/response-to-web-application-to-couple-or-not-to-couple/#comments</comments>
		<pubDate>Fri, 08 Feb 2008 20:33:24 +0000</pubDate>
		<dc:creator>Anthony Chaves</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[coupling]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[frameworks]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[webapps]]></category>

		<guid isPermaLink="false">http://blog.anthonychaves.net/personal/2008/02/08/response-to-web-application-to-couple-or-not-to-couple</guid>
		<description><![CDATA[I just read this thread on The Server Side and it makes me nervous that people still ask this kind of question.  The thread starts off by asking &#8220;An usually annoying question when designing an action-based web application is: &#8220;Should I place everything in my action or should I separate the web logic from [...]]]></description>
			<content:encoded><![CDATA[<p>I just read <a href="http://www.theserverside.com/news/thread.tss?thread_id=48304" target="_blank">this thread on The Server Side</a> and it makes me nervous that people still ask this kind of question.  The thread starts off by asking &#8220;An usually annoying question when designing an action-based web application is: &#8220;Should I place everything in my action or should I separate the web logic from the business logic?&#8221; and the alarm bells in my head are going off already.<span id="more-45"></span></p>
<p>Business logic <strong>always</strong> belongs in its own layer.  Why?  Business logic is <strong>the thing</strong> that makes your application what it is.  It doesn&#8217;t matter how it&#8217;s dressed up &#8211; web app, desktop app, web service &#8211; the business logic accomplishes the task the user wants to perform.  Business logic <strong>is</strong> your application.  Because of its importance business logic should be placed in a sacred place where it will not be disturbed by presentation logic or infrastructure underpinnings &#8211; the business tier.  Separating the business concerns from all other concerns buys a lot of benefits for the development team.</p>
<p>What if aggregate data must be displayed in multiple locations?  For example, shopping cart data could be displayed on a checkout screen and also as a side bar while the user is still shopping.  In an action-based framework this code would be duplicated in two different actions.  It would be present in the action that generated checkout screen and again in the action that assembled the shopping view screen.  Rather than duplicate the code why not make a method call into the business layer that did the same thing?  The end result is the same except it separates the concerns of web and business logic.</p>
<p>Refactoring this code into a business tier method helps make our application more loosely coupled.  Loose coupling is important for business logic because it allows for easier reuse, testability and maintanence.  If the business logic is located in the action then creating a web service around it is going to be more difficult.  The business logic will have to be decouple from the web action and pulled into a layer where both the web action and web service can use it.  A good example of this would be a web page that displays new items available to a customer.  A web page is ok but the customer would have to keep checking back for updates.  An easier way to publish this information would be to make it available as an RSS feed the customer can subscribe to.  Duplicating the logic to get the new items isn&#8217;t particularly difficult, but why make maintenance more difficult than it has to be?  The application should be refactored to have a business layer that is responsible for getting the data which can be called by two different locations in the presentation layer (the web tier and the RSS feed creator).  Testing the business logic (you&#8217;re testing, right?) and bug fixing only have to be done in one location thanks to this refactoring too.</p>
<p>Another quote from the thread is, &#8220;The other side of the story is that to have two separate classes, one dealing with the http/web layer (ex: UserAction) and one dealing with the business logic layer (ex: UserService) is bureaucratic.&#8221;  This statement shows a lack of understanding of functional decomposition.  Each module should be responsible for one and only one thing.  If the web layer is for dealing with actions then actions should only be dealt with in the web layer.  If the web layer is for dealing with actions then business logic should <strong>not</strong> be dealt with at the web layer.  Business logic belongs where it can remain undisturbed by other concerns.  Tight coupling of these concerns makes testing more difficult because it requires testing everything it once rather than testing in isolation.  Because your application is only as good as the business logic the business layer should have a test suite that can be run without depending on action or presentation logic.</p>
<p>There are plenty of other reasons you should keep business and web logic separate.  This is in no way an exhaustive list, but it&#8217;s certainly something to think about.  If you&#8217;re building any professional application then business logic should always be in its own layer.  Not only will your boss/team/successor thank you for it, it&#8217;s good software development and you&#8217;ll thank yourself for it too.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.anthonychaves.net/2008/02/08/response-to-web-application-to-couple-or-not-to-couple/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RE: Generics Microbenchmark</title>
		<link>http://blog.anthonychaves.net/2007/03/13/re-generics-microbenchmark/</link>
		<comments>http://blog.anthonychaves.net/2007/03/13/re-generics-microbenchmark/#comments</comments>
		<pubDate>Wed, 14 Mar 2007 01:43:07 +0000</pubDate>
		<dc:creator>Anthony Chaves</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[generics]]></category>
		<category><![CDATA[java5]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://blog.anthonychaves.net/personal/2007/03/13/re-generics-microbenchmark</guid>
		<description><![CDATA[After the popularity of my &#8220;How&#8217;d this String get into my List&#60;Integer&#62;?!&#8221; post I decided to follow up with a few small benchmarks.  I got the idea from Geoffrey Wiseman who read my previous post and wondered about Generics performance.
Geoffrey wondered if there was any runtime run-time performance penalty taken by using Java 5 [...]]]></description>
			<content:encoded><![CDATA[<p>After the popularity of my &#8220;How&#8217;d this String get into my List&lt;Integer&gt;?!&#8221; post I decided to follow up with a few small benchmarks.  I got the idea from <a href="http://furiouspurpose.blogspot.com" title="Furious Purpose">Geoffrey Wiseman</a> who read my previous post and wondered about Generics performance.<span id="more-36"></span></p>
<p><a href="http://furiouspurpose.blogspot.com/2007/03/checked-generic-collections.html" title="Checked Generic Collections">Geoffrey wondered</a> if there was any runtime run-time performance penalty taken by using Java 5 Generic Collections over pre-Java 5 non-generic Collections.  At first I thought there was no such run-time penalty incurred because Generics is a <em>compile-time</em> feature, not a run-time feature.  The Java Language Specification states that the class implementing a Generic Collection at run-time is the <em>erasure</em> of the Generic compile-time type.  That is to say that the same class implements ArrayList&lt;String&gt;, ArrayList&lt;Integer&gt;, ArrayList&lt;MyType&gt; and ArrayList rather than creating a run-time type for each different Generic type.  Because all of these types are implemented by the same class I didn&#8217;t think there would be much of a performance penalty, if any at all.  But being a good computer scientist I decided to find out for myself.</p>
<p>I wrote a Java class called <a href="http://wiki.anthonychaves.net/index.php?title=Generics_demo" title="GenericsMicroBenchmark">GenericsMicroBenchmark</a> to do a little bit of my own benchmarking.  The first thing I did was declare and initialize two lists, one Generic the other not.</p>
<blockquote><p>private List&lt;Integer&gt; myInts = new ArrayList&lt;Integer&gt;();<br />
private List yourInts = new ArrayList();</p></blockquote>
<p>The class really gets started in the addXIntegers method.  This method takes one argument to determine the number of Integers to add to the List.  Each Integer is created by a call to Math.random() which is multiplied by the current value of the loop counter and then cast to an int.</p>
<blockquote><p>myInts.add((int) (Math.random() * i));</p></blockquote>
<p>I&#8217;m using autoboxing in that line to promote the resulting int to an Integer value which affords that value a place in my list.  The whole loop to populate the List&lt;Integer&gt; looks like:</p>
<blockquote><p>             long startTimeGeneric = System.currentTimeMillis();<br />
for (int i = 0; i &lt; x; ++i) {<br />
myInts.add((int) (Math.random() * i));<br />
}<br />
long endTimeGeneric = System.currentTimeMillis();<br />
genericRunTimeSum += (endTimeGeneric &#8211; startTimeGeneric);</p></blockquote>
<p>In addition to the loop there are some very imprecise timing markers.  The non-generic loop looks very similar to the Generic one:</p>
<blockquote><p>long startTime = System.currentTimeMillis();<br />
for (int i = 0; i &lt; x; ++i) {<br />
yourInts.add((int) (Math.random() * i));<br />
}<br />
long endTime = System.currentTimeMillis();<br />
uncheckedRunTimeSum += (endTime &#8211; startTime);</p></blockquote>
<p>The genericRunTimeSum and uncheckedRunTimeSum variables contain a running total of execution time because the addXIntegers method contains a loop that runs these blocks 1000 times each.  The running total is then divided by 1000 to give us an average run time for each type of list.  You can take a look at the class linked above for more details about what the addXIntegers method does.</p>
<p>Now that we have a basic driver that is doing slightly more than trivial object creation let&#8217;s run it.  A quick javac later and we have a class file to do our bidding.  I&#8217;ve run this class a few different ways to get some interesting metrics out of it.  The first thing I did was just run it with javac and no JVM arguments.  I passed in 100,000 as a command line argument to the GenericsMicroBenchmark class in order to create 100,000 Integers to add to each list.</p>
<blockquote><p>java net.anthonychaves.sandbox.generics.GenericsMicroBenchmark 100000<br />
Exception in thread &#8220;main&#8221; java.lang.OutOfMemoryError: Java heap space<br />
at java.util.Arrays.copyOf(Arrays.java:2760)<br />
at java.util.Arrays.copyOf(Arrays.java:2734)<br />
at java.util.ArrayList.ensureCapacity(ArrayList.java:167)<br />
at java.util.ArrayList.add(ArrayList.java:351)<br />
at net.anthonychaves.sandbox.generics.GenericsMicroBenchmark.addXIntegers(GenericsMicroBench<br />
mark.java:18)<br />
at net.anthonychaves.sandbox.generics.GenericsMicroBenchmark.main(GenericsMicroBenchmark.jav<br />
a:47)</p></blockquote>
<p>That&#8217;s weird.  I commented out the lines of code that print out the results from each loop in order to get only the average times at the end of the program execution.  I guess the garbage collector didn&#8217;t get to run while the stats were printing so we ran into this exception.  I can fix that by passing a few JVM arguments.</p>
<blockquote><p>java -Xms1536M -Xmx1536M net.anthonychaves.sandbox.generics.<br />
GenericsMicroBenchmark 100000<br />
Avg Generics: 74 ms<br />
Avg unchecked: 48 ms</p></blockquote>
<p>I ran the program a few times just to confirm the results and so far it looks like Generics are slower than their non-generic counterparts.  I can&#8217;t believe that&#8217;s possible since the same class implements both ArrayList and ArrayList&lt;Integer&gt; at run-time.  Let&#8217;s see what happens when I add the -server JVM argument.</p>
<blockquote><p>java -server -Xms1536M -Xmx1536M net.anthonychaves.sandbox.generics.GenericsMicroBenchmark 100000<br />
Avg Generics: 63 ms<br />
Avg unchecked: 41 ms</p></blockquote>
<p>That&#8217;s a little closer, but not quite &#8220;almost equal&#8221; like I&#8217;m looking for.  Maybe the JVM is just getting warmed up when the Generic version of the loop finishes and it&#8217;s ready to rock when the non-generic version runs.  If I change the order of the loops in the addXIntegers method and run it again we get:</p>
<blockquote><p>java -server -Xms1536M -Xmx1536M net.anthonychaves.sandbox.generics.GenericsMicroBenchmark 100000<br />
Avg Generics: 39 ms<br />
Avg unchecked: 64 ms</p></blockquote>
<p>It looks like we have a little role-reversal going on here.  Again, my guess is that the JVM is just getting warmed up by the time the first loop ends and the second loop beings.  Let&#8217;s see if we can even that out a little bit.  Because the JVM is doing certain helpful, unknown-to-me things let&#8217;s give each list a clean slate when it starts.  We can do this by suggesting to the JVM to run the garbage collector before we begin creating our 100,000 Integers for each list.</p>
<blockquote><p>java -server -Xms1536M -Xmx1536M net.anthonychaves.sandbox.generics.GenericsMicroBenchmark 100000<br />
Avg Generics: 27 ms<br />
Avg unchecked: 27 ms</p></blockquote>
<p>Ah, the great equalizer.  Adding a call to System.gc() runs the garbage collector at the end of each list population pair and gives each a fresh start when it begins again.  A few runs with the System.gc() call show that the performance of Generic and non-generic Collections in Java actually are just about equal in run-time performance.  Again, Generics are a <em>compile-time</em> feature and are implemented by the erasure of the compile-time type which is the same for all objects of that type (generic or not).  I have to admit I was getting a little worried for a few minutes there, but all things being equal the run-time performance is pretty much equal.</p>
<p>I have to note that even though the algorithm performance was vastly improved by adding the call to System.gc() the total program time slowed significantly due to some 100,000 suggested runs of the garbage collector.   You really shouldn&#8217;t do this in practice as the JVM knows what is best for you most of the time.  I did this just to give the List implementation a fair shot at performance for Generic and non-generic code.  It was nothing more than give each algorithm equal footing.</p>
<p>You can find the full code listing at <a href="http://wiki.anthonychaves.net/index.php?title=Generics_demo" title="GenericsMicroBenchmark">GenericsMicroBenchmark</a>.</p>
<p>Thanks again for reading.  Feel free to add any comments or corrections below.  Special thanks to <a href="http://furiouspurpose.blogspot.com" title="Furious Purpose">Geoffrey Wiseman</a> for giving me the idea for this post.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.anthonychaves.net/2007/03/13/re-generics-microbenchmark/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
