|
|||||
Web
Design & Development CS506
VU
Lesson
40
MVC
Model 2 Architecture
We have
studied page-centric approach and page-with-bean
approach until now. You must
be wondering
when
we had covered these. Probably
these buzz words are new
one for you but we
already covered these
topics.
Let's review these once
again.
Page-Centric
Approach
A web
application that is collection of
JSPs. Generally this approach is
followed to get started
with
developing
web applications. This approach is
represented in the following
diagram:
The
page-centric approach has lot of draw
backs such as the code
becomes a mixture of presentation,
business
and data access logic.
The maintenance and up-gradation of the
application becomes a
nightmare.
Scaling
of such kind of application is
also difficult and lots of
code is also get
duplicated.
Page-with-Bean
Approach (MVC Model1)
This
approach is different from page-centric approach in a
way that all the business
logic goes into
JavaBeans.
Therefore, the web application is a
collection of JSPs and JavaBeans.
But still this approach
is
insufficient
to separate different kind of
logics. We have made an address
book example in the last
handout
using
this approach.
MVC
Model 2 Architecture
his
architecture introduces a controller. This
controller can be implemented
using JSP or servlet.
Introducing
a controller gives the following
advantages:
It centralizes the
logic for dispatching
requests to the next view
based on:
-The
Request URL
-Input
Parameters
-Application
state
It
gives the single point of
control to perform security
checks and to record
logging
information
It
also encapsulates the incoming
data into a form that is
usable by the back-end MVC model.
We'll
discuss it with the help of an
example.
The
following figure will help
you to understand the architecture and functioning of
the application that is
built
using MVC Model 2 architecture.
305
Web
Design & Development CS506
VU
306
Web
Design & Development CS506
VU
(saveperson.jsp
or showperson.jsp) page.
The
program flow of this example
is shown in the following diagram:
As
you can see in the diagram
that all the requests
are submitted to controller
which uses the
JavaBeans
and forwards/redirects the user to
another view (JSP)? If any
exception arises on
controller
or JSPs, the control would
automatically be transferred to
addbookerror.jsp to display an
appropriate
message.
How
controller differentiates between
requests?
Most
likely, you must be thinking
about it. The simplest
solution lies in using the
consistent name (e.g.
action)
of the submit button across
all the pages but
with different and unique values.
The same rule
applies
to
hyperlinks that send the
action parameter along with
value by using query string
technique.
This
eases the controller's job
to identify which page is
actually generated the request and
what to do next.
The
controller simply retrieves the value of
action parameter using
request.getParameter() method.
Now,
if-else
structure can be used to compare the
possible values of action to act upon the
requested task.
Now,
let's first see the code of
JavaBean that is used in
this example.
PersonInfo
This
JavaBean is used to represent
one person record. The code
is given below:
package
vu;
import
java.io.*;
public
class PersonInfo
implements
Serializable{
private
String name;
private
String address;
private
int phoneNum;
// no argument
constructor
public
PersonInfo() {
name
= "";
address
= "";
phoneNum
= 0;
}
//
setters
public
void setName(String
n){
name
= n;
}
public
void setAddress(String a){
address
= a;
}
public
void setPhoneNum(int
pNo){
phoneNum
= pNo;
}
//
getters
public
String getName( ){
return
name;
}
public
String getAddress( ){
return
address;
}
public
int getPhoneNum( ){
307
Web
Design & Development CS506
VU
return
phoneNum;
}
} //
end class PersonInfo
PersonDAO
This
class will help in
retrieving and storing person's records
in database. The code is
given below:
package
vu;
import
java.util.*; import
java.sql.*;
public
class PersonDAO{
private
Connection con;
//
default constructor
public
PersonDAO() throws
ClassNotFoundException
, SQLException {
establishConnection();
}
//
method used to establish connection
with db
private
void establishConnection()
throws
ClassNotFoundException ,
SQLException {
//
establishing conection
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String
conUrl = "jdbc:odbc:PersonDSN";
con =
DriverManager.getConnection(conUrl);
}
// used to
search the person records
against name and
returns
the
ArrayList that contains
only
//
those
PersonInfo
objects
which
matches
the search criteria i.e.
name
public
ArrayList retrievePersonList(String
pName) throws SQLException
{
ArrayList
personList
= new ArrayList();
//
preparing query
String
sql = " SELECT * FROM Person
WHERE name = ?";
PreparedStatement
pStmt = con.prepareStatement(sql);
pStmt.setString(
1, pName);
//
executing query
ResultSet rs =
pStmt.executeQuery();
String
name;
String
add;
int
pNo;
while
( rs.next() ) {
name
= rs.getString("name");
add =
rs.getString("address");
pNo =
rs.getInt("phoneNumber");
//
creating a CourseOutlineBean
object
PersonInfo
personBean = new
PersonInfo();
personBean.setName(name);
personBean.setAddress(add);
personBean.setPhoneNum(pNo);
308
Web
Design & Development CS506
VU
//
adding a bean to
arraylist
personList.add(personBean);
} //
end while
return
personList;
} //
end retrievePersonList
//
this method accepts an
object of PersonInfo, and stores it
into
// the
database
public
void addPerson(PersonInfo
person) throws
SQLException{
String
sql = " INSERT INTO Person
VALUES (?, ?, ?)";
PreparedStatement
pStmt = con.prepareStatement(sql);
String
name = person.getName();
String
add = person.getAddress();
int
pNo = person.getPhoneNum();
pStmt.setString(
1 , name );
pStmt.setString(
2 , add );
pStmt.setInt(
3 , pNo );
pStmt.executeUpdate();
} //
end addPerson // overriding
finalize method to release acquired
resources
public
void finalize( ) {
try{
con.close();
}
}catch(SQLException
sqlex){
System.out.println(sqlex);
}
} //
end finalize
} //
end PersonDAO class
addperson.jsp
This
page is used for entering a
new person record into the
database. Note that a
hyperlink is also given
at
the
ottom of the page that takes
the user to searchperson.jsp.
Note:
Since we
are following MVC model 2 architecture,
so all the hyperlinks will
also sends the
request
to
controller first which redirects the
user to requested
page.
309
Web
Design & Development CS506
VU
The
code of above page is given
below:
<%--
Although there are no
chances of exception to arise on
this page, for consistency,
error
page
is defined on top of all
JSPs
--%>
<%@page
errorPage="addbookerror.jsp" %>
<html>
<body>
<center>
<h2>
Address Book </h2>
<h3>
Add New Person</h3>
<%--
As mentioned in MVC2, all
the requests are submitted
to controller, that's why
action's
contains the value of
"controller.jsp"
--%>
<form
name ="register" action="controller.jsp"
/>
<TABLE
BORDER="1" >
<TR>
<TD> <h4> Name
</h4> </TD> <TD>
<input type="text" name="name"
/>
</TD>
</TR>
<TR>
<TD> <h4> Address
</h4> </TD> <TD>
<input type="text"
name="address"
/>
</TD>
</TR>
<TR>
<TD> <h4>Phone
Number</h4>
</TD>
<TD> <input
type="text"
name="phoneNum"
/> </TD>
</TR>
<TR>
<TD COLSPAN="2"
ALIGN="CENTER"">
<%--
As described above the technique to differentiate
between the requests, the
name
of the button is "action" with
value "save".
--%>
<input
type="submit" name ="action" value="save"
/>
<input
type="reset" value="clear" />
</TD>
310
Web
Design & Development CS506
VU
</TR>
</TABLE>
</form>
<h4>
<%-
The hyperlink will also
sends the request to
controller
Note
the action parameter with
its value are also part of
hyperlink
using
the
query string
technique.
--%>
<a
href="controller.jsp?action=searchperson"
>
Search
Person </a>
</h4>
</center>
</body>
</html>
searchperson.jsp
This
JSP is used to search the
person record against name given in the
text field. A hyperlink is
also given
at the
bottom of addperson.jsp.
The
code that is used to
generate that above page is
given below:
<%--
defining error page
--%>
<%@page
errorPage="addbookerror.jsp" %>
<
html>
<body>
<center>
<h2>
Address Book </h2>
<h3>
Search Person</h3>
<form
name ="search" action="controller.jsp"
/>
<TABLE
BORDER="1" >
<TR>
<TD> <h4> Name
</h4> </TD> <TD>
<input type="text" name="name"
/>
</TD>
</TR>
<TR>
<TD
COLSPAN="2" ALIGN="CENTER"">
311
Web
Design & Development CS506
VU
<%-
The name of the button is
still "action" but with
different value
"search".
--%>
<input
type="submit" name ="action"
value="search" />
<input
type="reset" value="clear" />
</TD>
</TR>
</TABLE>
</form>
<h4>
<%-
The action parameter with
different value "addperson"
are part of hyperlink
here as
well.
--%>
<a
href="controller.jsp?action=addperson"
>
Add Person
</a>
</h4>
</center>
</body>
</html>
controller.jsp
As
mentioned earlier that
controller.jsp identifies the page
which initiates the request
and use JavaBeans to
save/search
persons to/from database.
Also its job list
includes redirecting the user to
appropriate page.
Since
this JSP is doing only
processing therefore no view
available. Let's check it
out its code:
<%--
defining error page
--%>
<%@page
errorPage="addbookerror.jsp" %>
<%--
importing required packages.
package vu contains JavaBeans
--%>
<%@page
import ="java.util.*" %>
<%@page
import
= "vu.*" %>
<html>
<body>
<%--
declaring PersonDAO
object--%>
<jsp:useBean
id="pDAO" class="vu.PersonDAO" scope="page"
/>
<%-
scriptlet to identify JSP
for redirection purpose if
request comes from
hyperlinks
--%>
<%
//
retrieving action parameter
value
//
Remember that "action" is the
name of buttons as well
// it is
used in hyperlinks in making of
query string
String
action = request.getParameter("action");
// if
"Add Person" hyperlink is
clicked
if
(action.equals("addperson") ){
response.sendRedirect("addperson.jsp");
// if "Search
Person" hyperlink is clicked
} else
if (action.equals("searchperson")){
response.sendRedirect("searchperson.jsp");
// if
"save" button is clicked of
addperson.jsp
}else
if (action.equals("save")) {
%>
//
declaring PersonInfo obeject
312
Web
Design & Development CS506
VU
<jsp:useBean
id="personBean" class="vu.PersonInfo"
scope="page"/>
<%--
setting
all properties of personBean object
with input
parameters
using *
--%>
<jsp:setProperty
name="personBean" property="*"
/>
<%--
to insert record into
database--%>
<%
pDAO.addPerson(personBean);
//
redirecting user to
saveperson.jsp
response.sendRedirect("saveperson.jsp");
%>
<%-- if
"search" button is clicked on
searchperson.jsp --%>
<%
}else
if (action.equals("search") ) {
String
pName = request.getParameter("name");
ArrayList personList =
pDAO.retrievePersonList(pName);
//
storing personList(contains PersonInfo
objects) into // request
hashmap
request.setAttribute("list",
personList);
%>
<%--
forwarding request to showperson.jsp to
retrievestored arraylist
("list")
--%>
<jsp:forward
page="showperson.jsp" />
<%
} //
end if page == search
%>
</body>
</html>
saveperson.jsp
This
page displays a successful
message indicating that
person record is saved. Its
also give the options
to
the
user to move on to addperson.jsp or
searchperson.jsp through hyperlinks.
Note that these
hyperlinks
also
first take the user to
controller.jsp then on to requested
page.
The
code of saveperson.jspis given
below:
<%--
defining error page
--%>
<%@page
errorPage="addbookerror.jsp" %>
<html>
313
Web
Design & Development CS506
VU
<body>
<center>
<h3>
New Person Record is saved
successfully!</h3>
<h4>
<a
href="controller.jsp?action=addperson" >
Add
Person
</a>
</h4>
</h4>
<a
href="controller.jsp?action=searchperson" >
Search
Person
</a>
</h4>
</center>
</body>
</html>
showperson.jsp
This
following figure gives you
the view when name "saad" is
searched.
Below,
the code of showperson.jsp is
given:
<%--
defining error page
--%>
<%@page
errorPage="addbookerror.jsp" %>
<%--
importing required packages
--%>
<%@page
import="java.util.*" %>
<%@page
import="vu.*"
%>
<html>
<body>
<center>
<h2>
Address Book </h2>
<h3>
Following results meet your
search criteria</h3>
<TABLE
BORDER="1" >
<TR>
<TH>
Name </TH>
<TH>
Address </TH>
<TH>
PhoneNum </TH>
</TR>
<%
//
retrieving arraylist stored on
controller.jsp to display PersonInfo
objects
ArrayList
personList = (ArrayList)request.getAttribute("list");
PersonInfo person =
314
Web
Design & Development CS506
VU
null;
for(int
i=0; i<personList.size(); i++)
{
person
= (PersonInfo)personList.get(i);
%>
<%--
displaying PersonInfo
details--%>
<TR>
<TD> <%=
person.getName()%> </TD>
<TD> <%=
person.getAddress()%>
</TD>
<TD> <%=
person.getPhoneNum()%> </TD>
</TR>
<%
} // end
for
%>
</TABLE
>
<h4>
<a
href="controller.jsp?action=addperson"> Add
Person </a> <a
href="controller.jsp?action=searchperson">Search
Person</a>
</h4>
</c
enter>
</body>
</html>
addbookerror.jsp
User
will view this page
only when any sort of
exception is generated. The code of
this page is given
below:
<%--
indicating that this is an
error page --%>
<%@page
isErrorPage="true" %>
<%--
importing class
--%>
<%@page
import = "java.sql.SQLException"
%>
<html>
<head>
<title>Error</title>
</head>
<body>
<h2>
Error
Page
</h2>
<h3>
<%--
scriptlet to determine exception
type --%>
<%
if
(exception instanceof SQLException)
{
%>
An SQL
Exception
<%
} else
if (exception instanceof
ClassNotFoundException){
%>
A Class
Not Found Exception
<%
} else
{
%>
A
Exception
<%
} //
end if-else
%>
315
Web
Design & Development CS506
VU
<%--
end scriptlet to determine exception type
--%>
occured
while interacting with the
database
</h3>
<h3>
The
Error Message was
<%=
exception.getMessage() %>
</h3>
<h3
> Please
Try Again Later! </h3>
<%--
hyperlinks to return back to adperson.jsp
orsearchperson.sjp
--%>
<h3>
<a
href="controller.jsp?action=addperson"
>
Add Person
</a>
<a
href="controller.jsp?action=searchperson"
>
Search Person
</a>
</h3>
</body>
</html>
JSP is
the Right Choice as a
Controller?
Since
JSP that is performing the
job of controller is doing
only processing and there is no
view available of
it.
It includes the logic of selecting JSP
and to retrieve/store records from/to
dataset using
JavaBeans.
But
remember the reason for
introducing JSPs? JavaServer Pages
are built for presentation
(view) only so
JSP
is really not a good place
for such kind of logic.
Concluding, what's the option we
have? The answer
is,
use Servlets as controller.
Introducing
a Servlet as Controller
Remove the
controller.jsp from the previous
example code and add
ControllerServlet.java (a servlet)
into
this
example. This ControllerServlet.java
performs the same job that
was previously performed
by
controller.jsp.
Besides
adding ControllerServlet.java, you have
to modify all the addresses
which are previously
pointing
to
controller.jsp. For example the
value of action attribute of
form tag & the address of
hyperlink in all
concerned
pages.
If
controller is defined in web.xml as an
alias of ControllerServlet.java, consider the
following fragment of
code
which shows the value of
action attribute of form tag
before and after introducing
change.
When
controller.jsp is acting as a
controller
<form
name ="register" action="controller.jsp"
/>
When
ControllerServlet.java is acting as a
controller then value of
action attribute
becomes:
<form
name ="register" action="controller"
/>
Similarly,
the following comparison shows the code
of hyperlinks used in the previous
example before and
after
making changes
When
controller.jsp is acting as a
controller
<a
href="controller.jsp?action=searchperson"
>
Search
Person
</a>
When
ControllerServlet.java is acting as a
controller
<a
href="controller?action=searchperson"
>
Search
Person
</a>
316
Web
Design & Development CS506
VU
Passing
Exceptions to an Error JSP
from a Servlet
Servlet
can use existing error
pages (like addbookerror.jsp) to
pass on the exceptions. Set the
request
attribute
to javax.servlet.jsp.JspExcpetion with the
exception object you want to
pass. After that
forwards
the
request to error
page.
For
example, the following code
snippet is taken from
ControllerServlet.java to demonstrate how
to pass
SQLExceptionto
addbookerror.jsp
..................
..................
}catch
(SQLException
sqlex){
//
setting SQLException
instance
request.setAttribute("javax.servlet.jsp.JspException"
,
sqlex);
RequestDispatcher rd =
request.getRequestDispatcher("addbookerror.jsp");
rd.forward(request,
response);
} // end
catch
CotrollerServlet.java
The
following code is of servlet
that is acting as a
controller
package
controller;
import
vu.*;
import
java.io.*;import java.net.*;
import
java.sql.*; import
java.util.*;
import
javax.servlet.*; import
javax.servlet.http.*;
public
class ControllerServlet
extends
HttpServlet {
//
This method only calls
processRequest()
protected
void doGet(HttpServletRequest request,
HttpServletResponse response)
throws
ServletException,
IOException {
processRequest(request,
response);
}
//
This method only calls
processRequest()
protected
void doPost(HttpServletRequest request,
HttpServletResponse response)
throws
ServletException,
IOException {
processRequest(request,
response);
}
protected
void processRequest(HttpServletRequest
request,
HttpServletResponse
response) throws ServletException,
IOException {
//
retrieving value of action
parameter
String
userAction =
request.getParameter("action");
// if
request comes to move to addperson.jsp
from hyperlink
if
(userAction.equals("addperson") ) {
response.sendRedirect("addperson.jsp");
// if request
comes to move to searchperson.jsp
from hyperlink
} else
if (userAction.equals("searchperson")) {
response.sendRedirect("searchperson.jsp");
// if "save"
button clicked on addperson.jsp to
add new record
} if
(userAction.equals("save")) {
//
this method defined
below
addPerson(request,response);
317
Web
Design & Development CS506
VU
// if
"search" button clicked on
searchperson.jsp for search
} else
if (userAction.equals("search"))
{
//
this method defined
below
searchPerson(request,response);
}
} // end
processRequest()
// if
request comes to add/save
person
private
void addPerson(HttpServletRequest
request, HttpServletResponse
response)
throws
ServletException, IOException
{
try
{
//
creating PersonDAO
object
PersonDAO
pDAO = new
PersonDAO();
//
creating PersonInfo
object
PersonInfo
person = new
PersonInfo();
//
setting properties of Person
object
//
setting name property
String
pName =
request.getParameter("name");
person.setName(pName);
//
setting address
propertyt
String
add = request.getParameter("address");
person.setAddress(add);
//
setting phoneNumb
property
String
pNo = request.getParameter("phoneNum");
int
phoneNum = Integer.parseInt(pNo);
person.setPhoneNum(phoneNum);
//
calling PersonDAO method to
save data into
database
pDAO.addPerson(person);
//
redirecting page to
saveperson.jsp
response.sendRedirect("saveperson.jsp");
}catch
(SQLException
sqlex){
//
setting SQLException
instance
request.setAttribute("javax.servlet.jsp.JspException"
, sqlex);
RequestDispatcher rd =
request.getRequestDispatcher("addbookerror.jsp");
rd.forward(request,
response); }
catch
(ClassNotFoundException
cnfe){
//
setting ClassNotFoundException
instance
request.setAttribute("javax.servlet.jsp.JspException"
, cnfe);
RequestDispatcher
rd =
request.getRequestDispatcher("addbo
okerror.jsp");
rd.forward(request,
response);
}
}//
end addperson()
// if
request comes to search
person record from
database
318
Web
Design & Development CS506
VU
private
void searchPerson(HttpServletRequest
request,
HttpServletResponse
response) throws ServletException,
IOException {
try
{
//
creating PersonDAO
object
PersonDAO
pDAO = new
PersonDAO();
String
pName = request.getParameter("name");
//
calling DAO method to retrieve
personlist from database // against
name
ArrayList
personList =
pDAO.retrievePersonList(pName);
request.setAttribute("list",
personList);
//
forwarding request to showpeson, so it
can render personlist
RequestDispatcher
rd = request.getRequestDispatcher("showperson.jsp");
rd.forward(request,
response);
}catch
(SQLException
sqlex){
//
setting SQLException
instance
request.setAttribute("javax.servlet.jsp.JspException"
, sqlex);
RequestDispatcher
rd =
request.getRequestDispatcher("addboo
kerror.jsp");
rd.forward(request,
response);
}catch
(ClassNotFoundException
cnfe){
//
setting ClassNotFoundException
instance
request.setAttribute("javax.servlet.jsp.JspException"
, cnfe);
RequestDispatcher
rd =
request.getRequestDispatcher("addbookerror.jsp");
rd.forward(request,
response);
}
}//
end searchPerson()
} //
end ControllerServlet
web.xml
As
you already familiar, for
accessing a servlet, you
need to define a URL pattern
in web.xml. This is
shown
below:
<?xml
version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>
ControllerServlet </servlet-name>
<servlet-class>
controller.ControllerServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>
ControllerServlet </servlet-name>
<url-pattern>
/controller </url-pattern>
</servlet-mapping>
</web-app>
eferences:
.
Java A Lab Course by Umair
Javed.
.
Java E-commerce course at
Stanford
319
Table of Contents:
|
|||||