CS636 Class 20 Doc: Using DB from Webapp

hw 4 note: Pg 197: JSP error display and hints for fixes. Relevant to hw4 #5

Project 2 coming: pizza3 is available

We looked at pizza3's config, how to run it as client-server and web app

See pizza3/README and build.xml

Model 1 JSP: not covered in class, but discussed in this doc: Model1JSP.html

Bottom line: For this class, you can skip the Model-1 related material:

Guiding principle: We are doing MVC Model 2, which has a servlet to accept UI, but it is possible to live without servlets (except JSP servlets of course). That's "Model 1". Then everything for presentation is done in JSP, including interpreting incoming parameters.

Next challenge: Moving pizza1/music1 to the web container inside tomcat

We expect to get our BL+DAO code from pizza1 or music1 to execute inside the web container, i.e., in tomcat, but obviously the presentation layer has to be completely rewritten, a big job.

How can we start?  We need an absolutely minimal presentation code.

Hey, we already have it, in SystemTest!

We will get SystemTest to run from a servlet…The System.out.println output will show up in tomcat's log

Tomcat executes servlets in its own JVM. It uses the Java capability to load in additional classes and execute them.  Of course these classes have to follow certain rules for tomcat to know how call them. They have to provide methods doGet and/or doPost for tomcat to call when a HTTP request comes in with a URL that is recognizable as belonging to that servlet. 

When we execute ordinary Java programs, execution starts in main (SystemTest for example).  Tomcat itself has a main, but our servlets don’t.  Execution reaches our servlet code by a call from tomcat to doGet or doPost.

Here is a way to get our BL+DAO code from pizza1 or music1 to execute inside the web container, i.e., in tomcat, with no web UI at all.

See pizza3/src/cs636/music/presentation/web/SysTestServlet.java

One fix for this problem is to use a static initializer in say PizzaSystemConfig:

static {

    code that gets executed at class-load time

}

Then when the servlet calls PizzaSystemConfig.getAdminService() the first time, the class will be loaded and the static initializer run.  The class will stick around in memory because of its static fields.  So it won’t be reloaded again as further requests come in.

Another way, the one we’ll use, is to use the servlet’s init() method, which is called once at servlet class load (see Murach, pg. 161)

There is another technical detail: SystemTest reads a file, but a web app doesn’t know where it is in the filesystem, or this is not obvious anyway.  We need to put test.dat in the top-level deployment directory (say), and then ask the servlet software to convert its path for us.  See pg, 141 of Murach for code accessing a file from a servlet.

All transactions happen strictly inside service calls, so inside individual request cycles.  They can be concurrent, however, so we need to argue that they don’t interact badly.  Our stateless service layer helps with this. More on this later.

Of course we need to add the UI—use JSP to present HTML to the users via their browsers.

Pa2, pizza3: “MVC” approach, using a “dispatcher servlet”, doing decisions/business logic in Java, using JSP for display to user only. Model 2 (diagram, pg. 33)

Controller servlet --> View JSP

The --> is a request forward operation, done inside tomcat, so very fast

Forwarding a request: discussed, pg. 144, though not completely.

The forwarding action occurs inside the server, so there is no round-trip time back to the browser involved. The browser doesn’t know anything about it, and so the address bar in the browser doesn’t change either, never displaying the name of the .jsp being forwarded to. It gets the HTML generated by the .jsp when the response goes back.

Timeline: browser B uses URL for servlet S, which forwards to JSP J, which creates HTML response for browser B:

---*---------------------------**-------------------------------*---------
   B                           SJ                               B

   time--->

The request and response objects are forwarded, so for example, the servlet can attach attributes to the request and the JSP can use them. Similarly, the servlet can attach attributes to the session that are usable. Here is a picture, showing the servlet as an oval forwarding to the JSP shown as a rectangle. Of course the JSP is actually another servlet at runtime.

servlet to JSP diagramNote that the exceptions are usually due to calling the service layer, which we do in servlet code in MVC. So we don’t have to worry about handling exceptions in the JSP: it’s working with already-collected-in-memory data.

Practical Details

Needed libraries for JSPs: in WEB-INF/lib

JSP with EL: no libraries needed.  Note how basicjsp has no WEB-INF/lib directory. It has

Add.jsp  

1 + 2 + 3 = ${1 + 2 + 3}

JSTL, however, requires libraries

See discussion of JSTL libraries on pg. 271. All our needs are covered by the Core library with the two jar files you can see in pizza3 webapp, in WEB-INF/lib, that is, jstl-1.2.1.jar and jstl-api-1.2.1.jar.

Note that names of jar files can be misleading. What’s important is what classes are inside a jar file, not its name.  You can see the classes using the jar tool: “jar tf jstl-1.2.1.jar” for example.

Needed Setup in the JSP: none for JSP with just EL

start of JSP file: set up c: alias for core JSTL library:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

If you forget this, any <c:…> gets sent out as part of the response, causing no end of trouble.

Look at example JSP from pizza3

See includes of header and footer—look at header see own taglib, CSS linkage, script to support old browsers, shortcut icon for browser tabs, and image in header (same pizzapie image as icon)

<c:if  test=… >…</c:if>

<c:forEach…>

See <c:url for each URL: this is supporting URL-rewriting for session tracking.

JNDI and Connection pooling: see doc Using a Database from a Web App

Connection pooling is discussed in Murach, pp 464-469. It is important for web apps because they need Connections for such short periods of time that the Connection startup time with the database looks huge and would impact performance.  The Connection pool has hot standby Connections that the web app can borrow and return.

Connection pooling is provided by the DataSource JEE service.  We want one of these objects for each database in use, so three for our setup.

With a DataSource object, you can get a Connection by ds.getConnection(). A simple JDBC webapp can use this Connection normally, and must close it when done. That "close" operation doesn't actually close the connection, but rather puts it back in the pool for another request to use.

We want tomcat to set these up for us and provide refs to these objects—how does that work?

The app servers offer a JNDI service, another JEE service, that supports an object repository, i.e. a place to hold objects so that webapps can get them.  The objects are looked up by their JNDI names. For example, the DataSource object for our Oracle DB has JNDI name “jdbc/dbs2” in the part of the name space managed by tomcat, or full JNDI name “java:comp/env/jdbc/dbs2”. See http://en.wikipedia.org/wiki/Java_Naming_and_Directory_Interface for more info if interested.

We configure the entries in tomcat’s JNDI by using XML Resource entries in tomcat’s conf/context.xml or conf/server.xml. You see Resource elements with type and name attributes, for the type of object to hold and the name to use to look it up.  The other attributes specify parameters to the constructor or what setters to call, customizing the object.  Notably, the username and password needed for database access are held here, instead of in the app itself.

You need to edit context.xml!

Note that you need to edit your tomcat’s conf/context.xml as indicated in the doc, so that it will use your own DB accounts. 

Even a plain JDBC webapp like pizza3 can use JNDI lookup, using the code on the handout, assuming it is being executed in a servlet.

For webapps using JPA, we need to provide the DataSource object to the JPA provider by configuration, for its startup. Instead of username, password, jdbc URL, etc., we just need to provide one DataSource object.  So the lines in persistence.xml are changed to use a <non-jta-datasource> element.

When tomcat comes up, it reads context.xml and creates the DataSource objects. It needs access to the DB drivers to do this, so they have been put in tomcat’s lib directory.  A web app using a DataSource held in tomcat does not need its own driver jar files.

Once we are using a DataSource for the web app, we would also like to use it for client-server executions of our same project. We can do that by creating DataSource objects in our own code, as is done in StandaloneDataSourceFactory.java in cs636.pizza.config.

Threads and 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.

We start each transaction in the service layer, use the DAO once or more, then commit, all in one thread.

At transaction start, we get a Connection from the DataSource for the DB actions needed by the DAO calls. We hold the Connection in a local variable in the service layer during the transaction, and close it at commit. Local variables are private to the thread, so no concurrency problems will occur.


 

 

 

.