Section 2.5. Adding a Model and Controller


2.5. Adding a Model and Controller

Now we have a working skeleton. Let's add the model and controller to complete the MVC framework.

2.5.1. The Model

The model is a Plain Old Java Object (POJO). You've built classes like this a thousand times before. CarBean is nothing more than a class with three member variables and the associated accessors and mutators.

As you saw in the previous JSP example, using string arrays for data storage doesn't yield very expressive source code. We use an object-oriented programming language to build objects that have a deeper semantic meaning than a pile of primitive data types. In Example 2-9, you can see that CarBean is nothing more than a class with three member variables and the associated accessors and mutators. Car.make, Car.model, and Car.modelYear mean something to us, as opposed to the use of string [0], string [1], and string [2].

Example 2-9. CarBean.java
 package com.jbossatwork; public class CarBean {     private String make;     private String model;     private String modelYear;     public CarBean(String make, String model, String modelYear)     {         this.make = make;         this.model = model;         this.modelYear = modelYear;     }     public String getMake( )     {         return make;     }     public void setMake(String make)     {         this.make = make;     }     public String getModel( )     {         return model;     }     public void setModel(String model)     {         this.model = model;     }     public String getModelYear( )     {         return modelYear;     }     public void setModelYear(String modelYear)     {         this.modelYear = modelYear;     } }

Now that we have a model, let's change our JSP to iterate through an ArrayList of CarBeans instead of a simple string array (Example 2-10). The number of lines of code hasn't really changed, but hopefully the source code is far more readable using the JavaBean. (And yes, that pesky scriptlet code is still around. Once we get our Controller in place, we'll be able to replace it with something a bit more production-worthy.)

Example 2-10. carList.jsp
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page import="java.util.ArrayList,                 com.jbossatwork.CarBean"%> <%     // DON'T FREAK OUT!!! This scriptlet code will go away once     // we have a controller in place...     ArrayList carList = new ArrayList( );     carList.add(new CarBean("Toyota", "Camry", "2005"));     carList.add(new CarBean("Toyota", "Corolla", "1999"));     carList.add(new CarBean("Ford", "Explorer", "2005"));     pageContext.setAttribute("carList", carList); %> <html> <head>   <link rel="stylesheet" type="text/css" href="default.css"> </head> <body>   <table>     <tr>       <th>Make</th>       <th>Model</th>       <th >Model Year</th>     </tr>     <c:forEach items='${carList}' var='car'>       <tr>       <td>${car.make}</td>       <td>${car.model}</td>       <td >${car.modelYear}</td>       </tr>     </c:forEach>   </table> </body> </html>

Notice that our EL has changed to reference the individual attributes of the JavaBean instead of using array notation. EL automatically calls the getters and setters behind the scenes. We are left with code that is almost plain English"put the car make here, the car model there."

2.5.2. The Controller

Now the question is how will the JSP get its hands on the populated ArrayList? If you call the JSP directly (as we do in index.jsp: <a href="carList.jsp">), there's really no way to do the required setup for the view. Oh sureJSTL tags allow you to make SQL calls directly from your JSPs, but that doesn't sound "highly cohesive," now, does it?

Enter the controller. If our link sends us to the controller instead of directly to the JSP, the controller can get the cars from the database, put them in memory, and redirect us to the JSP. Our new link looks like this: <a href="controller?action=viewCarList">. This link calls the controller in Example 2-11, asking it to perform the viewCarList action.

Example 2-11. ControllerServlet.java
 package com.jbossatwork; import java.io.IOException; import java.util.List; import java.util.ArrayList; import javax.servlet.*; import javax.servlet.http.*; public class ControllerServlet extends HttpServlet {     private static final String ACTION_KEY = "action";     private static final String VIEW_CAR_LIST_ACTION = "viewCarList";     private static final String ERROR_KEY = "errorMessage";     private static final String ERROR_PAGE="/error.jsp";     public void doGet(HttpServletRequest request, HttpServletResponse response)             throws IOException, ServletException {         processRequest(request, response);     }     public void doPost(HttpServletRequest request, HttpServletResponse response)             throws IOException, ServletException {         processRequest(request, response);     }     protected void processRequest(                    HttpServletRequest request, HttpServletResponse response)             throws ServletException, IOException {         String actionName = request.getParameter(ACTION_KEY);         String destinationPage = ERROR_PAGE;         // perform action         if(VIEW_CAR_LIST_ACTION.equals(actionName))         {             List carList = new ArrayList( );             carList.add(new CarBean("Toyota", "Camry", "2005"));             carList.add(new CarBean("Toyota", "Corolla", "1999"));             carList.add(new CarBean("Ford", "Explorer", "2005"));             request.setAttribute("carList", carList);             destinationPage = "/carList.jsp";         }         else         {             String errorMessage = "[" + actionName + "] is not a valid action.";             request.setAttribute(ERROR_KEY, errorMessage);         }         // Redirect to destination page.         RequestDispatcher dispatcher =                getServletContext( ).getRequestDispatcher(destinationPage);         dispatcher.forward(request, response);     } }

The controller gets the action parameter off of the request stack and branches to the appropriate code block. (For now, we have only one action in place: VIEW_CAR_LIST_ACTION.) The controller creates the CarBeans, sticks them in an ArrayList named carList, and puts the list into Request scope. At the end of the processRequest( ) method it redirects us to the appropriate JSP.

Now that the controller handles the data setup, we can finally remove the scriptlet code from our JSP to get Example 2-12. It's looking pretty lean and mean at this point. (Go back and look at the original HTML-only example we started with to gauge just how far we've come.)

Example 2-12. carList.jsp (Final Version)
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head>   <link rel="stylesheet" type="text/css" href="default.css"> </head> <body>   <table>     <tr>       <th>Make</th>       <th>Model</th>       <th >Model Year</th>     </tr>     <c:forEach items='${carList}' var='car'>       <tr>       <td>${car.make}</td>       <td>${car.model}</td>       <td >${car.modelYear}</td>       </tr>     </c:forEach>   </table> </body> </html>

Notice that the JSTL for loop finds the carList object automatically in the Request scope. We don't have to tell it where to go looking for it.

The last thing we need to do is add the servlet to web.xml. In the coming chapters we'll use XDoclet to dynamically generate this file on the fly. For now, we'll just hand-edit the file in Example 2-13.

Example 2-13. web.xml
 <?xml version="1.0" encoding="ISO-8859-1"?> <web-app version="2.4"     xmlns="http://java.sun.com/xml/ns/j2ee"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-app_2_4.xsd">     <!-- servlet definition -->     <servlet>         <servlet-name>Controller</servlet-name>         <servlet-class>com.jbossatwork.ControllerServlet</servlet-class>     </servlet>     <!-- servlet mapping -->     <servlet-mapping>         <servlet-name>Controller</servlet-name>         <url-pattern>/controller/*</url-pattern>     </servlet-mapping>     <!-- The Welcome File List -->     <welcome-file-list>         <welcome-file>index.jsp</welcome-file>     </welcome-file-list> </web-app>

The <servlet> section allows us to create an alias for the class. This alias makes it easier to refactor later on. It shields us from class and package name changes, but also means that we can swap entirely different servlet classes in and out for testing purposes, with nothing but a single line change in web.xml.

The <servlet-mapping> section exposes hidden WEB-INF resources to the public. The <url-pattern> allows you to set up any name you'd like. We remapped com.jbossatwork.ControllerServlet to simply controller.

With all of this in place, we're ready to build and deploy again. Change to the ch02-mvc directory and type ant. Copy the new jaw.war to the deploy directory. Visit http://localhost:8080/jaw to see it in action.



JBoss at Work. A Practical Guide
JBoss at Work: A Practical Guide
ISBN: 0596007345
EAN: 2147483647
Year: 2004
Pages: 197

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net