<?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>The Carbon Emitter &#187; mvc</title>
	<atom:link href="http://blog.carbonfive.com/tag/mvc/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.carbonfive.com</link>
	<description>The blog of Carbon Five</description>
	<lastBuildDate>Thu, 19 Apr 2012 16:48:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Exploring Client-side MVC with Backbone.js</title>
		<link>http://blog.carbonfive.com/2011/12/19/exploring-client-side-mvc-with-backbonejs/</link>
		<comments>http://blog.carbonfive.com/2011/12/19/exploring-client-side-mvc-with-backbonejs/#comments</comments>
		<pubDate>Mon, 19 Dec 2011 16:55:48 +0000</pubDate>
		<dc:creator>Jared Carroll</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[backbonejs]]></category>
		<category><![CDATA[coffeescript]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=5609</guid>
		<description><![CDATA[Backbone.js continues to gain popularity in the JavaScript MVC community. I decided to give it a try by creating a simple, single-page app to CRUD a single domain model. While it wasn&#8217;t as trivial as a traditional server-side implementation in &#8230; <a href="http://blog.carbonfive.com/2011/12/19/exploring-client-side-mvc-with-backbonejs/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>
<a href="http://documentcloud.github.com/backbone">Backbone.js</a> continues to gain popularity in the JavaScript MVC community. I decided to give it a try by creating a simple, single-page app to CRUD a single domain model.
</p>
<p>
While it wasn&#8217;t as trivial as a traditional server-side implementation in Rails, it did turn out relatively clean. This is a long post, and if you make it through it, let me know what you think.
</p>
<p><span id="more-5609"></span></p>
<h2>Server-side Setup</h2>
<p>
Our server-side is a stock Rails 3.1 app. We&#8217;ll go with a classic blog app consisting of a single <code>Post</code> model to CRUD.
</p>
<p><script src="https://gist.github.com/1493846.js?file=gistfile1.sh"></script></p>
<p>
We&#8217;ll use the <a href="https://github.com/meleyal/backbone-on-rails">backbone-on-rails</a> Ruby gem to add <em>backbone.js</em> and <em>underscore.js</em> (backbone.js&#8217;s only dependency) to our Rails app.
</p>
<p><script src="https://gist.github.com/1493848.js"></script></p>
<p>
The <em>backbone.js</em> and <em>underscore.js</em> files are <strong>not</strong> copied into your Rails app&#8217;s directory. They&#8217;re both automatically loaded by the <code>backbone-on-rails</code> gem (the <code>jquery-rails</code> Ruby includes <em>jquery.js</em> and <em>jquery_ujs.js</em> the same way).
</p>
<p>
Let&#8217;s use the scaffold generator from <code>backbone-on-rails</code> to generate our client-side Backbone.js objects.
</p>
<p><script src="https://gist.github.com/1493849.js"> </script></p>
<p>
We&#8217;ll be using CoffeeScript, the Rails default client-side language, throughout our Backbone app.  CoffeeScript&#8217;s cleaner, Ruby-like syntax will help make the code more readable and understandable.
</p>
<h2>Listing Posts</h2>
<p>
We&#8217;ll start our app by implementing a &#8220;Read&#8221; action, the homepage. The homepage will be a list of all our posts. The <code>backbone-on-rails</code> scaffold generator has already created for us a router, an index view and template, a collection, and a model. To wire up the homepage we&#8217;ll need to modify our router.
</p>
<p>
Backbone routers are like controllers in Rails. They map routes to actions. The empty route represents the default action, in our case, the homepage.
</p>
<p><em>app/assets/javascripts/routers/posts_router.js.coffee</em><br />
<script src="https://gist.github.com/1493850.js"> </script></p>
<p>
In our <code>index</code> action, we create a <code>Posts</code> collection, a view for the collection, and then tell the collection to fetch its posts from the server. We don&#8217;t tell the view to render itself because the fetch is asynchronous. We&#8217;ll see later how the view uses an event handler to render itself after the fetch.
</p>
<p>
The <code>Posts</code> collection is configured to make server-side requests to our Rails app at &#8220;/posts&#8221; and to contain <code>Post</code> models.
</p>
<p><em>app/assets/javascripts/collections/posts.js.coffee</em><br />
<script src="https://gist.github.com/1493863.js"> </script></p>
<p>
Our <code>Post</code> model is as simple as it gets. It&#8217;s just a <code>Backbone.Model</code> subclass and contains no custom logic.
</p>
<p><em>app/assets/javascripts/models/post.js.coffee</em><br />
<script src="https://gist.github.com/1493865.js"> </script></p>
<p>
Before we take a look at the <code>PostsIndex</code> view, let&#8217;s first quickly go over the Rails layout used on the server-side.
</p>
<p><em>app/views/layouts/application.html.erb</em><br />
<script src="https://gist.github.com/1493867.js"> </script></p>
<p>
The only change we&#8217;ve made to this default Rails layout is the addition of a single &#8220;#app&#8221; <code>&lt;div&gt;</code>. This <code>&lt;div&gt;</code> will act as the container for our app. Each Backbone view will replace its contents.
</p>
<p>
Now we can take a look at the Backbone view.
</p>
<p><em>app/assets/javascripts/views/posts/posts_index.js.coffee</em><br />
<script src="https://gist.github.com/1493868.js"> </script></p>
<p>
On initialization, the view binds its <code>render</code> method as a handler to its collection&#8217;s <code>reset</code> event (this is the <code>Posts</code> collection we created in the <code>Blog.Routers.Posts#index</code> action). The <code>Posts</code> collection will trigger a <code>reset</code> event after successfully fetching its posts from the server. When the event is fired, the view will render its template and create and render another view for each <code>Post</code> in its collection.
</p>
<p>
Here&#8217;s the template used by the <code>PostsIndex</code> view:
</p>
<p><em>app/assets/templates/posts/index.jst.eco</em><br />
<script src="https://gist.github.com/1493870.js"> </script></p>
<p>
This table will be populated by the view used for each post in the collection:
</p>
<p><em>app/assets/javascripts/views/posts/posts_item.js.coffee</em><br />
<script src="https://gist.github.com/1493874.js"> </script></p>
<p>
And its template:
</p>
<p><em>app/assets/templates/posts/item.jst.eco</em><br />
<script src="https://gist.github.com/1493879.js"> </script></p>
<p>
There&#8217;s one last thing we need to do before we can view our homepage in a browser: we have to bootstrap our app&#8217;s router.
</p>
<p><em>app/assets/javascripts/blog.js.coffee</em><br />
<script src="https://gist.github.com/1493882.js"> </script></p>
<p>
An <code>onDOMReady</code> event handler invokes an <code>init</code> function that creates a <code>PostsRouter</code> and tells Backbone to start monitoring all hashchange events. All our client-side pages will use hash fragments as URLs. Backbone will listen for hash fragment changes and route them using the routes specified in our <code>PostsRouter</code>.
</p>
<p>
Finally we can now start our Rails server and hit our app at <a href="http://localhost:3000/posts">http://localhost:3000/posts</a>. Unfortunately, we don&#8217;t have any posts yet. So let&#8217;s move on to creating a post.
</p>
<h2>Creating a Post</h2>
<p>
At the bottom of our existing home template is a link to create a new post:
</p>
<p><em>app/assets/templates/posts/index.jst.eco</em><br />
<script src="https://gist.github.com/1493885.js"> </script></p>
<p>
This means we need to add another route and action to our <code>PostsRouter</code>.
</p>
<p><em>app/assets/javascripts/routers/posts_router.js.coffee</em><br />
<script src="https://gist.github.com/1493888.js"> </script></p>
<p>
In our <code>new</code> action, we create a <code>Post</code> model, then create a <code>Posts</code> collection and bind an anonymous handler to its <code>add</code> event. A collection will fire an <code>add</code> event whenever a new model is added to it. Our <code>add</code> event handler performs the equivalent of a server-side redirect by navigating the router to the &#8220;empty&#8221; router (the homepage). Finally we create and render a view to submit a new post.
</p>
<p><em>app/assets/javascripts/views/posts/posts_new.js.coffee</em><br />
<script src="https://gist.github.com/1493889.js"> </script></p>
<p>
The element (<code>PostsNew#el</code>) used in our new post view is the global &#8220;#app&#8221; <code>&lt;div&gt;</code>. The new post view will replace the contents of this <code>&lt;div&gt;</code> with its own template containing a form to submit a new post.
</p>
<p>
The view also registers a handler to the submit event from the <code>&lt;form&gt;</code> in its template. This handler stops the default form submission behavior and then asks its posts collection to create a new post. This will result in an HTTP POST request to the server and, if successful, the collection will fire an <code>add</code> event. This is the same event our <code>PostsRouter</code>, in its <code>new</code> action, bound an anonymous &#8220;redirect&#8221; handler to.
</p>
<p>
And here is the new post view&#8217;s template:
</p>
<p><em>app/assets/templates/posts/new.jst.eco</em><br />
<script src="https://gist.github.com/1493891.js"> </script></p>
<p>
Great, we can now create posts. However, we can&#8217;t let people create posts without a title and a body. Let&#8217;s see what we can do to validate our new posts.
</p>
<h2>Validating a Post</h2>
<p>
Adding some client-side validation will help improve the responsiveness of our UI. We&#8217;ll still validate posts on the server-side, but for the user&#8217;s sake, I feel this duplication is worth the tradeoff.
</p>
<p>
Backbone models include a <code>validate</code> method that can be used to perform custom validations. However, as Rails developers we&#8217;re used to <code>ActiveRecord</code>&#8216;s high-level, declarative approach to validation. And thanks to the <a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/">jQuery validation plugin</a>, we can have declarative validation on the client-side too.
</p>
<p>
First, download the plugin (<strong>after downloading and unzipping it, remember to restart your Rails server</strong>).
</p>
<p><script src="https://gist.github.com/1493892.js"> </script></p>
<p>
Next, add the plugin to our application&#8217;s JavaScript manifest file.
</p>
<p><em>app/assets/javascripts/application.js</em><br />
<script src="https://gist.github.com/1493895.js"> </script></p>
<p>
Now we can add some validation to our new posts.
</p>
<p><em>app/assets/javascripts/views/posts/posts_new.js.coffee</em><br />
<script src="https://gist.github.com/1493896.js"> </script></p>
<p>
The jQuery validate plugin allows you to specify per-attribute validation rules. Here we&#8217;re requiring a title and a body.  The <code>validate</code> method will stop the form submission when validation fails. This will also prevent the new post view&#8217;s form submission handler, <code>#create</code>, from executing as well.
</p>
<p>
Go and give it a try in the browser. Submitting a post without a title and body will now fail and display an error message(s).
</p>
<h2>Viewing a Post</h2>
<p>
Ok, so far we can display a list of posts, create a post, and validate a post. Next up is: viewing an individual post.
</p>
<p>
On our home page, each post row included the following link for viewing the post:
</p>
<p><em>app/assets/templates/posts/item.jst.eco</em><br />
<script src="https://gist.github.com/1493897.js"> </script></p>
<p>
Let&#8217;s add a route and action to our router for this post page (i.e., <code>#show</code>).
</p>
<p><em>app/assets/javascripts/routers/posts_router.js.coffee</em><br />
<script src="https://gist.github.com/1493898.js"> </script></p>
<p>
This newest route includes a named parameter, <code>:id</code>. Backbone will automatically pass the named parameter&#8217;s value as an argument to our <code>#show</code> action.
</p>
<p>
Currently in Backbone, fetching an individual model isn&#8217;t very elegant. Above is one of the cleanest ways. You first create a model with the requested id, then add the model to a collection, and finally, tell the model to <code>fetch</code> itself.
</p>
<p>
Our <code>#show</code> action also creates an instance of the following <code>PostsShow</code> view for the individual post.
</p>
<p><em>app/assets/javascripts/views/posts/posts_show.js.coffee</em><br />
<script src="https://gist.github.com/1493900.js"> </script></p>
<p>
During initialization, the view adds a handler to its <code>Post</code>&#8216;s <code>change</code> event. The <code>Post</code> will fire a <code>change</code> event after it has been successfully <code>fetch</code>ed.
</p>
<p>
The element (<code>PostsShow#el</code>) for this view is the same global &#8220;#app&#8221; <code>&lt;div&gt;</code> container that was used by the post list and new post views. And like those two views, an individual post view will also replace the contents of this <code>&lt;div&gt;</code>.
</p>
<p>
And here&#8217;s the posts show view&#8217;s template:
</p>
<p><em>app/assets/templates/posts/show.jst.eco</em><br />
<script src="https://gist.github.com/1493901.js"> </script></p>
<p>
The &#8220;back&#8221; link goes back to our homepage.
</p>
<h2>Client-side MVC</h2>
<p>
Backbone.js brings the power and maintainability of MVC to the client-side. Routers can be used like Rails server-side controllers to create responsive, single-page apps. Views are also like controllers, but instead of responding to url changes, they respond to DOM level events, such as link clicks and form submissions. Templates contain the app&#8217;s markup, they&#8217;re what Rails calls views. Models and collections round out Backbone.js, providing traditional class-based, client-side domain modeling.
</p>
<p>
We&#8217;ve only covered the first two letters in CRUD, but it was a lot!  I hope this article can give you some direction in implementing the rest of them. The client-side JavaScript MVC space is growing rapidly. Backbone&#8217;s quick and easy Rails integration makes it an easy sell but there are other options. Be sure to research other frameworks before evaluating what works best for you.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2011/12/19/exploring-client-side-mvc-with-backbonejs/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Stripes: A Successful First Project</title>
		<link>http://blog.carbonfive.com/2009/02/26/stripes-a-succesful-first-project/</link>
		<comments>http://blog.carbonfive.com/2009/02/26/stripes-a-succesful-first-project/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 12:12:47 +0000</pubDate>
		<dc:creator>Christian Nelson</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[stripes]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=301</guid>
		<description><![CDATA[We&#8217;re wrapping up a project that I&#8217;ve been leading since September and I&#8217;ve been reflecting on some of my decisions. Some of this reflection might be interesting to other developers. There are a few things on my mind, but I&#8217;ll &#8230; <a href="http://blog.carbonfive.com/2009/02/26/stripes-a-succesful-first-project/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re wrapping up a project that I&#8217;ve been leading since September and I&#8217;ve been reflecting on some of my decisions.  Some of this reflection might be interesting to other developers.  There are a few things on my mind, but I&#8217;ll start off off with my decision to use <a href="http://stripesframework.org">Stripes</a> as our MVC instead of our usual, Spring MVC.</p>
<h3>Background</h3>
<p>I&#8217;ve never been completely satisfied with Spring MVC (note that it&#8217;s pretty hard to win me over completely).  We know it well and we&#8217;ve had many successful projects while using it.  We&#8217;ve also used many of the new features that came along with Spring 2.5 (@Controller, more convention over configuration, etc), but in the end I still wasn&#8217;t loving it.</p>
<p>I came across Stripes over a year ago, and noted that it had a small but fairly vibrant and excited community.  The projects goals definitely resonated with me:</p>
<ul>
<li>Make developing web applications in Java easy</li>
<li>Provide simple yet powerful solutions to common problems</li>
<li>Make the Stripes ramp up time for a new developer less than 30 minutes</li>
<li>Make it really easy to extend Stripes, without making you configure every last thing</li>
</ul>
<p>So I decided to give it a try on a real project.  Switching from something we know inside and out to something that none of us had production experience with was arguably risky, so we decided to give it a try for a week with the intention that we&#8217;d go back to Spring MVC if anything took too long or felt awkward.  Thankfully, that never happened.</p>
<p>Some of this article may read a bit like a Stripes versus Spring MVC comparison.  That&#8217;s not really my  intention, but it&#8217;s somewhat inevitable as much of my experience has been with Spring MVC.  This isn&#8217;t intended to be a Stripes tutorial (there are great ones out there), so the code snippets and technical details will be sparse.</p>
<h3>Controller Lifecycle, Binding, and the Model</h3>
<p>Stripes controllers are called &#8220;Actions&#8221; or &#8220;ActionBeans&#8221; and each incoming HTTP request is routed to one primary Action (like Spring MVC).  Stripes creates a new Action instance for each incoming request; Spring Controllers are singletons in comparison.  Stripes binds parameters into the fields on the Action where Spring MVC passes them as method parameters.  The Stripes Action is not only the &#8220;Controller&#8221; in the MVC, but it also serves as the root of the &#8220;Model&#8221; as well.  The Action is made available to the View and all properties with getters can be queried using JSP-EL.  Spring&#8217;s model is separate, necessitated by the Singleton nature of the Controller.</p>
<p>Let&#8217;s look at a simple example:</p>
<pre class="brush: java; light: true; title: ; wrap-lines: false; notranslate">
// URI and embedded parameters defined using CleanURLs
@UrlBinding(&amp;quot;/status/{orderId}/{$event}&amp;quot;)
public class OrderStatusAction extends AbstractActionBean
{
    // Spring managed service to be dependency injected (see &amp;quot;Worth Mentioning&amp;quot; below)
    @Autowired OrderService orderService;

    // Required incoming parameter bound in the URI with {orderId}
    @Validate(required = true, minvalue = 1) long orderId;

    // OrderStatus to be accessible from the view for rendering
    OrderStatus orderStatus;

    // public setter tells stripes to allow binding
    public void setOrderId(long orderId) { this.orderId = orderId; }

    // public getter tell stripes to allow access from the view
    public OrderStatus getOrderStatus() { return orderStatus; }

    public Resolution view()
    {
        orderStatus = orderService.getOrderStatus(orderId);
        if (orderStatus == null) return new ErrorResolution(404);
        return new ForwardResolution(&amp;quot;/WEB-INF/jsp/order-status.jsp&amp;quot;);
    }
}
</pre>
<p>In our view we can access the Action / Model:</p>
<pre class="brush: xml; light: true; title: ; wrap-lines: false; notranslate">
...
&amp;lt;jsp:useBean id=&amp;quot;actionBean&amp;quot; scope=&amp;quot;request&amp;quot; type=&amp;quot;eg.OrderStatusBean&amp;quot;/&amp;gt;
...
&amp;lt;li&amp;gt;Order Number: ${actionBean.orderStatus.order.id}&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Status: ${actionBean.orderStatus.status}&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Tracking Number: ${actionBean.orderStatus.trackingNumber}&amp;lt;/li&amp;gt;
...
</pre>
<p>This example binds to a long, which is pretty simple.  Stripes can bind into graphs of objects, instantiating them along the way if necessary.  Collections are fully supported as well.  We haven&#8217;t yet found an example of something we couldn&#8217;t bind into right out of the box.</p>
<p>While I first was resistant to the Stripes lifecycle and combination of Controller and Model, I soon warmed up to it and now I find it quite natural, a bit better from a code readability standpoint, and more aesthetic.  It&#8217;s just the right amount of abstraction and encapsulation to make for speedy development while being easy to maintain.  I really like the fact that new instances of actions are created for each request, because the alternative is to pass all of your state into a handler method, which can easily lead hard-to-read code, especially with the annotations required to describe which request parameter maps to which method parameter.</p>
<p>If you can&#8217;t bind directly into your value objects and entities, the Action gives you a great place to bind into first, allowing you to manually instantiate your domain objects plugging in values from the Action.  This is quite useful when your domain model isn&#8217;t direct-binding friendly because of invariant enforcing, immutable value objects, and other practices encouraged by <a href="http://domaindrivendesign.org/">Domain Driven Design</a>.</p>
<p>We keep our Actions simple and lightweight, deferring all non-display logic to transactional, spring-managed services.  I&#8217;ve seen examples where Actions are directly interacting with the database, a pattern I discourage.</p>
<p>If you want to know more about how Stripes works, check out the references section at the end of this article.</p>
<h3>Generating URIs in Views</h3>
<p>I can&#8217;t tell you how many times I&#8217;ve run into regressions after making changes to URIs where a page would link to a controller at the wrong URI.  With Stripes, your URIs are defined once and only once, so when you change where an Action lives, pages will link to it correctly at its new location.  Stripes tags take a <code>beanclass</code> argument so that it can determine the correct URI at runtime rather than hard-coding it in the view.</p>
<pre class="brush: xml; light: true; title: ; wrap-lines: false; notranslate">
&amp;lt;stripes:link beanclass=&amp;quot;eg.OrderStatusAction&amp;quot; event=&amp;quot;view&amp;quot;&amp;gt;
  &amp;lt;stripes:param name=&amp;quot;orderId&amp;quot; value=&amp;quot;65432&amp;quot;/&amp;gt;
  View Order Status
&amp;lt;/stripes:link&amp;gt;
</pre>
<p>Renders: &lt;a href=&quot;http://example.com/status/65432/view&quot;&gt;View Order Status&lt;/a&gt;</p>
<p>The &lt;stripes:url &#8230;/&gt; and &lt;stripes:form &#8230;/&gt; tags work the same way.  To round it out, Actions can forward or redirect to other Actions without embedding URIs:</p>
<pre class="brush: java; light: true; title: ; wrap-lines: false; notranslate">
return new ForwardResolution(OrderHistoryAction.class, &amp;quot;view&amp;quot;).
return new RedirectResolution(OrderHistoryAction.class, &amp;quot;view&amp;quot;).
</pre>
<p>The net result is that there&#8217;s a single definition of each URI in our system and it lives on the Action which handles that URI, realizing the <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">Don&#8217;t Repeat Yourself (DRY)</a> principle.  We&#8217;ve been able able to change our URIs easily without fear of breaking views, which has been helpful as the project grows.</p>
<h3>Configuration</h3>
<p>Stripes only needs a few lines of configuration in your web.xml.  That&#8217;s it (really).  Stripes was built with convention over configuration in mind from day one.  Actions and Extensions (Converters, Formatters, Interceptors, etc) are auto-discovered via classpath scanning.  We never found ourselves needing to configure something differently than how it was out of the box.</p>
<p>While you can configure Spring MVC to be convention based (it&#8217;s okay to chuckle at this too), it&#8217;s not that way out of the box.  Perhaps Spring 3.0 will change this, but I have the sense that no matter what, there will always be some evidence of the fact that Spring MVC&#8217;s internals allow a wide range of configuration.</p>
<h3>Converters and Formatters</h3>
<p>In other frameworks, these concepts are often conflated into a single class.  Stripes converters do one thing: convert from strings to objects (e.g. phone numbers, zip codes, etc).  Whenever you need to turn an incoming request parameters into something more than a string, the converter is there to help.</p>
<p>Formatters work the other way, formatting objects into something that looks right on the screen as text.  Formatters can support multiple format types, so that you can support displaying objects differently when necessary (e.g. phone with extension, zip code with a plus 4, etc).</p>
<p>These helpers are simple to write and test.  All of the stripes tags will use them if they&#8217;re present, so it&#8217;s easy to affect how something &#8212; phone numbers for example &#8212; are displayed across the entire application.</p>
<h3>Testing</h3>
<p>There&#8217;s no reference to the servlet API in your Action classes, so it&#8217;s easy to write tests against the Java code within.  Tests fall into two categories: very lightweight unit tests which only test what&#8217;s happening in your handler and slightly more heavy-weight tests which involve more of the stack (but not the servlet container).</p>
<p>The outline for a unit test goes something like this:</p>
<ol>
<li>Instantiate your Action</li>
<li>Inject service stubs/mocks</li>
<li>Use the public setters to specify values to necessary fields</li>
<li>Invoke the handler</li>
<li>Assert on the Resolution and the state of the Action (optionally your Stub)</li>
</ol>
<p>Note that all of our Action tests fall into this category, even though you can test more of the stack (URL binding and validation).</p>
<p>What you can&#8217;t do &#8212; I haven&#8217;t seen any Java MVC provide this though &#8212; is write tests against the rendered markup of your views (a la Rails) without bringing up the servlet container.</p>
<p>Read more about <a href="http://stripesframework.org/display/stripes/Unit+Testing">testing with Stripes here</a>.</p>
<h3>Documentation and Community</h3>
<p>The Stripes documentation is definitely not very complete or polished.  Some of the documentation is out of date or non-existent (e.g. CleanURLs).  The same goes for the examples.  There is a decent book from Pragmatic Programmers press however, which I recommend if you&#8217;re interested in Stripes.</p>
<p>The good news is that despite all of this, it&#8217;s easy enough to find or figure out what you need without too much fuss.  Piecing together examples, tutorials, bogs, documentation, etc ultimately gives you what you need.  The <a href="http://stripes.svn.sourceforge.net/viewvc/stripes/">Stripes source</a> is small enough that you can rummage through to see how things work easily.  It&#8217;s not as configurable as Spring MVC so the code is less abstract and a little easier to grok (though it&#8217;s not as elegant).</p>
<p>There is an active mailing list where the developers and other users help out with questions.</p>
<h3>Conclusion</h3>
<p>I think working with Stripes is a lot of fun and that we made the right decision to use it.  I&#8217;d go as far as saying that we were at least as productive with it as we would have been with Spring MVC, and it&#8217;s likely we were more productive.  I&#8217;d say that the authors have largely delivered on their goals.  One of our front-end developers quickly dove right into building Actions without much help from other developers.  While we had the occasional &#8220;Huh?!&#8221; moment while trying to figure out why something wasn&#8217;t working, they were few and far between.</p>
<p>In comparing it to Spring MVC, I think there&#8217;s a simplicity and elegance to Stripes that comes from it being just an MVC and it not having the same legacy as Spring.  While Spring MVC has certainly evolved, it&#8217;s brought some of its crufty parts along with it.  I&#8217;ll be keeping an eye on Spring MVC to see what&#8217;s in store with 3.0, and I hope to be proven wrong.</p>
<p>There&#8217;s no doubt that Stripes is in a niche as compared to many of the other web frameworks.  The community is much smaller, and the development cycle much longer (last release was August 2008 and the one before that May 2007), which sometimes makes me wonder what Stripes future holds.</p>
<p>I&#8217;d say that one downside to Stripes, or any other framework that has a single backing Action per URI, is that there isn&#8217;t a great story for dealing with pages that aggregate a number of features and those features also show up on other pages.  The problem is that we can&#8217;t rely on the Action to provide all of the reference data, so we have to rely on other mechanisms for fetching it (filters, interceptors, tags, etc).  It&#8217;s not an issue with Stripes specifically, but all framework with the same approach.</p>
<p>For projects where this single primary controller per URI limitation isn&#8217;t a problem, I would definitely use Stripes again and I think it&#8217;s a framework Java developers should look into if they aren&#8217;t completely happy with whatever they&#8217;re using.</p>
<h3>Also Worth Mentioning&#8230;</h3>
<p>There are lots of other neat features in Stripes too: validation annotations and helper methods, <a href="http://stripesframework.org/display/stripes/Layout+Reuse">stripes layout</a>, <a href="http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/controller/FlashScope.html">flash scope</a>, wizard forms, encrypted parameters, a <a href="http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/ajax/JavaScriptResolution.html">JavaScriptResolution</a> for serializing Java objects to JavaScript, etc.  Open up the Stripes jar and start looking around.</p>
<p>Our application is using Spring as an IoC container for everything behind our Actions; to get handles to your Spring managed services we use a <a href="http://blog.carbonfive.com/2008/03/java/injecting-spring-25-beans-into-stripes-actions">simple Stripes Interceptor which injects dependencies into Actions</a>.</p>
<p>When using CleanURLs, you&#8217;ll want to use the <a href="http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/controller/DynamicMappingFilter.html">DynamicMappingFilter</a>, though there&#8217;s not much mention of it in the documentation.  CleanURLs in Stripes 1.5.1 should be even more flexible (see <a href="http://www.stripesframework.org/jira/browse/STS-617">STS-617</a>).</p>
<p>We used Spring Security on our application found that Stripes and Spring Security play nicely together.</p>
<p>Spring 3.0 will include a few new features that are similar to features I really like in Stripes, including RESTy URLs, and tags for generating the URIs to controllers.  The downside is that it&#8217;s still using the singleton model, which equates to controller handler methods with potentially lots of annotated parameters.</p>
<h3>References</h3>
<ul>
<li><a href="http://stripesframework.org">Stripes Homepage</a></li>
<li><a href="http://www.amazon.com/Stripes-development-Pragmatic-Programmers/dp/1934356212">Stripes by Federick Daoud</a></li>
<li><a href="http://stripesframework.org/display/stripes/2008/08/18/Stripes+1.5+Release+Available">Summary of Stripes 1.5 New Features</a></li>
<li><a href="http://greggbolinger.blogspot.com/2008/01/stripes-15-feature-clean-urls.html">CleanURLs Features</a></li>
<li><a href="http://www.devx.com/Java/Article/39199">Stripes in Black and White</a></li>
<li><a href="http://www.gridshore.nl/2008/12/13/using-stripes-as-a-webmvc-framework-without-that-thing-called-xml/">Using Stripes as a webmvc framework without that thing called xml</a></li>
<li><a href="http://plugins.intellij.net/plugin/?id=1528">IntelliStripes &#8211; IntelliJ IDEA Plugin</a></li>
<li><a href="http://github.com/knifhen/javarebel-stripes-plugin/tree/master">Stripes JavaRebel Plugin</a></li>
<li><a href="http://blog.springsource.com/2008/12/05/spring-framework-30-m1-released/">Spring 3.0 M1 Features</a> and <a href="http://blog.springsource.com/2009/02/25/spring-framework-30-m2-released/">Spring 3.0 M2 Features</a></li>
<li><a href="http://blog.springsource.com/2009/03/08/rest-in-spring-3-mvc/">Spring 3.0 MVC Features</a></li>
</ul>
<p>Updates: added reference to recently published Spring 3.0 MVC blog.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2009/02/26/stripes-a-succesful-first-project/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

