© Luciano Manelli and Giulio Zambon 2020
L. Manelli, G. ZambonBeginning Jakarta EE Web Developmenthttps://doi.org/10.1007/978-1-4842-5866-8_3

3. JSP Application Architectures

Luciano Manelli1  and Giulio Zambon2
(1)
Taranto, Italy
(2)
Harrison, ACT, Australia
 

In the first two chapters, you learned a large portion of JSP’s components through brief examples. In this chapter, I will tell you how everything fits together in complex applications.

The insertion of Java code into HTML modules opens up the possibility of building dynamic web pages, but to say that it is possible doesn’t mean you can do it efficiently and effectively. If you start developing complex applications exclusively by means of scripting elements, you’ll rapidly reach the point where the code will become difficult to maintain. The key problem with mixing Java and HTML, as in “Hello World!”, is that the application logic and the way the information is presented in the browser are mixed. Often, the business application designers and the web-page designers are different people with complementary and only partially overlapping skills. While application designers are experts in complex algorithms and databases, web designers focus on page composition and graphics. The architecture of your JSP-based applications should reflect this distinction. The last thing you want to do is blur the roles within the development team and end up with everybody doing what somebody else is better qualified to do. And even if you develop everything yourself, by keeping presentation and application logic separate, you will build more stable and more maintainable applications.

The Model 1 Architecture

The simplest way to separate presentation and logic is to move the bulk of the application logic from JSP to Java classes (i.e., Java beans), which can then be used within JSP (see Figure 3-1). This is called the JSP Model 1 architecture.
../images/309332_3_En_3_Chapter/309332_3_En_3_Fig1_HTML.jpg
Figure 3-1

JSP Model 1 architecture

Although Model 1 is acceptable for applications containing up to a few thousand lines of code, the JSP pages still have to handle the HTTP requests, and this can cause headaches for the page designers.

The Model 2 Architecture

A better solution, more suitable for larger applications, is to split the functionality further and use JSP exclusively to format the HTML pages. This solution comes in the form of the JSP Model 2 architecture, also known as the model view controller (MVC) design pattern (see Figure 3-2).
../images/309332_3_En_3_Chapter/309332_3_En_3_Fig2_HTML.jpg
Figure 3-2

JSP Model 2 architecture

With this model, a servlet processes the request, handles the application logic, and instantiates Java beans. JSP obtains data from the beans and can format the response without having to know anything about what’s going on behind the scenes.

E-bookshop

To illustrate this model, I will describe a sample application called E-bookshop, a small application to sell books online. E-bookshop is not really functional, because the list of books is hard-coded in the application rather than stored in a database. Also, nothing happens once you confirm the order. However, this example serves the purpose of showing you how Model 2 lets you completely separate business logic and presentation. Later in this chapter, I will introduce a better version of an online bookshop application that will accompany us through the rest of the book.

E-bookshop’s Structure

Now, create a new dynamic web project. Its name is “ebookshop”, and in the next dialog window, type “ebookshopWEB-INFclasses” as default output folder. When the next dialog comes up, associate the same name of configuration “context root” to “context directory”, that is, “ebookshop”.

Note that in this passage the creation of web.xml is checked. The automatic creation of the deployment descriptor is deprecated because the descriptor is no longer necessary for the latest applications (Servlet 3.X). The issue is related to the ability of working with “legacy” applications developed with Servlet 2.X.

Now, we create a new Servlet! You can just go to the File menu ➤ New ➤ Servlet.

Then, you can define the package ebookshop.Servlet (it is possible to insert different folders). Call the Servlet ShoppingServlet (conventionally Class and Servlet names are capitalized) as shown in Figure 3-3.
../images/309332_3_En_3_Chapter/309332_3_En_3_Fig3_HTML.jpg
Figure 3-3

Eclipse, servlet name, and package configuration

Finally, it is important to check the methods init and destroy in a Servlet.

We can immediately see that Eclipse generates the following annotation by default:
@WebServlet("/ShoppingServlet")
You can change it with /eshop:
@WebServlet("/eshop")
The annotation tells Tomcat that the requests will refer to the servlet as /eshop. As the root folder of this application (i.e., the folder immediately inside webapps) is ebookshop, Tomcat will then route to this servlet all the requests it will receive for the URL
http://servername:8080/ebookshop/eshop.

A little tip: if you want to indent file, select everything with Ctrl+A and then type Ctrl+I.

Now, you can copy the Servlet code or overwrite the file in the folder. I leave to you the choice.

Now, create a Java Class. To create a new class, right-click the ebookshop project and select “New ➤ Class” and give the name MyLog and package myclasses, as shown in Figure 3-4.
../images/309332_3_En_3_Chapter/309332_3_En_3_Fig4_HTML.jpg
Figure 3-4

Eclipse—creating a Java Class

Now, you can insert the other source files in your folder:
  • index.jsp, Checkout.jsp in workspaceebookshopebookshop

  • Book.java, in workspaceebookshopsrc

At last, refresh the project (position the cursor on the ebookshop project folder shown in the Project Explorer ➤, right-click, and select Refresh).

To get the application to work, you first need to compile it: it is simple with Eclipse, more than from the command line with javac! Build is automatic, but you can also use the clean option to refresh the project build (from main menu select project ➤, clean and select the ebookshop project).

After deploying the project (Run on Server), you can now open a browser and type http://localhost:8080/ebookshop/; you should see the application’s home page. If you want to export the project, use the WAR file; that is the best way to deploy your applications to more than one server: copy them into webapps, and Tomcat will do the rest for you. What could be easier than that?

Figure 3-5 shows the E-bookshop’s home page, which you see when you type http://localhost:8080/ebookshop in your browser’s address field.
../images/309332_3_En_3_Chapter/309332_3_En_3_Fig5_HTML.jpg
Figure 3-5

The E-bookshop home page

You can select a book by clicking the drop-down list, as shown in Figure 3-5, type in the number of copies you need, and then click the Add to Cart button. Every time you do so, the content of your shopping cart appears at the bottom of the window, as shown in Figure 3-6.
../images/309332_3_En_3_Chapter/309332_3_En_3_Fig6_HTML.jpg
Figure 3-6

The E-bookshop home page displaying the shopping cart

You can remove an item from the shopping cart or go to the checkout. If you add additional copies of a book to the cart, the quantity in the cart increases accordingly.

If you click the Checkout button , you’ll see the page shown in Figure 3-7.
../images/309332_3_En_3_Chapter/309332_3_En_3_Fig7_HTML.jpg
Figure 3-7

The E-bookshop checkout page

If you click the Buy more! link, you’ll go back to the home page with an empty shopping cart, ready for more shopping.

The E-bookshop Home Page

Listing 3-1 shows the home page http://localhost:8080/ebookshop/index.jsp. For ease of reading, I’ve highlighted the JSP directives and scriptlets in bold. The JSP index.jsp represents the V (view) component of the MVC design pattern.
<%@page language="java" contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page session="true" import="java.util.Vector, ebookshop.Book"%>
<html>
<head>
  <title>E-bookshop</title>
  <style type="text/css">
    body {background-color:gray; font-size=10pt;}
    H1 {font-size:20pt;}
    table {background-color:white;}
   </style>
  </head>
<body>
  <H1>Your online Bookshop</H1>
  <hr/><p/>
<%  // Scriptlet 1: check whether the booklist is ready
  Vector<ebookshop.Book> booklist =
      (Vector<ebookshop.Book>)session.getValue("ebookshop.list");
  if (booklist == null) {
    response.sendRedirect("/ebookshop/eshop");
    }
 else {
  %>
    <form name="addForm" action="eshop" method="POST">
      <input type="hidden" name="do_this" value="add">
      Book:
      <select name=book>
<%  // Scriptlet 2: copy the booklist to the selection control
        for (int i = 0; i < booklist.size(); i++) {
          out.println("<option>" + (String)booklist.elementAt(i) + "</option>");
          }
  %>
        </select>
      Quantity: <input type="text" name="qty" size="3" value="1">
      <input type="submit" value="Add to Cart">
      </form>
    <p/>
<%  // Scriptlet 3: check whether the shopping cart is empty
    Vector shoplist =
        (Vector<ebookshop.Book>)session.getAttribute("ebookshop.cart");
    if (shoplist != null  &&  shoplist.size() > 0) {
  %>
      <table border="1" cellpadding="2">
      <tr>
      <td>TITLE</td>
      <td>PRICE</td>
      <td>QUANTITY</td>
      <td></td>
      </tr>
<%  // Scriptlet 4: display the books in the shopping cart
      for (int i = 0; i < shoplist.size(); i++) {
        Book aBook = shoplist.elementAt(i);
  %>
        <tr>
          <form name="removeForm" action="eshop" method="POST">
            <input type="hidden" name="position" value="<%=i%>">
            <input type="hidden" name="do_this" value="remove">
            <td><%=aBook.getTitle()%></td>
            <td align="right">$<%=aBook.getPrice()%></td>
            <td align="right"><%=aBook.getQuantity()%></td>
            <td><input type="submit" value="Remove from Cart"></td>
            </form>
          </tr>
<%
        } // for (int i..
  %>
      </table>
      <p/>
      <form name="checkoutForm" action="eshop" method="POST">
        <input type="hidden" name="do_this" value="checkout">
        <input type="submit" value="Checkout">
        </form>
<%
      } // if (shoplist..
    } // if (booklist..else..
  %>
  </body>
</html>
Listing 3-1

The E-bookshop Home Page index.jsp

First, index.jsp (as shown in Scriptlet 1) checks whether the list of books to be sold is available, and if it isn’t, it passes the control to the servlet, which then must initialize the book list. In a real online bookshop, the book list would be very long and kept in a database. Note that JSP doesn’t need to know where the list is kept. This is the first hint at the fact that application logic and presentation are separate. You’ll see later how the servlet fills in the book list and returns control to index.jsp. For now, let’s proceed with the analysis of the home page.

If Scriptlet 1 discovers that the book list exists, it copies it into the select control one by one (as shown in Scriptlet 2). Notice how JSP simply creates each option by writing to the out stream. When the buyer clicks the Add to Cart button after selecting a title and possibly changing the number of copies, the home page posts a request to the eshop servlet with the hidden parameter do_this set to add. Once more, the servlet takes care of updating or creating the shopping cart by instantiating the class Book for each new book added to the cart. This is application logic, not presentation of information.

Scriptlet 3 checks whether a shopping cart exists. index.jsp, being completely data-driven, doesn’t remember what has happened before, so it runs every time from the beginning. Therefore, it checks for the presence of a shopping cart even when the buyer sees the book list for the very first time.

Scriptlet 4 displays the items in the shopping cart, each one with its own form. If the buyer decides to delete an entry, index.jsp sends a request to the servlet with the hidden parameter do_this set to remove.

The sole purpose of the last two scriptlets is to close the curly brackets of ifs and fors. However, notice that the form to ask the servlet to do the checkout is only displayed to the buyer when the shopping cart isn’t empty. This is possible because Tomcat, when converting a JSP page into a Java servlet, processes all scriptlets together, without expecting each one of them individually to contain a complete block of code. HTML elements can then be enclosed within a Java block statement spanning two scriptlets.

If the buyer clicks the Checkout button, index.jsp will send a request to the servlet with the hidden parameter do_this set to checkout.

Finally, notice the use of the expression elements <%=i%>, <%=aBook.getTitle()%>, <%=aBook.getPrice()%>, and <%=aBook.getQuantity()%>. The first expression, <%=i%>, is the position of the book within the shopping cart. The other three are the execution of methods of an object of type Book, which the servlet instantiated for each new book added to the cart.

You’ve probably noticed that the address shown in the browser is http://localhost:8080/ebookshop/eshop. This is actually the address of the Java servlet that controls the application.

The E-bookshop Servlet

Listing 3-2 shows the source code of the servlet. In this section and in the following one, I will explain how the code works. The servlet ShoppingServlet.java represents the C (controller) component of the MVC design pattern.
package ebookshop;
import java.util.Vector;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;
import ebookshop.Book;
public class ShoppingServlet extends HttpServlet {
  public void init(ServletConfig conf) throws ServletException  {
    super.init(conf);
    }
  public void doGet (HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {
    doPost(req, res);
    }
  public void doPost (HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {
    HttpSession session = req.getSession(true);
    @SuppressWarnings("unchecked")
    Vector<Book> shoplist =
      (Vector<Book>)session.getAttribute("ebookshop.cart");
    String do_this = req.getParameter("do_this");
    // If it is the first time, initialize the list of books, which in
    // real life would be stored in a database on disk
    if (do_this == null) {
      Vector<String> blist = new Vector<String>();
      blist.addElement("Learn HTML5 and JavaScript for iOS. Scott Preston $39.99");
      blist.addElement("Java 7 for Absolute Beginners. Jay Bryant $39.99");
      blist.addElement("Beginning Android 4. Livingston $39.99");
      blist.addElement("Pro Spatial with SQL Server 2012. Alastair Aitchison $59.99");
      blist.addElement("Beginning Database Design. Clare Churcher $34.99");
      session.setAttribute("ebookshop.list", blist);
      ServletContext sc = req.getSession().getServletContext();
      RequestDispatcher rd = sc.getRequestDispatcher("/");
      rd.forward(req, res) ;
      }
    else {
      // If it is not the first request, it can only be a checkout request
      // or a request to manipulate the list of books being ordered
      if (do_this.equals("checkout"))  {
        float dollars = 0;
        int   books = 0;
        for (Book aBook : shoplist) {
          float price = aBook.getPrice();
          int   qty = aBook.getQuantity();
          dollars += price * qty;
          books += qty;
          }
        req.setAttribute("dollars", dollars+””));
        req.setAttribute("books", books+””);
        ServletContext sc = req.getSession().getServletContext();
        RequestDispatcher rd = sc.getRequestDispatcher("/Checkout.jsp");
        rd.forward(req, res);
        } // if (..checkout..
      // Not a checkout request - Manipulate the list of books
      else {
        if (do_this.equals("remove")) {
          String pos = req.getParameter("position");
          shoplist.removeElementAt (Integer.parseInt(pos));
          }
        else if (do_this.equals("add")) {
          boolean found = false;
          Book aBook = getBook(req);
          if (shoplist == null) {  // the shopping cart is empty
            shoplist = new Vector<Book>();
            shoplist.addElement(aBook);
            }
          else {  // update the #copies if the book is already there
            for (int i = 0; i < shoplist.size() && !found; i++) {
              Book b = (Book)shoplist.elementAt(i);
              if (b.getTitle().equals(aBook.getTitle())) {
                b.setQuantity(b.getQuantity() + aBook.getQuantity());
                shoplist.setElementAt(b, i);
                found = true;
                }
              } // for (i..
            if (!found) {  // if it is a new book => Add it to the shoplist
              shoplist.addElement(aBook);
              }
            } // if (shoplist == null) .. else ..
          } // if (..add..
        // Save the updated list of books and return to the home page
        session.setAttribute("ebookshop.cart", shoplist);
        ServletContext sc = getServletContext();
        RequestDispatcher rd = sc.getRequestDispatcher("/");
        rd.forward(req, res);
        } // if (..checkout..else
      } // if (do_this..
    } // doPost
  private Book getBook(HttpServletRequest req) {
    String myBook = req.getParameter("book");
    int    n = myBook.indexOf('$');
    String title = myBook.substring(0, n);
    String price = myBook.substring(n+1);
    String qty = req.getParameter("qty");
    return new Book(title, Float.parseFloat(price), Integer.parseInt(qty));
    } // getBook
  }
Listing 3-2

ShoppingServlet.java

As you can see, the init() method only executes the standard servlet initialization, and the doGet() method simply executes doPost(), where all the work is done. If you were to remove the doGet() method, you would effectively forbid the direct call of the servlet. That is, if you typed http://localhost:8080/ebookshop/eshop in your browser, you would receive an error message that says the requested resource isn’t available. As it is, you can type the URL with or without trailing eshop.

The highlighted line shows that I suppressed a warning. Normally, a warning tells you that something might be wrong. Therefore, it is not good to have spurious warnings, because they might distract you from noticing warnings you should fix. The use of @suppressWarnings is in general bad practice and encourages you to use a sloppy programming style. In this particular case, the compiler complained about the typecasting of a generic Object to a Vector, but I knew that the attribute ebookshop.cart was of type Vector<book>.

When you analyze index.jsp, you can see that it passes control to the servlet on four occasions, as listed here from the point of view of the servlet:
  1. 1.

    If no book list exists: This happens at the beginning, when the buyer types http://localhost:8080/ebookshop/. The servlet executes without any parameter, initializes the book list, and passes control straight back to index.jsp.

     
  2. 2.

    When the buyer clicks Add to Cart: The servlet executes with do_this set to add and a parameter containing the book description. Normally, this would be done more elegantly with a reference to the book rather than the whole description, but we want to keep things as simple as possible. The servlet creates a cart if necessary and adds to it a new object of type Book or, if the same book is already in the cart, updates its quantity. After that, it passes the control back to index.jsp.

     
  3. 3.

    When the buyer clicks Remove from Cart: The servlet executes with do_this set to remove and a parameter containing the position of the book within the cart. The servlet removes the book in the given position by deleting the object of type Book from the vector representing the cart. After that, it passes the control back to index.jsp.

     
  4. 4.

    When the buyer clicks Checkout: The servlet executes with do_this set to checkout. The servlet calculates the total amount of money and the number of books ordered, adds them as attributes to the HTTP request, and passes the control to Checkout.jsp, which has the task of displaying the bill.

     

More on E-bookshop

By now, it should be clear to you how the servlet is in control of the application and how JSP is only used to present the data. To see the full picture, you only need to see Book.java, the Java bean used to represent a book, and Checkout.jsp, which displays the bill. Listing 3-3 shows the code for Book.java that represents the M (model) component of the MVC design pattern.
package ebookshop;
public class Book {
  String title;
  float  price;
  int    quantity;
  public Book(String t, float p, int q) {
    title    = t;
    price    = p;
    quantity = q;
    }
  public String getTitle()         { return title; }
  public void   setTitle(String t) { title = t; }
  public float  getPrice()         { return price; }
  public void   setPrice(float p)  { price = p; }
  public int    getQuantity()      { return quantity; }
  public void   setQuantity(int q) { quantity = q; }
  }
Listing 3-3

Book.java

In a more realistic case, the class Book would contain much more information, which the buyer could use to select the book. Also, the class attribute title is a misnomer, as it also includes the author names, but you get the idea. Listing 3-4 shows the code for Checkout.jsp.
<%@page language="java" contentType="text/html"%>
<%@page session="true" import="java.util.Vector, ebookshop.Book" %>
<html>
<head>
  <title>E-Bookshop Checkout</title>
  <style type="text/css">
    body {background-color:gray; font-size=10pt;}
    H1 {font-size:20pt;}
    table {background-color:white;}
    </style>
  </head>
<body>
  <H1>Your online Bookshop - Checkout</H1>
  <hr/><p/>
  <table border="1" cellpadding="2">
    <tr>
      <td>TITLE</td>
      <td align="right">PRICE</td>
      <td align="right">QUANTITY</td>
      </tr>
<%
    Vector<Book> shoplist =
        (Vector<Book>)session.getAttribute("ebookshop.cart");
    for (Book anOrder : shoplist) {
%>
      <tr>
        <td><%=anOrder.getTitle()%></td>
        <td align="right">$<%=anOrder.getPrice()%></td>
        <td align="right"><%=anOrder.getQuantity()%></td>
        </tr>
<%
      }
    session.invalidate() ;
  %>
    <tr>
      <td>TOTALS</td>
      <td align="right">$<%=(String)request.getAttribute("dollars")%></td>
      <td align="right"><%=(String)request.getAttribute("books")%></td>
      </tr>
    </table>
  <p/>
  <a href="/ebookshop/eshop">Buy more!</a>
  </body>
</html>
Listing 3-4

Checkout.jsp

Checkout.jsp displays the shopping cart and the totals precalculated by the servlet, and it invalidates the session so that a new empty shopping cart will be created if the application is restarted from the same browser window.

Note that you could have included the checkout logic in index.jsp and made its execution dependent on the presence of the two totals. However, I wanted to show you a more structured application. It’s also better design to keep different functions in different JSP modules. In fact, I could have also kept the shopping cart in a separate JSP file. In real life, I would have certainly done so. In addition, I would have saved the styles in a Cascading Style Sheets (CSS) file rather than repeating them in all JSP sources. Finally, there is close to no error checking and reporting. You could easily crash this application. In a real case, you would add an error page as explained in the previous chapter.

Before we move on, you’ll certainly find it interesting to see the dynamic HTML page that actually reaches the browser after adding one item to the shopping cart (see Listing 3-5).
<html>
<head>
  <title>E-bookshop</title>
  <style type="text/css">
    body {background-color:gray; font-size=10pt;}
    H1 {font-size:20pt;}
    table {background-color:white;}
    </style>
  </head>
<body>
  <H1>Your online Bookshop</H1>
  <hr/><p/>
<form name="addForm" action="eshop" method="POST">
      <input type="hidden" name="do_this" value="add">
      Book:
      <select name=book>
<option>Learn HTML5 and JavaScript for iOS. Scott Preston $39.99</option>
<option>Java 7 for Absolute Beginners. Jay Bryant $39.99</option>
<option>Beginning Android 4. Livingston $39.99</option>
<option>Pro Spatial with SQL Server 2012. Alastair Aitchison $59.99</option>
<option>Beginning Database Design. Clare Churcher $34.99</option>
</select>
      Quantity: <input type="text" name="qty" size="3" value="1">
      <input type="submit" value="Add to Cart">
      </form>
    <p/>
<table border="1" cellpadding="2">
      <tr>
      <td>TITLE</td>
      <td>PRICE</td>
      <td>QUANTITY</td>
      <td></td>
      </tr>
<tr>
          <form name="removeForm" action="eshop" method="POST">
            <input type="hidden" name="position" value="0">
            <input type="hidden" name="do_this" value="remove">
            <td>Pro Spatial with SQL Server 2012. Alastair Aitchison </td>
            <td align="right">$59.99</td>
            <td align="right">1</td>
            <td><input type="submit" value="Remove from Cart"></td>
            </form>
          </tr>
</table>
      <p/>
      <form name="checkoutForm" action="eshop" method="POST">
        <input type="hidden" name="do_this" value="checkout">
        <input type="submit" value="Checkout">
        </form>
</body>
</html>
Listing 3-5

HTML Generated by index.jsp

Neat, isn’t it?

You now have in your hands the full code of a nontrivial Java/JSP application, but you still need to know how to make these four modules work together.

Summary

In this chapter, I described the application architectures suitable for web applications and provided the example E-bookshop to explain how the Model-View-Controller architecture works.

You then learned how to create a Servlet and a Class in the Eclipse IDE. It was necessary at this point because, with E-bookshop, we had reached the limit of what was reasonable to do without an IDE.

In the next chapters, I’ll introduce the Eshop project, which, in different versions, I will use to complete the description of JSP and to explain JSF and take you through the remaining functionality of JSP. To do that, I will use simple dedicated examples and the relevant aspects of the eshop application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.44.108