<?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; spring</title>
	<atom:link href="http://blog.anthonychaves.net/category/spring/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>Wiring RESTful web services with Spring</title>
		<link>http://blog.anthonychaves.net/2009/12/10/wiring-restful-web-services-with-spring/</link>
		<comments>http://blog.anthonychaves.net/2009/12/10/wiring-restful-web-services-with-spring/#comments</comments>
		<pubDate>Fri, 11 Dec 2009 01:31:50 +0000</pubDate>
		<dc:creator>Anthony Chaves</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://blog.anthonychaves.net/?p=143</guid>
		<description><![CDATA[I&#8217;ve recently been using Spring 3.0M1 to make some RESTful APIs.  While working on the project a question came up a few times from different people: how do the &#60;jee:jndi-lookup/>, &#60;context:annotation-config/> and &#60;context:component-scan/> beans relate to each other?  I&#8217;ve got some sample code that I use as a reference when this question comes [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently been using Spring 3.0M1 to make some RESTful APIs.  While working on the project a question came up a few times from different people: how do the &lt;jee:jndi-lookup/>, &lt;context:annotation-config/> and &lt;context:component-scan/> beans relate to each other?  I&#8217;ve got some sample code that I use as a reference when this question comes up.</p>
<p>Let&#8217;s start with the &lt;jee:jndi-lookup/> bean.  Since a RESTful API probably runs in a web container we need to look up a data source, persistence unit or persistence context.  We define the persistence unit in WEB-INF/classes/META-INF/persistence.xml.</p>
<pre name="code" class="Xml:nocontrols">
&lt;?xml version="1.0"?>
&lt;persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
  &lt;persistence-unit name="bookmarksPU" transaction-type="RESOURCE_LOCAL">
    &lt;provider>org.apache.openjpa.persistence.PersistenceProviderImpl&lt;/provider>
    &lt;non-jta-data-source>jdbc/bookmarks&lt;/non-jta-data-source>
    &lt;class>net.anthonychaves.bookmarks.models.User&lt;/class>
    &lt;class>net.anthonychaves.bookmarks.models.Bookmark&lt;/class>
  &lt;/persistence-unit>
&lt;/persistence>
</pre>
<p>The bookmarksPU persistence unit is registered with the container when the webapp is deployed.  It looks up the jdbc/bookmarks datasource and uses it for access to the database.  Setting up this datasource is up to you based on your container.</p>
<p>The bookmarksPU is also bound to a JNDI name, persistence/bookmarksPU.  We can inject this persistence unit into our webapp in the form of an EntityManagerFactory after registering a bean in our Spring container.  We do this in our Spring configuration file by looking up the persistence unit in JNDI.</p>
<pre name="code" class="Xml:nocontrols">
&lt;jee:jndi-lookup id="bookmarksPU" jndi-name="persistence/bookmarksPU"/>
</pre>
<p>In our service layer we have a class UserService.</p>
<pre name="code" class="Java:nocontrols">
@Service
public class UserService {

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

  public void saveUser(User user) {
    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin();
    em.persist(user);
    em.getTransaction().commit();
  }

  public User findUser(String name) {
    EntityManager em = emf.createEntityManager();
    Query query = em.createQuery("select u from User u where u.name = ?1")
                    .setParameter(1, name);
    em.getTransaction().begin();
    User user = (User) query.getSingleResult();
    em.getTransaction().rollback();
    return user;
  }
}
</pre>
<p>Notice two things about this class: it is annotated with the org.springframework.stereotype.Service annotation and its EntityManagerFactory is annotated with the javax.persistence.PersistenceUnit annotation.    We want Spring to deal with both of these annotations.  We want the component, the class annotated by @Service, registered as a Spring bean without doing it manually in XML.  We also want Spring to inject an instance of EntityManagerFactory bound to the persistence/bookmarksPU persistence unit.  </p>
<p>One of the nice things about Spring is that we can rely on these annotations so we don&#8217;t have to create long XML configuration files.  We still need the XML config to tell Spring which classes it should examine for these annotations.  Enter the &lt;context:annotation-config/> and &lt;context:component-scan/> beans.  </p>
<p>Each of these beans implicitly creates instances of classes that implement the BeanPostProcessor interface.  The post processor created by the &lt;context:annotation-config/> bean that is most important to our case is the PersistenceAnnotationPostProcessorBean.  This bean finds the bookmarksPU bean created when we performed the JNDI lookup and injects it into the emf field annotated with @PersistenceUnit.</p>
<p>The &lt;context:annotation-config/> bean takes care of the javax.persistence annotation but it does not create a bean definition for the UserService class.  To do that we need the &lt;context:component-scan/> bean.  This bean scans the specified base package for classes annotated with @Component and its subclasses, which includes @Service.  By annotating the UserClass as a @Service we are spared from configuring it by hand in XML.</p>
<p>The &lt;context:component-scan/> bean only searches for annotations relevant to the current application context.  In this case we must define the service layer outside of the *-servlet.xml WebApplicationContext.  The @Controller annotation is valid in a WebApplicationContext where a @Service annotation is not.  We should instead keep our service layer configuration separate from the webapp configuration.  In services.xml we have our services defined.</p>
<pre name="code" class="Xml:nocontrols">
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.0.xsd

http://www.springframework.org/schema/jee

                           http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

  &lt;jee:jndi-lookup id="bookmarksPU" jndi-name="persistence/bookmarksPU"/>

  &lt;!-- here we need component-scan for the services and annotation-config for the persistence unit -->
  &lt;context:component-scan base-package="net.anthonychaves.bookmarks"/>
  &lt;context:annotation-config/>

&lt;/beans>
</pre>
<p>A WebApplicationContext inherits all the bean definitions from any imported ApplicationContexts.  If we import the services.xml file in our *-servlet.xml file we will inherit the fully wired UserService bean created by the BeanPostProcessor beans in that ApplicationContext.  We have a controller that needs an instance of UserService.</p>
<pre name="code" class="Java:nocontrols">
@Controller
@RequestMapping("/user")
public class UserController {

	@Autowired
	UserService userService;

	@Autowired
	ImageCaptchaService icservice;

	@RequestMapping(value="/new", method=RequestMethod.GET)
	public String newUser(ModelMap model) {
		model.addAttribute(new User());
		return "user_new";
	}

	@RequestMapping(method=RequestMethod.POST)
	public String createUser(@ModelAttribute("user") User user,
							 HttpSession session,
							 @RequestParam("j_captcha_response") String captchaResponse) {

		boolean validResponse = icservice.validateResponseForID(session.getId(), captchaResponse);
		if (validResponse) {
		  userService.saveUser(user);
		  session.setAttribute("user", user);
			return "redirect:/b/user";
		} else {
			return "redirect:/b/user/new";
		}
	}

	@RequestMapping(method=RequestMethod.GET)
	public String user(HttpSession session) {
	  if (session == null || session.getAttribute("user") == null) {
	    return "redirect:/b/user/new";
	  }

		User user = (User)session.getAttribute("user");
	  return "user";
	}

	@RequestMapping(method=RequestMethod.POST, value="/login")
	public String login(@RequestParam("name") String username, HttpSession session) {
	  User user = userService.findUser(username);
	  session.setAttribute("user", user);
    return "redirect:/b/user";
	}

	public void setUserService(UserService userService) {
	  this.userService = userService;
	}
}
</pre>
<p>By specifying the UserService in UserController as @Autowired we expect an AutowiredAnnotationBeanPostProcessor to inject an instance of UserService into an instance of this class.  Both the &lt;context:annotation-config/> and &lt;context:component-scan/> beans create instances of AutowiredAnnotationBeanPostProcessor.  The &lt;context:annotation-config/> bean creates a PersistenceAnnotationBeanPostProcessor which is not important to us here.  We don&#8217;t have any persistence units to inject.  </p>
<p>The &lt;context:component-scan/> bean creates an AutowiredAnnotationBeanPostProcessor and it also registers a bean definition for the UserController.  @Controller is a subclass of @Component and has several annotations that would only be used in a class annotated with @Controller.  The &lt;context:component-scan/> bean takes care of mapping any routes and parameters specified by the @RequestMapping, @RequestParam and other @Controller-related annotations.  </p>
<p>Our bookmarks-servlet.xml file needs only the &lt;context:component-scan/> bean defined to get our web classes up and running.  The full bookmarks-servlet.xml file is very simple.</p>
<pre name="code" class="Xml:nocontrols">
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.0.xsd

http://www.springframework.org/schema/jee

                           http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

  &lt;import resource="services.xml"/>

  &lt;!-- component-scan creates implicit AutowiredBeanPostProcessor,
             we don't need PersistenceAnnotationPostProcessor -->
  &lt;context:component-scan base-package="net.anthonychaves.bookmarks"/>

  &lt;bean id="viewResolver" 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;bean id="captchaService" class="net.anthonychaves.bookmarks.service.CaptchaServiceSingleton"
        factory-method="getInstance"/>

&lt;/beans>
</pre>
<p>This should hopefully make it very easy for anyone to quickly create at least a skeleton RESTful API with Spring.  Comments?  Let me know!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.anthonychaves.net/2009/12/10/wiring-restful-web-services-with-spring/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dummy Code (Quick&#8217;n&#039;Dirty vs. Engineered)</title>
		<link>http://blog.anthonychaves.net/2009/02/04/dummy-code-quickndirty-vs-engineered/</link>
		<comments>http://blog.anthonychaves.net/2009/02/04/dummy-code-quickndirty-vs-engineered/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 22:34:13 +0000</pubDate>
		<dc:creator>Anthony Chaves</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[career]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://blog.anthonychaves.net/?p=125</guid>
		<description><![CDATA[When creating software, two people will never write the same implementation of a method or system of non-trivial design.  Creating software is a problem solving process and there are usually many ways to solve one problem.  The solutions may differ in elegance and efficiency while giving the same output for a given set of inputs.  [...]]]></description>
			<content:encoded><![CDATA[<p>When creating software, two people will never write the same implementation of a method or system of non-trivial design.  Creating software is a problem solving process and there are usually many ways to solve one problem.  The solutions may differ in elegance and efficiency while giving the same output for a given set of inputs.  A correct solutions is a correct solution regardless of implementation.<span id="more-125"></span></p>
<p>Building software modules within a team requires communicating, at a minimum,  method or class signatures and a general idea of the functionality.  This may include a detailed design document clearly specifying method signature and a pseudo-code implementation or method stubs and comments about what the method should do right in the source file.  One thing that should never be used for communicating a signature and functionality is dummy code.</p>
<p>Dummy code looks like real code.  It is real code but it rarely works.  Even if it compiles it doesn&#8217;t produce the correct result when run.  Nor are there any tests that prove it (in)correct.  Dummy code exists only for the sake of its author&#8217;s gratification.</p>
<p>Rather than talk about the desired functionality through some more productive means the dummy code author thinks he is helpfully providing a guesstimate of correct implementation.  What he has actually done is provide a jumbled mess of non-working code cleverly disguised as a working part of the project when he checks it in to the SCM.  The dummy code author thinks someone else will come along and provide the correct implementation &#8220;later&#8221;.</p>
<p>What he doesn&#8217;t realize is that his dummy code is almost indistinguishable from code that should be part of the project.  The next person to try to reuse this code is in for hours of WTF moments trying to figure out WTF the code is supposed to do and why it&#8217;s got code branching five levels deep.</p>
<p>At my first post-college job I had a wonderful mentor.  Thys (pronounced <em>Tays</em>, like &#8220;taste&#8221; without the second &#8216;t&#8217;) and I were talking one day when he asked me a question.  &#8220;Anthony, if you were given a task of writing software that would only be run once would you do it quick-and-dirty or with a well-measured, engineered approach?&#8221;</p>
<p>How bad could &#8220;quick-and-diry&#8221; be if the software would run only once?  I thought about it for a moment before answering.  Quick and dirty.</p>
<p>Thys said he would never write quick and dirty software.  Doing so figuratively creates a  monkey on the developerment team&#8217;s back.  The software that only needs to run once inevitably needs to run a second time and a third time and eventually run regularly.  Thys helped me realize that software evolves and escapes.  Useful software will run indefinitely.  Any time and effort saved on the initial write will be lost 10 times (I made that number up.  It is actually higher.  Any want to provide real data or examples?) over on the maintenance, bug fixes and rewrites.</p>
<p>Writing dummy code is writing software quick and dirty without any idea of the implementation details.  Bad code and bad algorithms.  The worst of both worlds.  It&#8217;s been a long time since Thys and I had that conversation but the years have proven him right again and again.  Any code worth checking in to SCM is worth writing well.  That includes unit tests.</p>
<p>Dummy code has no place in SCM.  If you&#8217;re not going to correctly implement a method you stub out then don&#8217;t provide an implementation at all.  Leave some comments around the method stub if you have to.  Open a ticket in the issue tracking system to let someone know the method needs an implementation and describe the input and output.  Let the implementer determine which algorithms and data structures to use.</p>
<p>Dummy code is a hazard to software projects.  It violates the principle of least astonishment.  Next time you think about writing some remember that the next person that uses the code will waste time figuring out why it doesn&#8217;t work as expected.</p>
<p>If you check code in to your SCM where other people can pull it, take a look at what you&#8217;re checking in.  Does it work?  Does it work well?  Are there tests that prove it?  Helping someone by coding less is sometimes the best help of all.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.anthonychaves.net/2009/02/04/dummy-code-quickndirty-vs-engineered/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scalability round-table/forum on January 28</title>
		<link>http://blog.anthonychaves.net/2009/01/13/scalability-round-tableforum-on-january-28/</link>
		<comments>http://blog.anthonychaves.net/2009/01/13/scalability-round-tableforum-on-january-28/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 21:03:28 +0000</pubDate>
		<dc:creator>Anthony Chaves</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://blog.anthonychaves.net/?p=80</guid>
		<description><![CDATA[The Boston Scalability User Group is hosting a technology round-table meeting on Wednesday January 28th at 6 p.m.  The meeting is at the IBM Innovation Center in Waltham, MA.
This is the first time we&#8217;ve done the round-table style meeting and I&#8217;m excited to see how it goes.  Guests are encouraged to come prepared with questions, [...]]]></description>
			<content:encoded><![CDATA[<p>The Boston Scalability User Group is hosting a technology round-table meeting on Wednesday January 28th at 6 p.m.  The meeting is at the IBM Innovation Center in Waltham, MA.</p>
<p>This is the first time we&#8217;ve done the round-table style meeting and I&#8217;m excited to see how it goes.  Guests are encouraged to come prepared with questions, answers and opinions on application scalability tools, strategies and designs.  Hot topics will include platform and software stack, cloud computing and resources, vendor tools and support and CDNs. Those are my guesses about hot topics doesn&#8217;t mean the meeting is limited to those topics.</p>
<p>Guests, be the regular or first-timers, will drive the direction of the discussion.  We&#8217;ll talk about solving technical problems based on past experience or serve as an advisory panel on where and when to use a particular tool.</p>
<p>Full meeting details are at the <a href="http://www.bostonsug.org">BostonSUG web site</a>.  We ask that you sign up for the meeting at the <a href="http://www.bostonsug.org/meeting-registration/">meeting registration page</a> so we have an idea of how much food to buy.  There will be snacks and bottled water at this meeting.</p>
<p>Hope to see everyone on the 28th at 6 p.m.!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.anthonychaves.net/2009/01/13/scalability-round-tableforum-on-january-28/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Terracotta Tech Talk</title>
		<link>http://blog.anthonychaves.net/2008/05/20/53/</link>
		<comments>http://blog.anthonychaves.net/2008/05/20/53/#comments</comments>
		<pubDate>Tue, 20 May 2008 17:21:01 +0000</pubDate>
		<dc:creator>Anthony Chaves</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[terracotta]]></category>

		<guid isPermaLink="false">http://blog.anthonychaves.net/java/2008/05/20/53</guid>
		<description><![CDATA[I&#8217;m developing a Java/Spring web application deployed on JBoss 4.2.2 that makes heavy use of memcached in order to reduce the latency experienced by the user.  The user interacts with data that is (unbeknownst to them) in the cache.  In order to make changes permanent a message is placed on a queue that [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m developing a Java/Spring web application deployed on JBoss 4.2.2 that makes heavy use of memcached in order to reduce the latency experienced by the user.  The user interacts with data that is (unbeknownst to them) in the cache.  In order to make changes permanent a message is placed on a queue that is picked up by an MDB.  The message is just the key used to access the data in the cache.  The MDB takes the data out of the cache and then saves it to the database.  This greatly improves the user experience because they do not have to wait for the next page to load while costly database writes occur.  So far, so good.</p>
<p>In this case I am unfortunately duplicating data by separating the reads from the writes.  The data lives in the Hibernate session used by the read-only app server in order to load the data in the first place.  It also has to be loaded in the write-only app server in order for that Hibernate session to work with it, which brings me to the point of this post: Is there any way that I can use <a href="http://www.terracotta.org">Terracotta</a> to pool my Hibernate-managed objects into one pool used by both the read-only and write-only app servers?  I think I would like to pool my Hibernate second-level cache.  It seems like <a href="http://terracotta.org/confluence/display/explore/Hibernate">Terracotta can get the job done</a>.</p>
<p>That said, I&#8217;m anxious to explore this topic more when Orion Letizi from Terracotta Tech comes to speak at the <a href="http://www.bostonsug.org">Boston Scalability User Group</a> next Wednesday on May 28th.  The meeting starts at 6 p.m. at the IBM Innovation Center in Waltham, MA.  Of course there will be pizza and soda (sponsored by Terracotta &#8211; thank you!) so come to the meeting to have some food and explore what Terracotta can do for your project.  All the details, including directions, are on the <a href="http://www.bostonsug.org">Boston Scalability User Group</a> web site.  Remember, there will be pizza!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.anthonychaves.net/2008/05/20/53/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>
	</channel>
</rss>
