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
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
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.
Finally, it is important to check the methods init and destroy in a Servlet.
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.
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?
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 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
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
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>.
- 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.
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.
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.
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
Book.java
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.
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.