Who Needs Struts?
For smaller projects it's sometimes better to write code by hand rather than incur the overhead of a major framework.
by Lew Bloch

September 28, 2005

Model-View-Controller (MVC) identifies a design pattern that suits J2EE applications especially well, as the abundance of tutorials, white papers, and frameworks such as Apache Struts attest. The benefit is real, the hype notwithstanding, so we use Struts everywhere and the bluebirds of happiness sing sweetly, right? Well, maybe. Sometimes the framework is just a wee bit overmuch for a small application, or it otherwise obscures the underlying MVC-ness. Wouldn't it occasionally be simpler and more useful to avoid all that scaffolding? Let's look at how to use a template for MVC applications that uses just Java, JavaServer Pages (JSP), and a few simple HTML idioms to gain all the benefit of the MVC pattern with virtually no overhead except to use your brain.

The heart of the MVC application is the controller, which we'll implement as the Controller class. Its job is to link an action from the front end to some model logic on the back end, and then show some result through a view JSP. That JSP will accept user input and post it to the Controller as another action, and the cycle repeats. Unlike the frameworks, our implementation is minimal and does not use external resources to define its flow, although that would be a simple enhancement.

The Controller assumes that every JSP sends at least one parameter named action, which maps to a unique combination of a model object and a view. When Controller receives a POST, it uses action to look up a model-view pair, and then it hands off the HTTP request to an instantiation of the model and forwards control to the view. Simple.

Each model object is of a class that derives from the parent Logic class, so that the controller need not care about the specifics except in the initialization. The corresponding view JSP is usually cognizant of the specific subclass it needs. The simplified code is shown in Listing 1. (You can also download the code here.)

We leave out try-catch blocks and other necessary code for expository purposes, but it really is close to being this simple. The model-view pair associated with each action is expressed by the inner class MV:

private static class MV
{
  public final 
    Class <? extends Logic> clazz;
  public final String         view;
  public MV( 
    Class <? extends Logic> clazz, 
    String view )
  {
    this.clazz = clazz;
    this.view = view;
  }
  public static final MV DEFAULT 
    = new MV( Logic.class, "index.jsp" );
}

The rest is up to the subclasses of Logic and the JSPs, the model, and view, respectively. For example, Controller maps the action value "simple" to the model-view pair MV(SimpleLogic.class, "simple.jsp"). So when Controller invokes logic.setRequest(request), SimpleLogic takes care of it.

Interactive View
The view gives the user the prompts, inputs, and result displays by which they interact with the application logic. Look at a simple example that asks for just a name and a number, and has buttons to submit the data or to go home to the index page. The HTML hidden input named action tells Controller to map simple to the appropriate MV:

<form name="simpleform" method=
  "post" action="home" >
  <label for="name">Name:</label>
  <input type="text" maxlength="60" 
    id="name" name="name" 
    value="<%= nm %>" 
  />
  <label for="number">Number:
  </label>
  <input type="text" maxlength="24" 
    id="number" name="number" 
    value="<%= numb %>" 
  />
  <input type="hidden" id="action" 
    name="action" value="simple" 
  />
  <input type="submit" id="simple" 
    name="simple" value="Next" 
  />
</form>

The scriptlet values <%= nm %> and <%= numb %> are set from the request parameters. Another way to set the action is to name the submit button action:

<input type="submit" id="gosimple" 
  name="action" 
  value="Simple Example" 
/>

The Logic class and its subclasses implement the model. The base class takes the request and just makes sure that it isn't null. It also has an empty implementation of validate(), a method to support surface edits. The subclass SimpleLogic overrides validate() to check that the form provided a valid, non-negative number:

int nu = Integer.parseInt( numb );
if ( nu < 0 )
{
  msgs.add("\""+ numb +"\
    " is less than zero.");
  msgs.add(
    "Select a number at least 
    zero.");
}

The Logic object won't necessarily do anything with the data; it may perform lazy evaluation, deferring processing until the JSP asks for the result, or it may process the request immediately upon the setRequest() call. More complex scenarios would have Logic that, for example, connects to a database, initiates a commercial transaction, or otherwise performs useful work.

Sometimes for a smaller project its better to write a few things by hand rather than to incur the overhead of a major framework. With the simple techniques outlined here, the full power of the MVC pattern comes to bear without extra XML, third-party libraries, opaque servlets, or the other downsides to frameworks. Plus the programmer gets a much better grasp of the principles.

About the Author
Lew Bloch is a programmer who has been working on projects and contracts for over two decades. Currently Lew works on system integration through Web services. Contact Lew at .