WHAT’S IN THIS CHAPTER?
WROX.COM CODE DOWNLOADS FOR THIS CHAPTER
The wrox.com code download for this chapter is found at www.wrox.com/go/projavaeedesignpatterns
on the Download Code tab. The code is in the Chapter 14 download and individually named according to the names throughout the chapter.
The model view controller (MVC) pattern is one of the most ubiquitous architectural design patterns in modern application development that is listed in the book from the Gang of Four. It is built on the philosophy of separation of concerns and encapsulates the processing of application data from the presentation of the data. Not encapsulating the processing of data from the presentation of data leads to highly coupled systems that are hard to maintain and extend. The separation of concerns that the MVC pattern provides makes modifications to both the business logic and the user interface much easier and more independent.
The MVC pattern is not much different than buying a subscription from a cable provider and a TV set from an electrical store. One provides the content, and the other makes sure you view it in the right way. Neither worries about the changes in the technology on the field. You can always buy a new TV set when better panels are released or subscribe to more channels without buying new hardware.
Developers of web applications use the MVC pattern extensively, and it is within this context that its implementation will be discussed.
In MVC, the model represents the application’s data and related business logic. The model may be represented by one object or a complex graph of related objects. In a Java EE application, the data is encapsulated in domain objects often deployed in an EJB module. Data is transported to and from the database access layer in data transfer objects (DTOs) and accessed via data access objects (DAOs). See Chapter 12, “Data Access Pattern.”
The view is the visual representation of the data contained in the model. A subset of the model is represented in a single view; thus, the view acts as a filter to the model data. The user interacts with the model data via the view’s visual representation and invokes business logic that in turn acts upon the model data.
The controller links the view to the model and directs application flow. It chooses which view to render to the user in response to the user’s input and the business logic that’s processed. The controller receives a message from the view, which it forwards to the model. The model in turn prepares a response and sends it back to the controller where the view is chosen and sent to the user.
The MVC pattern logically spans the client and middle tier of a multitier architecture. In a Java EE environment, the model is located in the business layer, normally in the form of an Enterprise JavaBeans (EJB) module. The controller and view are located in the web tier. The view is likely to be constructed from JavaServer Faces (JSF) or JavaServer Pages (JSP) with the help of Expression Language (EL). The controller is normally a servlet that receives Hypertext Transfer Protocol (HTTP) requests from the user. See Chapter 2, “Basics of Java EE” for a discussion of multitier architecture and the different application layers.
Often the MVC pattern is combined with other patterns, such as the command (or action), strategy, composite, and observer patterns. This chapter doesn’t delve into the depths of these patterns, but it does touch on the action pattern in the example that follows.
Even though the MVC elements of this pattern were defined more than 30 years ago, they are surprisingly relevant to their current use in a web application.
Figure 14.1 shows the user making a request to the controller. The controller handles the request by updating the model and rendering a new view, which is then sent to the user.
The MVC pattern comes in many different forms. The two most recognized are referred to as Type I and Type II.
The principle difference between Type I and Type II is where the controller logic is located: in Type I it is in the view, and in Type II it is in a servlet.
Many frameworks, such as Spring MVC, Struts, Grails, and Wicket, implement their own version of the Type II MVC pattern. For example, Spring MVC includes the concept of the Dispatcher servlet that interacts with the HTTP requests and delegates to the controller, view (and view resolver), and handlers. Figure 14.2 shows a diagram of Spring’s implementation of the MVC pattern.
You are going to implement the MVC pattern with the help of the action pattern. This pattern takes on the responsibility of determining where to redirect the user based on the user’s request. It helps maintain the single responsibility of the controller.
You’ll start with the controller class. In Listing 14-1, you have implemented a simple controller that responds to any HTTP GET
request made to the /users/*
path. The mapping of this relationship is defined in the web.xml
file:
<servlet>
<servlet-name>FrontController</servlet-name>
<servlet-class>com.devchronicles.mvc.plain.FrontController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FrontController</servlet-name>
<url-pattern>/users/*</url-pattern>
</servlet-mapping>
In the listing, you map the controller class com.devchronicles.mvc.plain.FrontController
to the request URL /users/*
. Therefore, for every request made to this URL, it is directed to the FrontController
class for processing.
The doGet()
method is invoked for such requests, and an Action
object is retrieved from the AbstractActionFactory
, which determines the location of the view that should be returned to the user.
Listing 14-2 has two classes: AbstractActionFactory
and ActionFactory
. The AbstractActionFactory
class creates an instance of the ActionFactory
class. The Action Factory’s getAction
method accepts an HttpServletRequest
object, which contains a reference to the URI of the requested location. The factory uses the URI to determine which Action
object to return to the controller. You maintain a map of URI request paths and Action
objects in the action Map
. An Action
object is chosen from the map based on the URI request path and returned to the controller.
What is important in the Action
object is that the concrete implementation provides an implementation of the execute()
method. This method performs business-specific logic required to generate the page that the user requested. It may query a database to obtain data, perform calculations, or generate a file.
In Listing 14-3, the ListUserAction
’s execute method constructs a list of users that it adds as an attribute to the request object; then it returns the location of the view to render and display to the user. The data now stored in the request object is accessed by the listuser.jsp
page and displayed.
For brevity, a List
object has been populated and returned, but in a real application, this is where you would use EJB or other data objects that connect to a database.
The Action
object returns to the controller, which receives the location of the page to which it should dispatch the request and response objects.
String view = action.execute(request, response);
getServletContext().getRequestDispatcher(view).forward(request, response);
In Listing 14-4, the JSP accesses the page’s requestScope
variable and retrieves the userList
list object created in ListUserAction
. It then iterates over the collection and displays the usernames.
The example that’s been demonstrated is a simple implementation of the MVC pattern. You’ll continue by looking at how you would implement the same application but using the advantages of Java EE 7.
The plain code implementation of the MVC pattern required you to write the controller logic, map the URLs to controller classes, and write a lot of plumbing code. However, in the latest release of Java EE, the plumbing code has been done for you. You only need to concentrate on the view and the model. The FacesServlet takes care of the controller implementation.
The FacesServlet takes control of managing user requests and delivering the view to the user. It manages the life cycle for web applications that use JSF to construct the user interface. All user requests go through the FacesServlet. The servlet is integral to JSF and can be configured if nonconventional behavior is required. However, thanks to the concept of convention over configuration, you will find that for all but the most complex web applications, it is not necessary to change the default configurations.
Since JSF 2.2, you can perform the most common configurations by using annotation, further reducing the need to touch the faces-config.xml
file.
You are going to rewrite the preceding example using the FacesServlet servlet and JSF. The view declaration language for JSF is called facelets. Facelets are the replacement for JSPs and are written in XHTML using cascading style sheets (CSS).
JSF includes the concept of backing beans. These are Plain Old Java Objects (POJOs) annotated with the @Named
and the @RequestScope
annotations. These beans are accessible by the JSF page for the duration of the HTTP request. You can refer to their methods directly in the JSF. In Listing 14-5, you rewrite ListUsersAction.class
to make it a backing bean.
Because all backing beans are annotated with at least @Named
and @RequestScope
, there is a Stereotype annotation you can use that gives it all the behavioral characteristics of a backing bean when it’s applied. This annotation is the @Model
annotation.
Next, you need to create an index.xhtml
file. This replaces home.jsp
and is called directly from the browser. The purpose of this JSF is to call the execute
method on ListUsersAction
that prepares the data for the view listusers.xhtml
.
Listing 14-6 shows how this method is provoked.
You use the h:commandLink
tag and reference the backing bean and the execute()
method in the action element. The execute()
method is called directly from the JSF; it generates the user list, returns the location of the view that will render the list, and then invokes the getUserList()
method and displays the user list. Listing 14-7 demonstrates this.
In the backing bean, the action class is referred to as listUsersAction
starting in lowercase, and the method getUserList()
omits the word get
. If a method starts with get
, you can omit it.
When you deploy this application, the index.xhtml
view renders the link, which when clicked will display a list of users as follows:
Our users are:
John Lennon
Ringo Starr
Paul McCartney
George Harrison
You have now successfully built an MVC-style website using the latest features of Java EE 7.
The most prolific use of the MVC pattern is in web applications, although you can use it anywhere there is a benefit to separating the view logic from the business logic. In fact, the use of the MVC pattern in web application architecture is so ubiquitous that any suggestion not to use it would be met with derision and disdain.
There is no doubt that the two principle benefits of using the pattern are strong. Its separation of concerns makes for a flexible and adaptable web application, and its separation of production allows different parts of the application to be developed virtually independently of each other. For example, one team can work on the display logic while separately another team can work on the business logic and domain objects.
The MVC pattern has many commentators offering their point of view on its use, implementation, and even validity. You will read my interpretations of this pattern and see many implementations. It can be confusing to see the real benefits of this pattern.
You should go back to the essence of the MVC pattern: the separation of the display logic from the business logic. If you implement code that stays true to this objective, you have successfully implemented the MVC pattern.
The concept behind a separation of presentation and business logic is to maintain a clear divide between domain objects that model your problem and the presentation of that logic. This separation allows the business data to be presented in any number of different ways, simultaneously and without the need for the domain object to know anything about the way it is being displayed. It could be displayed on the screen in a variety of formats or as Word or Excel files.