Timesheet List Screen: A No-Form Controller Example


Developing a no-form controller in Spring is a relatively straightforward process. Let's look at the steps involved to do this.

Step-by-Step Configuration

The following are Spring-related items we need to configure in timex-servlet.xml, our Spring application context file.

Map Handler

The first thing we need to do is to map the incoming request URL to an actual controller, which will handle the request. The following excerpt from the timex-servlet.xml file shows how we can map the timesheetlist.htm URL to an internal bean reference named timesheetListController (discussed next) with the help of Spring's SimpleUrlHandlerMapping class:

<bean      >     <property name="interceptors">         <list>             <ref bean="httpRequestInterceptor" />         </list>     </property>     <property name="urlMap">         <props>             <prop key="/timesheetlist.htm">                 timesheetListController             </prop>


Also, notice the interceptors property; by configuring this, we can intercept HTTP requests, for example, to implement authentication (interceptors are discussed in detail later in this chapter).

Define Controller and Associated Class

The next step is to define the controller class referenced by the map handler. The following excerpt from the timex-servlet.xml file demonstrates how this is done:

<bean name="timesheetListController"     >     <property name="timesheetManager">         <ref bean="timesheetManager" />     </property>     <property name="applicationSecurityManager">         <ref bean="applicationSecurityManager" />     </property>     <property name="successView">         <value>timesheetlist</value>     </property> </bean>


Notice the ref attributes. As you might guess, these are references to other beans defined in our application context, as shown in this XML excerpt:

<bean      /> <bean       />


We already developed the TimesheetManager class in Chapter 5; we will develop the ApplicationSecurityManager class later in this chapter.

This is all we need to configure for the Timesheet List screen. Now we need to write the controller and view code, referenced here. Let's look at that next.

Step-by-Step Coding

The Timesheet List screen is a relatively simple screen and will be developed using the most basic type of Spring controller because it contains no form fields; therefore, it will not require things such as Command and Validator classes. Basically, if we look at this from an MVC design pattern perspective, the files for this screen will include the following:

  • Model TimesheetManager.java and Timesheet.java

  • View timesheetlist.jsp

  • Controller TimesheetController.java

We already developed the model files in the previous chapter, so all we need to develop here are the controller and view files. Let's dissect and review parts of our complete code.

Let's begin by writing the unit test code for our controller class.

Writing Our Test First with Mock Objects

The next few code excerpts from our TimesheetListControllerTest.java file show how we can unit test controller classes. We will create this in the timex/src/java/com/visualpatterns/timex/controller directory.

We start by creating an instance of the org.springframework.mock.web. MockHttpServletRequest class to simulate a real HTTP request. This class not only provides the benefit of being able to unit test our code but also reduces the need to deploy the application and potentially restart the servlet container (Tomcat, for example) each time we want to test something.

mockHttpServletRequest = new MockHttpServletRequest("GET", "/timesheetlist.htm");


Next, we will create some test dependency objects and inject them, as Spring will do for us at runtime:

Employee employee = new Employee(); employee.setEmployeeId(EMPLOYEE_ID); applicationSecurityManager.setEmployee(mockHttpServletRequest,         employee); // inject objects that Spring normally would timesheetListController = new TimesheetListController(); timesheetListController.setTimesheetManager(timesheetManager); timesheetListController         .setApplicationSecurityManager(applicationSecurityManager);


In our test code, we instantiated our own TimesheetManager class for the sake of simplicity. However in real-world applications, you might want to use Spring's FileSystemXmlApplicationContext or ClassPathXmlApplicationContext classes to instantiate your classes. This way, you not only get an instance of a class but also have its dependent objects loaded and injected by Spring.

Now we can complete our test by checking the java.util.List we just retrieved; our test ensures that list is not empty and also that it contains Timesheet objects for the employee we requested the records for:

ModelAndView modelAndView = timesheetListController.handleRequest(         mockHttpServletRequest, null); assertNotNull(modelAndView); assertNotNull(modelAndView.getModel()); List timesheets = (List) modelAndView.getModel().get(         TimesheetListController.MAP_KEY); assertNotNull(timesheets); Timesheet timesheet; for (int i = 0; i < timesheets.size(); i++) {      timesheet = (Timesheet) timesheets.get(i);      assertEquals(EMPLOYEE_ID, timesheet.getEmployeeId());      System.out.println(timesheet.getTimesheetId() + " passed!"); }


That's about it for our unit test class; now let's review the actual TimesheetListController class.

Writing Unit Test and Actual Code in the Same Sitting

This book's code zip file shows the complete code for our TimesheetListControllerTest.java class, which is the JUnit test case for TimesheetController.java. As I've preached previously in this book, development of a unit test and the actual code works best when it is done in the same sitting. For example, I wrote the TimesheetListControllerTest.java and TimesheetListController.java in the same sitting; that is, I coded a little, compiled and tested a little, and then repeated these steps until my controller class provided all the functionality I needed. The obvious benefit of this approach was that my code was unit tested by the time I was done!

Furthermore, our controller class will now contain only the code we neednothing more, nothing less.

Another notable benefit worth mentioning is that at times I find myself getting programmer's block (similar to writer's block). But starting out with the unit test code helps me get going. Note that what I have mentioned here is a personal style of working, but hopefully you will find value in it and give the test-first approach a try (if you don't already do so).

One thing I do want to stress is that like everything else, you need to find the right balance. Although I believe in the test-first approach, there are times when it isn't feasible for me to write a unit test code that becomes more complicated than the actual code or is cumbersome to write. After all, you are writing Java code to test other Java code, which raises an obvious questiondo we also test the test code? Of course, I'm kidding here, but my point is to find the right balance and in most cases, unit tests work out pretty well.

Last, unit testing works best if you write small methods that can be unit tested relatively easily.


Controller Code

Now it is time to review the code behind our controller class for the Timesheet List screen, TimesheetListController.java. We will create this in the timex/src/java/com/visualpatterns/timex/controller directory.

For starters, notice that we are implementing the org.springframework.web.servlet.mvc.Controller interface; this is perhaps the most basic type of controller you can develop using Spring.

public class TimesheetListController implements Controller


The next interesting thing to note is the handleRequest method; this is the only method we must implement to satisfy the requirements of the Controller interface.

public ModelAndView handleRequest(HttpServletRequest request,                                   HttpServletResponse response)


The handleRequest method returns a ModelAndView object, which contains the view name and the model data (a java.util.List, in our case). The view name is resolved by JstlView, which we defined in the timex-servlet.xml file we saw earlier in this chapter.

return new ModelAndView(VIEW_NAME,                         MAP_KEY,                         timesheetManager.getTimesheets(employeeId));


There are a few more variations to how you can construct the ModelAndView class, as shown in the following list (see the Spring Framework API Javadocs for details):

  • ModelAndView()

  • ModelAndView(String viewName)

  • ModelAndView(String viewName, Map model)

  • ModelAndView(String viewName, String modelName, Object modelObject)

  • ModelAndView(View view)

  • ModelAndView(View view, Map model)

  • ModelAndView(View view, String modelName, Object modelObject)

View/JSP Code

We already prototyped the screens in Chapter 2, "The Sample Application: An Online Timesheet System," so we now need to add some code to the related view (.jsp) files. This book's code zip file contains the before file, timesheetlist.html (prototyped, static HTML), and the after file, timesheetlist.jsp (dynamic/JSP), versions of this file.

Let's review our timesheetlist.jsp a bit closer. For starters, we will create this in the timex/src/java/com/visualpatterns/timex/view directory. Now let's look at some JSP code.

The following excerpt from our timesheetlist.jsp file shows the dynamic code used for populating the HTML table on the Timesheet List screen; this is done in a loop using JSTLs forEach tag. Within each loop, we are generating the HTML table's rows and columns (and also formatting the hours) using the JSTL core library.

<c:forEach items="${timesheets}" var="timesheet">     <tr>         <td align="center"><a             href='enterhours.htm?eid=<c:out             value="${timesheet.employeeId}"/>&amp;tid=<c:out             value="${timesheet.timesheetId}"/>'><fmt:formatDate             value="${timesheet.periodEndingDate}" type="date"


Now let's look at another interesting piece of code from our view file, timesheetlist.jsp:

<c:if test="${not empty message}">    <font color="green"><c:out value="${message}"/></font>    <c:set var="message" value="" scope="session"/> </c:if>


All this code does is check for any messages stored in the message session attribute. This message is set by the Enter Hours controller upon a successful save in the onSubmit method, as you will see later in the chapter.

We just looked at how to configure and code the Timesheet List screen. Now it is time to review more complex Spring MVC features.



Agile Java Development with Spring, Hibernate and Eclipse
Agile Java Development with Spring, Hibernate and Eclipse
ISBN: 0672328968
EAN: 2147483647
Year: 2006
Pages: 219

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