The Source for Java Technology Collaboration
User: Password:



Simon Brown's Blog

January 2006 Archives


Comparing webapp frameworks : Struts

Posted by simongbrown on January 26, 2006 at 09:48 AM | Permalink | Comments (4)

Struts is the grandaddy of Java webapp frameworks so it's fitting that we start our tour here. I think it's probably safe to say that Struts was the first model 2 (web MVC) framework to gain widespread adoption in the Java arena and to this day it's still used by many people.

Just to ensure everybody is up to speed, model 2/web MVC is an architectural pattern that promotes separation of concerns between the model, the view and the controller in a web environment. As we saw in the previous model 1 implementations of the sample application, each of the JSP pages contains Java code to lookup data and display it to the user. With an MVC approach, each of the components has a strict responsibility as follows.

  • Model : represents the data being viewed/manipulated.
  • View : responsible for rendering the model back to the user.
  • Controller : responsible for taking the request/user input and initialising the model, manipulating it, etc.

In reality, different people have different views as to whether the controller represents only the web specific parts of the process flow and whether real business logic in fact resides in the model (it being a model of the underlying business). What's important here is that web MVC promotes a separation of concerns through reusable and testable components, regardless of how you cut it. For more information about the model 2 architecture, take a look at Designing Web Applications and Servlet Patterns.

Home page
So what's different between the Struts version of the example application and the original model 1 version? Remember that Java code at the top of the page? Basically, that's been moved into a Java class.

package action;

import domain.Blog;
import domain.BlogService;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ViewBlogEntriesAction extends Action {

  public ActionForward execute(ActionMapping mapping, ActionForm form,
    HttpServletRequest request, HttpServletResponse response) throws Exception {

    BlogService blogService = new BlogService();
    Blog blog = blogService.getBlog();
    request.setAttribute("blog", blog);

    return mapping.findForward("success");
  }
}

In Struts terminology, this class is called an action although you'll also see this general pattern referred to as the command pattern. At runtime, the Struts controller (a Java servlet) maps the incoming request onto an action class and calls the execute() method, which contains the (business) logic required to service the request. In the example, this logic is responsible for locating the Blog instance and making it available (via the request) so that the recent list of blog entries can be presented back to the user. As with all of the others, this example uses JSP as the view technology, although you'll notice from the code above that we don't explicitly say, "please now show JSP page X". We'll cover this shortly but for now, here's the JSP page itself.

<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

  <head>
    <title><bean:write name="blog" property="name" /></title>
    <link rel="stylesheet" href="screen.css" type="text/css" />
  </head>

  <body>
    <div id="container">
      <h1><bean:write name="blog" property="name" /></h1>
      <h2><bean:write name="blog" property="description" /></h2>

      <logic:iterate id="blogEntry" name="blog" property="blogEntries" >
        <div class="blogEntry">
          <h3><bean:write name="blogEntry" property="title" /></h3>
        </div>

        <logic:notEmpty name="blogEntry" property="excerpt">
          <bean:write name="blogEntry" property="excerpt" filter="false" />
          <p>
          <html:link action="viewBlogEntry" paramId="id" paramName="blogEntry" paramProperty="id">Read more</html:link>
          </p>
        </logic:notEmpty>

        <logic:empty name="blogEntry" property="excerpt">
          <bean:write name="blogEntry" property="body" filter="false" />
        </logic:empty>

        <p>
        Posted on <bean:write name="blogEntry" property="date" format="dd MMM yyyy HH:mm:ss" />
        </p>
      </logic:iterate>
    </div>
  </body>

</html>

As you can see, moving the Java code out of the page makes for a shorter JSP that looks just like regular XHTML, albeit with a few custom tags here and there. On that note, I've chosen to use Struts tags in this version of the page purely to show something a little different to last time, but you have other alternatives including the (more feature rich) JSTL tags.

So how does a request for the home page make its way through to the ViewBlogEntriesAction class? Well, the main index.jsp page contains a simple JSP forward to /viewBlogEntries.do, which is subsequently mapped to the ViewBlogEntriesAction Java class. With Struts, there are two parts to this. First of all, the mapping between *.do and the Struts front controller servlet is defined in the web.xml file, as follows.

  <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>
        org.apache.struts.action.ActionServlet
    </servlet-class>
    <init-param>
        <param-name>config</param-name>
        <param-value>
         /WEB-INF/struts-config.xml
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

Next, the mapping between a URL and the Java class responsible for processing that request is specified in a file called struts-config.xml that typically resides in /WEB-INF (but is configurable, as you see above). Here's the relevant part of the file that illustrates these mappings (path -> type) for the sample application.

    <action-mappings>

      <action path="/viewBlogEntries" type="action.ViewBlogEntriesAction" name="viewBlogEntries">
        <forward name="success" path="/viewBlogEntries.jsp" />
      </action>

      <action path="/viewBlogEntry" type="action.ViewBlogEntryAction" name="viewBlogEntry">
        <forward name="success" path="/viewBlogEntry.jsp" />
        <forward name="notfound" path="/404.jsp" />
      </action>

    </action-mappings>

Within each of the action mappings, you'll also notice one or forward elements and these are essentially an abstraction over the JSP that will be responsible for rendering the response. It's probably worth noting that this is just a URI, so you don't have to reference a JSP page here. If you look back to the ViewBlogEntriesAction class above, you'll see that the last line in the execute method performs mapping.findForward("success"). This says, please find the mapping called success that's defined for this action mapping and forward control to it. In this case, the viewBlogEntries.jsp page is used. This completes the picture and is the basic way that most requests in Struts are handled.

Blog entry detail page
Likewise, for the blog entry page we have an action class and a JSP page. Here's the action.

package action;

import domain.Blog;
import domain.BlogEntry;
import domain.BlogService;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ViewBlogEntryAction extends Action {

  public ActionForward execute(ActionMapping mapping, ActionForm form,
    HttpServletRequest request, HttpServletResponse response) throws Exception {

    BlogService blogService = new BlogService();
    Blog blog = blogService.getBlog();
    request.setAttribute("blog", blog);

    BlogEntry blogEntry = blog.getBlogEntry(request.getParameter("id"));
    if (blogEntry == null) {
      return mapping.findForward("notfound");
    } else {
      request.setAttribute("blogEntry", blogEntry);
      return mapping.findForward("success");
    }
  }

}

No big surprises here except that there are two possible routes through the action depending on whether the specified blog entry is found or not. And here's the JSP page used to render the successful response.

<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

  <head>
    <title><bean:write name="blogEntry" property="title" /> : <bean:write name="blog" property="name" /></title>
    <link rel="stylesheet" href="screen.css" type="text/css" />
  </head>

  <body>
    <div id="container">
      <h1><bean:write name="blog" property="name" /></h1>
      <h2><bean:write name="blog" property="description" /></h2>

      <div class="blogEntry">
        <h3><bean:write name="blogEntry" property="title" /></h3>

        <bean:write name="blogEntry" property="body" filter="false" />

        <p>
        Posted on <bean:write name="blogEntry" property="date" format="dd MMM yyyy HH:mm:ss" />
        </p>
      </div>
    </div>
  </body>

</html>

Summary
Despite its age, Struts is still one of the mostly widely used web application frameworks and one of the top choices for teams building Java EE systems. Additionally, the overall implementation strategy (called the Command and controller strategy in Java EE pattern documentation) is probably the most pervasive in both bespoke build and, as we'll be seeing, other open source alternatives to Struts.



Comparing webapp frameworks : Model 1 with JSP XML

Posted by simongbrown on January 12, 2006 at 02:49 AM | Permalink | Comments (0)

For completeness, I wanted to show how the JSP pages from the JSTL version could be written using the JSP XML syntax. Unsurprisingly, many people don't even know of its existence and, as I've blogged before, there aren't that many situations where you'd want to use it to write pages by hand. Should you need to, here are a couple of examples of how you would go about it using the XML syntax.

Home page
Here's the home page once again, implemented using the JSTL and written in the JSP XML syntax.

<?xml version="1.0" encoding="UTF-8"?>
<jsp:root xmlns="http://www.w3.org/1999/xhtml"
   xmlns:jsp="http://java.sun.com/JSP/Page"
   xmlns:c="http://java.sun.com/jstl/core_rt"
   xmlns:fmt="http://java.sun.com/jstl/fmt_rt"
   version="2.0">

  <jsp:useBean id="blogService" scope="request" class="domain.BlogService"/>
  <c:set var="blog" value="${blogService.blog}" />

  <jsp:output doctype-root-element="html"
    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
    doctype-system="http://www.w3c.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
  <jsp:directive.page contentType="text/html;charset=UTF-8" />

  <html xmlns="http://www.w3.org/1999/xhtml">

    <head>
      <title>${blog.name}</title>
      <link rel="stylesheet" href="screen.css" type="text/css" />
    </head>

    <body>
      <div id="container">
        <h1>${blog.name}</h1>
        <h2>${blog.description}</h2>

        <c:forEach var="blogEntry" items="${blog.blogEntries}">
          <div class="blogEntry">
            <h3>${blogEntry.title}</h3>

            <c:choose>
              <c:when test="${not empty blogEntry.excerpt}">
                ${blogEntry.excerpt}
                <p>
                <a href="viewBlogEntry.jsp?id=${blogEntry.id}">Read more</a>
                </p>
              </c:when>
              <c:otherwise>
                ${blogEntry.body}
              </c:otherwise>
            </c:choose>

            <p>
            Posted on <fmt:formatDate value="${blogEntry.date}"
                        timeZone="${blog.timeZone}" type="both"
                        dateStyle="long" timeStyle="long" />
            </p>
          </div>
        </c:forEach>
      </div>
    </body>

  </html>

</jsp:root>

In comparison to the previous implementation, the major difference here is that the JSP page must be well formed XML, with everything wrapped up inside a <jsp:root> element. In addition, the taglib directives are replaced by a simple XML namespace, which is really quite neat.

Blog entry detail page
The blog entry detail page is fairly similar in all respects, with the Java code at the top of the page now being wrapped up inside a <jsp:scriptlet> element.

<?xml version="1.0" encoding="UTF-8"?>
<jsp:root xmlns="http://www.w3.org/1999/xhtml"
   xmlns:jsp="http://java.sun.com/JSP/Page"
   xmlns:c="http://java.sun.com/jstl/core_rt"
   xmlns:fmt="http://java.sun.com/jstl/fmt_rt"
   version="2.0">

  <jsp:output doctype-root-element="html"
    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
    doctype-system="http://www.w3c.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
  <jsp:directive.page contentType="text/html;charset=UTF-8" />
  <jsp:directive.page import="domain.*" />

  <jsp:scriptlet>
    BlogService blogService = new BlogService();
    Blog blog = blogService.getBlog();
    request.setAttribute("blog", blog);

    BlogEntry blogEntry = blog.getBlogEntry(request.getParameter("id"));
    if (blogEntry == null) {
      response.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    } else {
      request.setAttribute("blogEntry", blogEntry);
    }
  </jsp:scriptlet>

  <html xmlns="http://www.w3.org/1999/xhtml">

    <head>
      <title>${blogEntry.title} : ${blog.name}</title>
      <link rel="stylesheet" href="screen.css" type="text/css" />
    </head>

    <body>
      <div id="container">
        <h1>${blog.name}</h1>
        <h2>${blog.description}</h2>

        <div class="blogEntry">
          <h3>${blogEntry.title}</h3>

          ${blogEntry.body}

          <p>
          Posted on <fmt:formatDate value="${blogEntry.date}"
                      timeZone="${blog.timeZone}" type="both"
                      dateStyle="long" timeStyle="long" />
          </p>
        </div>
      </div>
    </body>

  </html>

</jsp:root>

Summary
All in all, there aren't massive changes between writing a page in the native JSP syntax and writing it in the XML syntax, but care does have to be taken to ensure that your JSP pages are valid XML and easily readable if using the latter. Personally, I've never seen the XML syntax in use on projects that I've been involved with but the choice, as they say, is yours.

Right, let's put model 1 behind us and start comparing some webapp frameworks. :-)



Comparing webapp frameworks : Model 1 with JSTL

Posted by simongbrown on January 10, 2006 at 09:05 AM | Permalink | Comments (2)

It's been a while since the last blog entry, but let's continue our look at the webapp frameworks with another model 1 implementation, this time using the JavaServer Pages Standard Tag Library (JSTL).

In Comparing webapp frameworks : Model 1 with scriptlets we saw that model 1 applications typically have some boilerplate code at the top of the page to "set the scene" and the use of scriptlets means short pieces of Java code scattered throughout the page to control the presentation logic. As an alternative to this, we could use the JSTL.

Home page
Here's the home page, implemented using the JSTL.

<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>

<jsp:useBean id="blogService" scope="request" class="domain.BlogService"/>
<c:set var="blog" value="${blogService.blog}" />

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

  <head>
    <title>${blog.name}</title>
    <link rel="stylesheet" href="screen.css" type="text/css" />
  </head>

  <body>
    <div id="container">
      <h1>${blog.name}</h1>
      <h2>${blog.description}</h2>

      <c:forEach var="blogEntry" items="${blog.blogEntries}">
        <div class="blogEntry">
          <h3>${blogEntry.title}</h3>

          <c:choose>
            <c:when test="${not empty blogEntry.excerpt}">
              ${blogEntry.excerpt}
              <p>
              <a href="viewBlogEntry.jsp?id=${blogEntry.id}">Read more</a>
              </p>
            </c:when>
            <c:otherwise>
              ${blogEntry.body}
            </c:otherwise>
          </c:choose>

          <p>
          Posted on <fmt:formatDate value="${blogEntry.date}"
                      timeZone="${blog.timeZone}" type="both"
                      dateStyle="long" timeStyle="long" />
          </p>
        </div>
      </c:forEach>
    </div>
  </body>

</html>

As you can see, the boilerplate code at the top of the page to locate the Blog instance has been replaced with a simple JSTL tag and access to all properties on blog is performed using the JSP expression language ${...} construct, which is very succinct. In addition, the code that handles the presentation logic of iteration, conditional output and formatting has also been replaced by some JSTL tags. Line for line, this version is shorter and more readable than the previous one.

Blog entry detail page
The blog entry detail page also benefits from using the JSTL, although the scriptlet at the top of the page to locate the required blog entry is actually longer than before in order to make the objects available to the JSTL tags.

<%@ page import="domain.*" %>
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>

<%
  BlogService blogService = new BlogService();
  Blog blog = blogService.getBlog();
  request.setAttribute("blog", blog);

  BlogEntry blogEntry = blog.getBlogEntry(request.getParameter("id"));
  if (blogEntry == null) {
    response.sendError(HttpServletResponse.SC_NOT_FOUND);
    return;
  } else {
    request.setAttribute("blogEntry", blogEntry);
  }
%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

  <head>
    <title>${blogEntry.title} : ${blog.name}</title>
    <link rel="stylesheet" href="screen.css" type="text/css" />
  </head>

  <body>
    <div id="container">
      <h1>${blog.name}</h1>
      <h2>${blog.description}</h2>

      <div class="blogEntry">
        <h3>${blogEntry.title}</h3>

        ${blogEntry.body}

        <p>
        Posted on <fmt:formatDate value="${blogEntry.date}"
                    timeZone="${blog.timeZone}" type="both"
                    dateStyle="long" timeStyle="long" />
        </p>
      </div>
    </div>
  </body>

</html>

Summary
As this example shows, the JSTL can be used to considerably reduce the need for Java code but ultimately the overall design of a model 1 page is still the same. It's hard to get away from having a block of Java code at the top of the page where processing needs to happen before the page is rendered. A good example is the blog entry detail page that looks up a blog entry given a specific ID. Next time, we'll look at a slightly different way to write the pages.





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds