Building the Forum Using Model 1 Architecture

 < Free Open Study > 



As our discussion forum is only simple, we'll just go straight ahead and build it using a Model 1 page-centric architecture.

The presentation and logic of our application will be constructed from a number of JSP pages. We've already designed the underlying representation of our domain model so all we have to do now is build the user interface. With this in mind, we'll develop JSP pages that make use of our Topic, Response and User classes.

Although we are building an application based upon the Model 1 architecture, we could in fact use servlets to make use of the classes that we have just defined. However, because the majority of the code associated with building these pages is presentational, using JSP pages makes this easier. The same results could be achieved with servlets, but in this case the code would become complex and cluttered with statements simply printing the HTML back to the client.

Viewing the Topics

The first page that we need to build is the home page (index.jsp), which shows a list of the topics that are currently in our system. Here's what the page looks like in the browser:

click to expand

We've created links for each topic title so that the user can navigate to another page showing the responses that have been made so far. In terms of how this has been implemented, the table of topics is generated by some Java code embedded inside a JSP scriptlet. Our JSP page looks up the topics that are currently known by the system and then iterates over them. We make use of a class called Topics, which represents the set of sample data for this example. In a real system the topics would probably be stored in a database.

start sidebar

You should note that, for simplicity, surrounding HTML tags (such as <head> and <body>), Java import statements, and so on, have been omitted in the code below.

end sidebar

Here's the relevant code from index.jsp:

    <h2>Current topics</h2>    <p>    <table width="100%" border="1">      <tr>        <td><b>Title</b></td>        <td><b>Responses</b></td>      </tr>      <%        Collection topics = Topics.getTopics ();        Iterator it = topics.iterator();        Topic topic;        int id;        while (it.hasNext()) {          topic = (Topic)it.next();          id = topic.getId();      %>         <tr>           <td> 

In order to generate the appropriate hyperlink that will take the user to the responses page, we've just hard-coded the name of the page, passing the id of the topic as a parameter:

           <a href="view-topic.jsp?id=<%= id %>"><%= topic.getTitle() %></a>          </td>          <td>            <%= topic.getResponseCount() %>          </td>        </tr>      <%        }      %>    </table>    </p> 

The Login Page

In order to keep anonymous responses off our discussion forum we will require users to login. If we assume that the users are already setup on the system then they simply need to login with their username and password. For our forum there are two users setup - Sam and Simon, both with a password of password. Here's what the page looks like:

click to expand

As you can see, we have a simple HTML form containing two text fields - one for the user id (called id) and one for the password (called password): Once a user types in their information and clicks the Submit button, we need to process it and determine whether they are a valid user. To do this, we specify the name of another JSP in the action attribute of the form tag. So that the user's password doesn't get displayed in the address bar at the top of the browser, we've opted to use the POST method, again defined within the opening form tag of login.jsp:

    <h2>Login</h2>    <form action="process-login.jsp" method="post">    User id : <input type="text" name="id">    <br>    Password : <input type="password" name="password">    <br>    <br>    <input type="submit" value="Submit">    </form> 

Processing the Login

Next is the page that processes the login details, process-login.jsp. We've decided that the user should be forwarded back to the home page once they successfully log in. Therefore, this JSP page doesn't actually contain any visual element. Once more we use a class to represent sample data that would usually be stored in a database, in this case Users. Here's the relevant code from the JSP page:

    <%@ page import="forum.*" %>    <%      String id = request.getParameter("id");      String password = request.getParameter("password");      if (Users.exists (id, password)) {        session.setAttribute("user", Users.getUser(id));        pageContext.forward("index.jsp");      } else {        pageContext.forward("login.jsp");      }    %> 

We get the values of the user id and password that were sent as a result of the user submitting the form and use them to determine whether a user exists on the system. If this is the case, we lookup the appropriate User instance, place this in the HTTP session under the name user and redirect them to the home page:

click to expand

If a user doesn't exist with the specified user id and password, we'll (perhaps unhelpfully) simply return them to the login page.

Viewing the Responses

Next we want the page to display the responses to a particular topic, reached by clicking on a linked topic title on the home page:

click to expand

Again, this was built as a JSP page, view-topic.jsp. It takes the id parameter passed as part of the query string and uses it to look up the appropriate Topic:

    <%      String id = request.getParameter("id");      Topic topic = Topics.getTopic(Integer.parseInt (id));    %> 

Once it has these parameters, it can get a list of all of the responses to the selected topic and again generate an HTML table:

    <h2>Topic : <%= topic.getTitle() %></h2>    <p>    <table width="100%" border="1">    <tr>      <td><b>Author</b></td>      <td><b>Response</b></td>      <td>&nbsp;</td>    </tr>      <tr>        <td><%= topic.getUser().getId() %></td>        <td><%= topic.getText() %><br><br></td>        <td>&nbsp;</td>      </tr>      <%        Iterator it = topic.getResponses().iterator();        Response res; 

Here it builds up the table one row at a time, only displaying those responses that have not been deleted:

        while (it.hasNext()) {          res = (Response)it.next();          if (!res.isDeleted()) {      %>            <tr> 

The first row of data in the table contains the message associated with the original topic, with the remainder representing each response in the order in which it was added. As we're going to offer the ability to delete responses, we have an appropriate link for this that is generated in the last column. This is just a dynamically generated hyperlink that appends the following information to the query string:

  • topic - the id of the current topic

  • response - the id of the response to be deleted

              <td><%= res.getUser().getId() %></td>              <td><%= res.getText() %><br><br></td>              <td valign="top" align="center">                [ <a href="delete-response.jsp?                     topic=<%= topic.getId() %>&response=<%= res.getId() %>">                  Delete</a> ]              </td>            </tr>      <%          }        }      %>    </table>    </p> 

Finally, we have a link that will allow users to add new responses:

    <p>    <center>    [ <a href="new-response.jsp?id=<%= topic.getId() %>">New response</a> ]    </center>    </p> 

Adding a New Response

Adding a new response to an existing topic is a straightforward process, captured by a small HTML form containing a text area in which to write the response. Here's what it looks like:

click to expand

And here is the relevant HTML in the JSP page, new-response.jsp:

    // ... same as view-topic.jsp ...    <p>    <center>    <form action="process-new-response.jsp" method="post">    <textarea name="text" rows="4" cols="48">Type your response here.</textarea>    <input type="hidden" name="id" value="<%= id %>">    <br>    <br>    <input type="submit" value="Submit">    </form>    </center>    </p> 

Here we have a text area called text representing the body of the response, and a hidden field representing the id of the topic to which the new response should be added.

Processing a New Response

When the Submit button is clicked on the new-response.jsp page, we need to extract the information from the request and use it to add a new response to the appropriate topic. This can be performed as follows (this code is from process-new-response.jsp in the code download):

    <%@ page import="forum.*" %>    <%      String text = request.getParameter("text");      int id = Integer.parseInt(request.getParameter("id"));      User user = (User)session.getAttribute("user");      Topic topic = Topics.getTopic(id);      topic.add(new Response(user, text));      pageContext.forward("view-topic.jsp?background-color:d9d9d9">%> 

We extract the text and the topic id from the HTTP request, while the user information can be found in the HTTP Session object because that's where we placed it when the user logged in. Using all of this information we can find the appropriate Topic instance and add a new Response. Once complete we can forward the user onto the responses page once again so that they can see their new response.

Deleting an Existing Response

Finally we must build the functionality to delete a response. Once again, this is provided by a JSP (delete-response.jsp) as follows.

    <%@ page import="forum.*" %>    <%      int topicId = Integer.parseInt(request.getParameter("topic"));      int responseId = Integer.parseInt(request.getParameter("response"));      User user = (User)session.getAttribute("user");      Topic topic = Topics.getTopic(topicId);      Response res = topic.getResponse(responseId); 

We must check to see if the user is the author of the response. We won't allow deletion if this is not the case:

      if (res.getUser().equals(user)) {        topic.remove(res);      }      pageContext.forward("view-topic.jsp?background-color:d9d9d9">%> 

This is again fairly straightforward. Whatever happens, we simply forward back to the viewtopic.jsp page where the current state of the topic will be seen.

A Closer Look at the Page Flow for the Application

With our development complete, we can begin to test our web application. The page flow is as shown below:

click to expand

As with most websites, all pages link back to the home page. For clarity these links have not been included on the diagram. Also not included on the diagram are the constraints to indicate that a user must be logged in to be able to post a new response, or delete a response, and so on.

As it stands, the application works, but there are a few problems that you may have spotted already.

Authentication

Although we have a login link on the front page, the current structure of the website means that people can look at the topics without logging in. In fact, any user could bypass the login page completely, meaning that they would also be able to add new responses anonymously. For example, a user could open their browser and jump straight to the following page: http://localhost:8080/forum-model1/new-response.jsp?id=0.

One solution would be to require users to login before they can view the list of topics in the forum. However, this might reduce the likelihood of them visiting our site in the future. A better alternative would be to ask the user to login the first time that they wanted to perform some action on the site such as adding or deleting a response - that way they can still view all the valuable information quickly and easily.

This is easy enough and can be achieved by adding the following scriptlet to the top of those restricted pages:

    <%      if (session.getAttribute("user") == null) {        pageContext.forward("login.jsp");      }    %> 

In this scriptlet we check whether a User instance has been set in the user's session. If one does exist, we can assume that the user has already logged in and the page will be rendered as usual. If a User instance doesn't exist (under the name of user), we can forward the user to the login page.

This code fragment could be copied and pasted into each JSP that needs to be secure. This style of reuse is a step in the right direction but is hardly the most efficient. After all, if we needed to make some changes then we've certainly got our work cut trying to find each and every place that it's used.

Of course we could place this functionality into a reusable software component such as a JavaBean or a custom tag, or at a simpler level, another JSP that gets included wherever necessary. This is a further step in the right direction but still requires that we make use of the functionality everywhere that we need it. We've already noted earlier in the chapter that centralizing user access would make securing our application an easier task.

Authorization

In the same way as we have done for authentication, authorization code could be duplicated throughout the system. An example of this is the code that checks whether the current user can delete the selected response. If we forgot to make use of this functionality somewhere then data could become available or corrupted by inappropriate users. While it is probably not much of a problem in a small discussion forum, e-commerce sites generally have confidential information available (such as user's credit card numbers and home addresses). This information should certainly not be accessed by anybody except its rightful owner.

Extending the Application

We might want to extend our application so that we log a user's progress through the system, and track which pages in the system are being used more than others. This is especially useful for e-commerce type solutions where customers often leave if a website is deemed as too slow.

If we wanted to create a log that tracked the users throughout the site, whereabouts would this functionality be placed? Also, how easily could it be turned off when we've finished analyzing the data? In this example application, there is no single place - no central point - where such logging could be located. Instead, it would have to be placed into each page, either explicitly, by calling some included code, or by using a reusable component such as a JavaBean or custom tag. The decision to include a logging facility is therefore one that should be made at design time, before the coding commences.



 < Free Open Study > 



Professional Java Servlets 2.3
Professional Java Servlets 2.3
ISBN: 186100561X
EAN: 2147483647
Year: 2006
Pages: 130

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