CS636 Class 21: hw5 available,  due Dec. 6 (Wed.)

Threads and JDBC Connections in a Web App as we have set it up

Each transaction is running in a Java thread, the same thread for the whole transaction and in fact the same thread for the whole request/response cycle, in tomcat’s JVM.

In pizza3 and music3, we are using a DataSource object to provide JDBC Connections by conn = dataSource.getConnection(). The DataSource is necessarily a thread-safe class, i.e., multiple threads can be trying to get new Connections concurrently without trouble.

We save the dataSource object as a field in the DAO, specifically in DbDAO of pizza3 and SalesDbDAO and CatalogDbDAO of music3.

At transaction start, a new Connection is pulled out of the pool by Connection connection = dataSource.getConnection(); Autocommit is turned off by connection.setAutoCommit(false), and the Connection is returned to service-layer caller, which is just starting one of its service calls that accesses the database.

The service-layer method puts the Connection in a local variable, which is always thread-private, and uses it for various calls into the DAO. It is a little impure to allow a JDBC class like Connection to be used in the service layer, but it's not domain data, so we are maintaining the important rule of a stateless service layer.

When the service-layer method is done with its action, it calls commitTransaction(conn), and in that call the Connection is closed, returning it to the pool.

Blow by blow, at request time:

If we start another transaction in the same request cycle, we'll get another Connection from the pool, but usually we have only one transaction in a certain request-response cycle. 

Last time: moving the system into the web container, using SysTestServlet, a special-case servlet

Two production servlets in pizza3:

You can use either model in music3 for an individual project. Partners are expected to use a DispatcherServlet, or two such servlets if you would like to show how this project could be implemented with two separate databases.

The pizza3 view pages:

These URLS “.../WEB-INF/jsp/...) are not used in JSPs of the app. Instead, all URLs (except the initial URL used to start the app) in the web app point to the servlet using xxx.html names, for example, in orderForm.jsp:

    <c:url var="orderPizzaURL" value="orderPizza.html" />

    <!--change to method="post" when development is done -->
    <form method="get" action="${orderPizzaURL}">

The use of c:url allows session tracking even for users who turn off cookies (and has another feature described later). We are assuming our users allow cookies, so this code could be simplified to

    <!--change to method="post" when development is done -->
    <form method="get" action="
orderPizza.html">  

This generates HTML with a URL of form xxx.html. This goes back to the browser where the user sees the form.

    <form method="get" action="orderPizza.html">

In web.xml: URL mapping for DispatcherServlet:

       <servlet-mapping>
              <servlet-name>DispatcherServlet</servlet-name>
              <url-pattern>*.html</url-pattern>           
       </servlet-mapping>

The submit of the pizza order form with action=orderPizza.html, apparently satisfies the url-pattern *.html, but we should check more carefully.

In more detail, worrying about the directory involved, since this is a relative URL.

This action=orderPizza.html goes back in the HTML of the response. The browser has used a URL like

http://localhost:8080/pizza3/orderPizza.html to get to the the order form page, so the browser uses

http://localhost:8080/pizza3/orderPizza.html to submit the form, and this is orderPizza.html relative to the pizza3 servlet context

This orderPizza.html satisfies the <url-mapping> of *.html, so the request goes to the DispatcherServlet

In the servlet (DispatcherServlet), the incoming URL is examined, and it determines what processing to do and forwards to the appropriate jsp. The browser never sees a URL in the jsp area--it's secret to the servlet.

The DispatcherServlet’s work is to handle the incoming request and determine what to forward to. The work for one action (one incoming URL) is

In DispatcherServlet, the work for one action (one incoming URL) is abstracted into a Controller object, that is, an object that implements the Controller interface:

package cs636.pizza.presentation.web;

import …

// Each controller does the guts of doGet/doPost
// via handleRequest declared here
public interface Controller {
     // return forward-to URL
     String handleRequest(HttpServletRequest request,
              HttpServletResponse response)
     throws IOException, ServletException;
}

For example, the order form has an OrderFormContoller that implements Controller. Its object (a singleton) is created at startup of DispatcherServlet. This Controller object then goes on to handle all the requests that are order form submissions.

In OrderFormController, handleRequest does the following:

--gets all sizes and toppings from the DB, using studentService ref provided at construction time

--attaches these sets to request attributes “allSizes” and “allToppings”

--also sets request attribute “numRooms” to 10

--return the String URL “/WEB-INF/jsp/orderForm.jsp”, which was provided at contruction time

All the incoming student-action requests get handled by DispatcherServlet, which looks at the URL and calls the appropriate controller. The controller Java code calls the service API to do its task and loads up some session and/or request variables with the results that need display to the user. Finally, the controller forwards the request to a URL which is usually a JSP to compose the HTML of the response, or sometimes the URL leads back to the servlet.

DispatcherServlet

We have one master servlet for student pages, DispatcherServlet, which calls various controllers

Servlet gets the actual URL by using request.getServletPath(), so it knows what Controller to call on.

We can make a table of cases:

Request URL                              Controller                             forward-to-URL (for “view” or further servlet processing)

/welcome.html           ---                         /welcome.jsp

/studentWelcome.html    StudentWelcomeController    /WEB-INF/jsp/studentWelcome.jsp

/orderForm.html         OrderFormController         /WEB-INF/jsp/orderForm.jsp

/orderPizza.html        OrderPizzaController        /WEB-INF/jsp/studentWelcome.html
                                                OR
/WEB-INF/jsp/orderForm.html for form resubmission

/orderReceive.html      OrderReceiveController      /WEB-INF/jsp/studentWelcome.jsp


Note that the URLs here are “servlet-context-relative”, so /welcome.html means .../pizza3/welcome.html, etc.

Here we see studentWelcome.jsp as the page displayed after the OrderFormController runs, and also after the OrderPizzaController runs successfully (student actually ordered something, not needing resubmission of form), and after the OrderReceiveController runs. This just means that the student welcome page is redisplayed originally when the student selects this service, again after they order a pizza, and again after they acknowledge receipt of pizza, showing them the changes to their collection of orders.

Note there are only two pages in the page flow for the student actions, ones generated by studentWelcome.jsp and orderForm.jsp. We already determined this in hw3--see the page flow diagram its solution

The complicated case is when a form is submitted with unusable input. For example, the user is trying to order Mushrooms as a topping, but meanwhile the admin deleted that topping. Then the user submits the form using URL orderForm.html, the DispatcherServlet does the validation, decides it failed, and forwards to URL orderForm.html, i.e., forwards to itself as a servlet. Then the DispatcherServlet is reentered (with the same request and response objects) and goes to the OrderFormController, and forwards to orderForm.jsp.

UI in general for a Collection of objects. Here the UI has to manage various collections of objects: student orders or a room, toppings, sizes, days, all orders. The pattern we use is to display the collection on the "main" page, and provide a link or form for additions and updates and deletions from the collection, causing redisplay of the main page to show the new collection. 

When the order form is completed successfully by the user, the servlet actually redirects to /studentWelcome.html instead of forwarding to it, to change the URL known to the browser, so that a refresh of the page does not re-POST the form, but rather only re-GETs the result page. A complete (long-winded) discussion is  in http://www.theserverside.com/news/1365146/Redirect-After-Post

AdminServlet

Note that there is another servlet for the admin pages, AdminServlet, with url-mapping:

       <servlet-mapping>
              <servlet-name>AdminServlet</servlet-name>
              <url-pattern>/adminController/*</url-pattern>
     </servlet-mapping>

Thus any URL like … /pizza3/adminController/xxx will be handled by this servlet

See in sidebar.jsp:

<c:url var="adminWelcomeURL" value="/adminController/adminWelcome.html" />

...

     <a href="${adminWelcomeURL}">Admin Service</a><br>

Note that the use of JSP include files increases the complexity of the system, so do without them unless you are an expert in JSP.

Here the URL in c:url starts with /, which means app-context-relative URL, a nice feature of c:url discussed on pg. 286. That means this URL turns into /pizza3/adminController/adminWelcome.html in the HTML, a doc-root-relative URL.AKA "relative to webapps directory" URL, covered on pg. 101.  (webapps is tomcat's document root as a web server.)   Since sidebar.jsp is included in several pages, an ordinary relative URL isn't useful.

You can drop the use of <c: url if you want, but then there is no concept of app-relative URLs. You can use instead the one line:

     <a href="/pizza3/adminController/adminWelcome.html">Admin Service</a><br>

but then it doesn't work under another webapp name, like pizza3a. Note that this HTML URL is also a document-root relative URL. But for this project, it is OK to assume the webapp name is known.

Either way, (with or without c:url), when the user clicks the “Admin Service” link, their request is handled by AdminController, and this sets the browser’s concept of current server directory to /pizza3/adminController, so relative URLs in the view JSPs work to stay in this area.

Example: in toppingView.jsp: <c:url var="toppingsURL" value="toppings"/>

<form action="${toppingsURL}" method="post">

---or alternatively just---

<form action="toppings" method="post">

Here "toppings" is a relative URL to the browser-known current directory /pizza3/adminController, so the full URL will be ... /pizza3/adminController/toppings, and fit the url-mapping of the AdminController.

As mentioned before, the AdminServlet is coded in a less structured way than DispatcherServlet. It doesn’t use Controllers, but we could still set up a table showing request URLs and forward-to targets: ADMIN_JSP_DIR="/WEB-INF/admin/"

Request URL                                                        forward-to-URL (for “view” or further servlet processing)
                                                                                 (assuming no errors)

/adminController/adminWelcome.html        ADMIN_JSP_DIR + "adminWelcome.jsp”

/adminController/toppings                 ADMIN_JSP_DIR + "toppingView.jsp”

/adminController/sizes                    ADMIN_JSP_DIR + "sizeView.jsp”   

/adminController/orders                   ADMIN_JSP_DIR + "orderView.jsp”

/adminController/days                     ADMIN_JSP_DIR + "dayView.jsp"

/adminController/initializeDB.html        ADMIN_JSP_DIR + "initializeDB.jsp"

 Note: There is no form re-submission here.