The user interface of an application can be volatile (changes frequently), while the application data and logic tend to be stable (changes infrequently). But changing the user interface may force changes to the application logic and data.
Divide the application into three classes:
Model: encapsulates application data and logic
View: responsible for displaying model data to the user
Controller: responsible for executing user commands, which may involve asking
the model to update its data.
Examples of a model might be the text of a word processor document or the worksheet of a spread sheet application.
Examples of views are windows that display representations of the application data such as charts, graphs, or formatted text.
Examples of controllers are menus, toolbars, control panels, message dispatchers, and command line interpreters such as the console.
Taken together, the views and controllers constitute the application's user interface (UI).
Most importantly, while the UI is dependent on the model, the model is totally independent of the UI.
In a web application, views are often implemented as JSPs, the controller might be a servlet, and the model might be a bean or an application server.
Where should presentation logic go in a traditional client-server application. Can application data be decoupled from application logic? How does the web server fit in?
Application logic is encapsulated by one or more application servers. Application data is managed by a database server. Presentation logic is the responsibility of the web server, which can by pass the application server if the application logic is simple.
How can we decouple presentation/application logic from the technical details of implementing a generic server (such as security, communication, synchronization, transaction processing, etc.)
Implement a generic server as a container. Application/presentation logic can be implemented as components that implement an interface that allows the container to discover what the components do when they are installed.
A web server can be a container. In this case JSPs are the components. An application server can be a container. In this case EJBs (Enterprise Java Beans) are components. A web page can be a container. In this case web elements such as tables, forms, scripts, and applets are components.
Changing the source of data may force us to make major changes to the rest of the application.
Encapsulate access to the data source in a data access object (DAO). If the DAO implements a given interface, then changes to the data source only involve changes to the DAO.
We would like to limit that amount of logic employed by a view and focus instead on design.
Encapsulate any logic (such as getting the data required from a DAO) in a view helper bean.
Multiple accesses to a remote database to fetch the fields of a row can be inefficient.
Fetch all the rows at once. Store them in a simple value object that has public fields corresponding to each column in the result set.
<%!
String selectView(String cmmd) {
return cmmd; // for now
}
%>
<html>
<head><title> Front Controller </title></head>
<body>
<%
String command =
request.getParameter("cmmd");
String view = selectView(command);
if (view != null) {
%>
<jsp:forward page = "<%= view %>" />
<%}%>
</body>
</html>
public class DAOBean implements Serializable {
protected String driverName =
"COM.cloudscape.core.RmiJdbcDriver";
protected String dbasePrefix =
"jdbc:cloudscape:rmi:";
protected Connection connection;
protected Statement statement;
public ResultSet
execute(String sql) {
try {
System.out.println("sql =
" + sql);
boolean ok =
statement.execute(sql);
System.out.println("ok =
" + ok);
return statement.getResultSet();
} catch (SQLException e) {
//return null;
}
return null;
}
public void connect(String dbName)
throws SQLException,
ClassNotFoundException {
String dbaseName = dbasePrefix +
dbName;
try {
Class.forName(driverName);
connection =
DriverManager.getConnection(dbaseName);
} catch (Exception e) { // dbase not
found?
System.err.println
("can't connect to " +
dbaseName + " because " + e);
connection =
DriverManager.getConnection(dbaseName
+ ";create=true");
}
statement =
connection.createStatement();
}
public void finalize() throws SQLException
{
statement.close();
connection.close();
}
}
public class PersonVOBean implements java.io.Serializable {
public int pid;
public String fname;
public String lname;
public String street;
public String city;
public String state;
public String zip;
public String phone;
}
import java.sql.*;
import java.io.*;
public class PeopleHelperBean implements Serializable {
private DAOBean dao;
static private int nextPID = 10;
public PeopleHelperBean() {
try {
dao = new DAOBean();
dao.connect("people");
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
public boolean find(PersonVOBean vo) {
try {
String sql = "select * from
people where lname='" + vo.lname + "'";
ResultSet rs = dao.execute(sql);
boolean flag = rs.next();
if (!flag) return false;
vo.fname =
rs.getString("fname");
vo.street =
rs.getString("street");
vo.city =
rs.getString("city");
vo.state =
rs.getString("state");
vo.zip =
rs.getString("zip");
vo.phone =
rs.getString("phone");
vo.pid =
rs.getInt("pid");
} catch (Exception e) {
System.err.println("e =
" + e.getMessage());
return false;
}
return true;
}
public void insert(PersonVOBean vo) {
String sql = "insert into
people values (";
sql += nextPID++;
sql += ", '" + vo.fname;
sql += "', '" + vo.lname;
sql += "', '" + vo.street;
sql += "', '" + vo.city;
sql += "', '" + vo.state;
sql += "', '" + vo.zip;
sql += "', '" + vo.phone +
"')";
System.out.println("sql =
" + sql);
dao.execute(sql);
}
}
<jsp:useBean id = "helper"
scope = "request" class =
"PeopleHelperBean" />
<jsp:useBean id = "vo" scope = "request" class =
"PersonVOBean" />
<html>
<head><title> Search Me </title></head>
<body>
<%
String unk = "unknown";
boolean flag = false;
if
(request.getParameter("insert") != null) {
vo.fname =
request.getParameter("fname");
vo.lname =
request.getParameter("lname");
vo.street =
request.getParameter("street");
vo.city =
request.getParameter("city");
vo.state =
request.getParameter("state");
vo.zip =
request.getParameter("zip");
vo.phone =
request.getParameter("phone");
helper.insert(vo);
} else {
String last =
request.getParameter("lname");
if (last != null) {
vo.lname = last;
flag = helper.find(vo);
}
}
%>
Enter last name to search. Fill in all fields and check insert to
insert.<br/>
<form action = "FrontController.jsp">
<input type = "hidden" name = "cmmd" value =
"PeopleView.jsp" />
Last Name:
<input type = "text" name = "lname"
value = "<%=flag?vo.lname:unk %>"/>
<hr /><br />
First Name:
<input type = "text" name = "fname" value =
"<%=flag?vo.fname:unk%>"/><br />
Street:
<input type = "text" name = "street"
value ="<%=flag?vo.street:unk%>"/><br />
City:
<input type = "text" name = "city" value
="<%=flag?vo.city:unk%>"/>
<br />
State:
<input type = "text" name = "state" value =
"<%=flag?vo.state:unk%>"/><br />
Zip:
<input type = "text" name = "zip" value =
"<%=flag?vo.zip:unk%>"/>
<br />
Phone:
<input type = "text"
name = "phone" value =
"<%=flag?vo.phone:unk%>"/><br /><hr />
<p><hr />
Check to insert a record:
<input type = "checkbox" name = "insert" />
</p><hr />
<input type = "submit">
</form>
</body>
</html>