The Grand Tour: Kickin' It MVC Style

January is turning out to be a pretty light month for Java news. Oh well, more time to continue my grand tour of Java Web development! Still following along?

Last time, I showed you how to convert a “to-do list” servlet into a JSP. Unfortunately, what we got wasn’t much better in terms of readable code–Java code embedded in an HTML document isn’t a whole lot more readable than HTML code embedded in a Java class.

What to do? Well, so far we have two tools at our disposal: servlets and JSPs. Servlets are great for containing Java code, JSPs are great for containing HTML code. The answer is to split our application apart so that the Java code goes into servlets, and the HTML code goes into JSPs.

A standard approach for this called Model 2 Architecture has been around for a long time, but lately it has become known by the more descriptive name: Model-View-Controller (MVC).

The idea is to break the application into three parts:

  • The model: a collection of Java classes that perform the actual work of the application (often called the business logic), independant of the Web interface.
  • The view, a collection of JSPs, or some other technology, that produce the actual Web pages that the users see.
  • The controller, one or more servlets that process browser requests by telling the model what to do and then handing over to the view to respond.

Now I could blab on and on about this all day, but it’s easier to see through an example, so let’s get to work on modifying our to-do list application.

The model is usually the best place to start, as you can usually write it without worrying much about the Web interface. In the case of our to-do list application, we already have our model: it’s made up of the classes ToDoList and ToDoItem. These two classes do all the work of managing the to-do list.

While we’re looking at these classes, let’s make one minor tweak to the getToDoItems method: we’ll make it return a List rather than an Iterator. This allows for a bit more flexibility in how the to-do list items may be used when they are retrieved through this method.

  public List getToDoItems() {     refreshList();     return (List)list.clone();   }

Next, let’s work on our controller. We know we’ll have three different kinds of requests coming from the browser: simple requests to view the to-do list, form posts for adding new items to the list, and form posts for deleting existing items from the list.

We now have a choice: do we write one servlet that knows how to handle all these different request types, or do we write three simple, specialized servlets that each know how to handle one type of request? There is no right answer, as there are advantages to each approach, but let’s try to keep our classes simple and go for multiple servlets.

We’ll start with ToDoServlet, which will handle requests to view the to-do list. The first thing this servlet needs to do is set up the model–an instance of ToDoList. Back when we first looked at servlets, we did this with the init() method of the servlet, which stored the ToDoList in an instance variable of the servlet.

This time, that won’t quite do the trick, because we want all three of our servlets to be able to access the model. We can’t create the ToDoList in one servlet’s initialization procedure because one of the other servlets might need it first, and we can’t store it in an instance variable because the other servlets wouldn’t be able to see it at all. What we need is a way to create the model when the Web application first starts up, and a place to store it where any servlet can get at it.

To perform initialization tasks for the entire application, we must use a ServletContextListener. Rather than a class to extend, this is an interface, which any class can implement. Since our “main” servlet is a good place to do this stuff, we’ll make it implement that interface:

public class ToDoServlet extends HttpServlet     implements ServletContextListener {

When a class implements ServletContextListener, it must contain two methods: contextInitialized, which performs application initialization tasks, and contextDestroyed, which performs application cleanup:

  public void contextInitialized(ServletContextEvent sce) {     ServletContext sc = sce.getServletContext();     sc.setAttribute("toDoList",         new ToDoList(sc.getInitParameter("jdbcDriver"),                      sc.getInitParameter("jdbcConnectionString")));   }    public void contextDestroyed(ServletContextEvent sce) {   }

All the action here is in contextInitialized, since we don’t need to do anything special when the application shuts down. As you can see, both of these methods receive a ServletContextEvent when they are called, from which we can get a reference to the ServletContext. The ServletContext is an object that represents the Web application as a whole–it is the context in which the servlet is running. All servlets and JSPs have access to the ServletContext; therefore, it provides the perfect place to store our model!

The ServletContext lets you set and get attributes, which are simply application-wide values associated with string labels. We will store our model, a new ToDoList object, in an attribute labelled "toDoList".

Before we move on, have a close look at the code that creates the ToDoList:

        new ToDoList(sc.getInitParameter("jdbcDriver"),                      sc.getInitParameter("jdbcConnectionString")));

As we have done previously, we’re getting the JDBC driver and connection string values required by this class from initialization parameters, but because we are performing initialization for our entire application, the initialization parameters for the ToDoServlet are not yet available! That’s why we’re calling the getInitParameter method of the ServletContext object, not the servlet itself as we are used to doing. These are known as context initialization parameters, as opposed to servlet initialization parameters.

So we’ve got a ServletContextListener that’s ready to initialize our application, as long as it gets the context initialization parameters it needs. As you may have guessed, we need to add some things into our web.xml file to make this work:

<?xml version="1.0" encoding="UTF-8"?> <web-app 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 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">   <display-name>ToDoMVC</display-name>   <listener>     <listener-class>com.sitepoint.ToDoServlet</listener-class>   </listener>   <context-param>     <description>The JDBC driver class.</description>     <param-name>jdbcDriver</param-name>     <param-value>com.mysql.jdbc.Driver</param-value>   </context-param>   <context-param>     <description>The JDBC connection string.</description>     <param-name>jdbcConnectionString</param-name>     <param-value>jdbc:mysql://localhost/todo?user=root&amp;password=password</param-value>   </context-param> </web-app>

The <listener> tag lets the application know about the context listener we have provided, while the <context-param> tags set up our application-wide context initialization parameters.

Now, before we got caught up in all this application initialization stuff, I seem to remember we were writing a servlet. So let’s take a look at the doGet and doPost methods:

  public void doGet(HttpServletRequest request, HttpServletResponse response)       throws ServletException, IOException {     ToDoList toDoList = (ToDoList)getServletContext().getAttribute("toDoList");     List toDoItems = toDoList.getToDoItems();     request.setAttribute("toDoItems", toDoItems);        RequestDispatcher view = request.getRequestDispatcher("/todo.jsp");     view.forward(request, response);   }    public void doPost(HttpServletRequest request, HttpServletResponse response)       throws ServletException, IOException {     doGet(request, response);   }

Look at that! A servlet with no embedded HTML code! How is such a thing possible? Well remember, this servlet is merely the controller in our MVC design–after getting things done with the model, it hands the request to the view to display the actual Web page. Looking closely at the doGet method, you’ll see this is exactly what it does:

    ToDoList toDoList = (ToDoList)getServletContext().getAttribute("toDoList");     List toDoItems = toDoList.getToDoItems();     request.setAttribute("toDoItems", toDoItems);

Here it fetches the model (the ToDoList stored in a servlet context attribute), uses it to get a List of the to-do list items, and then stores that List someplace where the view will be able to find it–namely, in the request object. It turns out that the request object supports attributes too, and this is the perfect way to pass values to the view that it will need to build the page.

With the heavy lifting done, we’re ready to pass the request to the view (in this case, a JSP called todo.jsp in the root of our application):

    RequestDispatcher view = request.getRequestDispatcher("/todo.jsp");     view.forward(request, response);

At a glance, this may seem a bit bamboozling, but this is the formula we will always use to forward requests from a servlet to a JSP. We get a RequestDispatcher object for the location we want to forward to (in this case, "/todo.jsp" specifies the todo.jsp file in the root of the application), then we call its forward method, passing it the request and response objects it will need to do the job.

Okay, so I’ve had to yammer on a bit to explain all the new stuff that’s going on in this servlet, but if you step back and look at the code, you’ll find it’s actually pretty neat and tidy. And since they aren’t burdened with all the application setup stuff, our other two servlets are even neater and tidier!

package com.sitepoint;  import javax.servlet.*; import javax.servlet.http.*; import java.io.*;  public class AddToDoServlet extends HttpServlet {   public void doPost(HttpServletRequest request, HttpServletResponse response)       throws ServletException, IOException {      String newToDo = request.getParameter("newtodo");     if (newToDo != null) {       ToDoList toDoList = (ToDoList)getServletContext().getAttribute("toDoList");       toDoList.addItem(newToDo);     }     response.sendRedirect("index.html");   } }
package com.sitepoint;  import javax.servlet.*; import javax.servlet.http.*; import java.io.*;  public class DeleteToDoServlet extends HttpServlet {   public void doPost(HttpServletRequest request, HttpServletResponse response)       throws ServletException, IOException {     String deleteid = request.getParameter("deleteid");     if (deleteid != null) {       try {         ToDoList toDoList = (ToDoList)getServletContext().getAttribute("toDoList");         toDoList.deleteItem(Integer.parseInt(deleteid));       }       catch (NumberFormatException e) {         throw new ServletException("Bad deleteid value submitted.", e);       }     }     response.sendRedirect("index.html");   } }

You might be surprised to note that these two servlets don’t actually forward to a JSP after they’ve done their work. Instead, they redirect the browser to "index.html", which we’ll shortly configure to point to our main ToDoServlet.

Because we want to show the user the updated to-do list after adding or deleting an item, we could forward the request to /todo.jsp, but, as I have explained in the past, this would lead to problems if the user were to refresh the browser afterward. The browser would re-submit the item addition/deletion request, causing errors or duplicate list entries. Redirecting instead of forwarding gets around this by having the browser make a new request, which is safe to repeat, after it has submitted the form.

To polish off our servlets, we need to assign URLs to each of them in our web.xml file. We’ll use /index.html for the ToDoServlet, since we want it to come up by default when a user loads our application directory. AddToDoServlet and DeleteToDoServlet will get /AddItem.do and /DeleteItem.do respectively, following the convention of giving “action” URLs .do extensions in Java Web apps.

  <servlet>     <servlet-name>todoservlet</servlet-name>     <servlet-class>com.sitepoint.ToDoServlet</servlet-class>   </servlet>   <servlet-mapping>     <servlet-name>todoservlet</servlet-name>     <url-pattern>/index.html</url-pattern>   </servlet-mapping>   <servlet>     <servlet-name>addtodoservlet</servlet-name>     <servlet-class>com.sitepoint.AddToDoServlet</servlet-class>   </servlet>   <servlet-mapping>     <servlet-name>addtodoservlet</servlet-name>     <url-pattern>/AddItem.do</url-pattern>   </servlet-mapping>   <servlet>     <servlet-name>deletetodoservlet</servlet-name>     <servlet-class>com.sitepoint.DeleteToDoServlet</servlet-class>   </servlet>   <servlet-mapping>     <servlet-name>deletetodoservlet</servlet-name>     <url-pattern>/DeleteItem.do</url-pattern>   </servlet-mapping>

With our servlets done, all that’s left is to build the view for our application. For this example, all we need is a single JSP file: todo.jsp.

Now that we’ve pulled all our initialization and request processing code out into servlets, our JSP file looks a lot more reasonable:

<%@ page import="java.util.*,com.sitepoint.*,uk.co.anyware.html.*" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head>   <title>To-Do List</title>   <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />   <link rel="stylesheet" type="text/css" href="<%= request.getContextPath() %>/styles.css" /> </head> <body>   <%   List toDoItems = (List)request.getAttribute("toDoItems");   Iterator it = toDoItems.iterator();   if (it.hasNext()) {     %>     <form action="DeleteItem.do" method="post">       <select name="deleteid" size="<%= Math.max(2, toDoItems.size()) %>">         <%         while (it.hasNext()) {           ToDoItem toDoItem = (ToDoItem) it.next();           %>           <option value="<%= toDoItem.getId() %>"><%= HTMLEscaper.escape(toDoItem.toString()) %></option>           <%         }         %>       </select>       <input type="submit" value="Delete Selected Item" />     </form>     <%   }   %>   <form action="AddItem.do" method="post">     <input type="text" name="newtodo" />     <input type="submit" value="Add New Item" />   </form> </body> </html>

If you understood the JSP we built last time, this one should be a piece of cake! The scriptlet code simply pulls the List out of the request‘s "toDoItems" attribute to produce the list of to-do items, and our two forms now submit to the .do URLs we assigned to the corresponding servlets. Beyond those changes, it’s the same old JSP with a lot less Java code.

And there we have it: an MVC Java Web application! Here’s the directory structure:

/todo.jsp /styles.css /WEB-INF/web.xml /WEB-INF/classes/com/sitepoint/AddToDoServlet.class /WEB-INF/classes/com/sitepoint/AddToDoServlet.java /WEB-INF/classes/com/sitepoint/DeleteToDoServlet.class /WEB-INF/classes/com/sitepoint/DeleteToDoServlet.java /WEB-INF/classes/com/sitepoint/ToDoItem.class /WEB-INF/classes/com/sitepoint/ToDoItem.java /WEB-INF/classes/com/sitepoint/ToDoList.class /WEB-INF/classes/com/sitepoint/ToDoList.java /WEB-INF/classes/com/sitepoint/ToDoServlet.class /WEB-INF/classes/com/sitepoint/ToDoServlet.java /WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.class /WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.java /WEB-INF/lib/mysql-connector-java-version-bin.jar

Download the code (250KB)

This application is starting to look pretty darned good, even if I do say so myself. Some of the code can be a bit of a pain to type by hand, but with a good Java IDE to write the boilerplate code for you (with a major new version out just last month, NetBeans is a popular free choice), a lot of the drudgery goes away.

The major weakness of the application at this stage continues to be the Java scriptlet code in the JSP. We’ve gotten rid of most of the Java code from this file, but what’s in there would still be pretty confusing for a Web designer. The next step in the grand tour will be to look at some of the features of modern JSP that allow us to dispense with these scriptlets in favour of tags and expressions.

Replay

Category: java Time: 2005-01-14 Views: 1
Tags:

Related post

  • The Grand Tour: A crash course in Java-less JSP 2005-05-22

    It's time to take the Java out of JavaServer Pages. In the last instalment of my "Grand Tour" of Java Web application technology, we split our to-do list Web application into three parts: the model, classes that manage the data at the heart of o

  • The Grand Tour: Servlets 2004-11-05

    If you've followed along, you've now got a to-do list database and a couple of classes that view and update it. The next step is to take that functionality to the Web by wrapping it in a Web application. On the Java platform, there are dozens of ways

  • The Grand Tour: Old School JSP 2005-01-01

    Thought I was gone, didn't you? December was a crazy month for me, so I had to put this blog on hold, but with the new year comes new priorities, and I'm back to serve you, the Java-hungry hordes. First up this year, another step along the path to un

  • Follow the Rubberduck - Part 3: JavaFX MVC and MVP Matrjoshka 2016-06-21

    After the last post had some minor improvements for me and the beta release was actually used for some things, I decided that the GUI was too ugly to continue like this and rewrote the whole GUI in JavaFX. The Matrjoshka - Usage This posed some chall

  • Is the source code of the online tour available? 2011-10-13

    For Oneiric Ocelot launch, there was an awesome Tour created for showcasing how Ubuntu especially Unity works. The Ubuntu Online tour actually mimics a whole desktop and to a greater extent behaves a lot like using Unity in real. My question is where

  • Formatting of entire column based on the grand total using color scale? 2014-08-19

    This might be answered somewhere else, but I haven't been able to find a solution to this. The question is how to use color scale for entire column just based on grand total. I have attached the picture for reference. I am happy with the color scale

  • File browser window in the "Ubuntu Tour" has no menu bar. Is this real? 2014-09-18

    File browser window of new (14.04?) Ubuntu has no menu bar across the top like old one. Don't want to go backward. So it seems a bad idea to upgrade to the new Ubuntu. Or does the file browser actually have a menu bar, just not shown on the tour? The

  • How to save the edit widget setting in a style or layer definition file? 2014-09-24

    I am using QGIS 2.4 on Windows 7 installed by the OSGeo4W-installer. I want to save the "edit widget"-settings in a style to use them after loading in a different vector layer. The problem: If I change the "edit widget"-setting in the

  • What is problematic about this approach for a Managed Package to provide subscriber orgs with the ability to modify our Visualforce styles? 2015-04-14

    We have a Managed Package that works with the Community product and so has a site template. The components and controllers for the template are going to be marked Global to allow clients to create their own site template (for the purpose of modifying

  • In Kubuntu 15.04, how do I switch the K-menu back to classic style? 2015-08-17

    I've updated to Kubuntu 15.04. Previously, the K-menu in Plasma could be switched to classic style by right-clicking and selecting Switch to classic style. In Kubuntu 15.04, this appears to be no longer available. In Kubuntu 15.04, how do I switch th

  • The entity type 'Microsoft.AspNet.Mvc.Rendering.SelectListGroup' requires a key to be defined 2016-01-18

    Not sure what happened but I am getting the following error while attempting to pull up any view in my web app. The code is auto generated by visual studio and I am not getting any errors before building. Using ASP.Net MVC 6, EF7. An exception of typ

  • Show the images from the shared drive with C# MVC 2016-02-22

    I want to show the images from the shared drive, I have published the solution and hosted in the IIS and created one directory named as "Images" which directs to the another server's shared folder having images. So I have to show those images in

  • Obtaining the best of both worlds: MVC and WebForms 2011-09-28

    Rather than asking a general question about WebForms vs MVC (such as in ASP.NET v/s ASP.NET MVC), I have a specific quesiton. It appears the main differences between the two approaches are WebForms is Event Driven and uses pre built components MVC ha

  • How to bind Data to the Template/View in Umbraco MVC 2016-01-18

    I am using Umbraco 6.2.1 with MVC3 and I Created one Document Type as Index and also template by the same name and My Umbraco Structure is as follows: Here I am trying to Render the View(CNOReplacement)and binding the Model data to the View on the su

  • Aligning address on the same line, in 3-column style 2016-02-20

    I have been using example res9a on this page. As you can see, the address is divided into three lines. I am new to LaTeX, so not sure if this is possible, but can those three lines be put in one line, just in a 3-column layout style? For example, the

  • What's the proper way to use each style in office suites? 2011-03-16

    In LibreOffice 3.3, the default range of paragraph styles include the following: "Addresse, Bibliography, Caption, Complimentary Close, Contents-" and character styles include: "Bullets, Definition, Endnote anchor, Example, Footnote anchor-

  • Building websites, which is the better approach MVP or MVC? 2011-06-21

    I'm looking for feedback on MVP and MVC patterns used as a framework to build a website. I've used both with a certain degrees of success and failure. Furthermore I've worked in places which have miserable implement MVP across the web, desktop and se

  • Does Drupal resave the photo even if it's already the correct size as your Image Style? 2011-08-26

    Does Drupal still recompress the photo even if the file you uploaded is already the same size as your selected Image Style? In the event that it does recompress it, is there a way to prevent it? Image quality is at stake in this case since it saves i

  • Does the Canon 50D have a picture style for Lomography? 2011-10-07

    Is there a Lomography picture style software for Canon 50D, are there custom camera settings I could use to achieve a similar effect? --------------Solutions------------- No built in picture style exists for lomo on the Canon 50D camera. Basically yo

iOS development

Android development

Python development

JAVA development

Development language

PHP development

Ruby development

search

Front-end development

Database

development tools

Open Platform

Javascript development

.NET development

cloud computing

server

Copyright (C) avrocks.com, All Rights Reserved.

processed in 4.246 (s). 13 q(s)