Kamis, 12 Februari 2009

Java Server Pages and JDBC Tutorial

Java Server Pages and JDBC Tutorial


There are many options available when implementing object-oriented designs. We have a range of programming languages we can use (e.g. Java, Visual Basic, Delphi, C++, C#, Cobol, …); a range of data management strategies (relational database (RDBMS), object-oriented database (OODBMS), files (text or binary), XML database, persistent objects); various “middleware” inter-connectivity (sockets, RMI, CORBA, DCOM, XML, HTTP, WAP, SOAP); and various kinds of user interface approaches (HTML-based, command-line, desktop GUI, virtual environment, mobile device).


In this tutorial we’ll learn how to built thin-client applications (HTML for the most part, though can be used for e.g. WML too) using Java Server Pages (JSPs). JSPs provide a server-side “scripting” language which contains (mostly static) presentation mark-up, with embedded dynamic processing logic expressed in the Java programming language. We’ll see how JSPs provide HTML-based user interfaces that are supplied to a browser running on a user’s machine via the HTTP protocol. We will use the Java DataBase Connectivity (JDBC) API to obtain and update data stored in a relational database (I’ll use MS Access in this tutorial, but its easy to use SQL Server, Oracle, Interbase etc too).

I’ve chosen JSPs as our implementation platform for several reasons:
• They provide a “nice” distributed object-based platform form learning basic DIS implementation strategies
• Many “nasty” DIS issues are handled for you (threading, complexities of synchronisation, distributed object creation etc)
• You can produce some nifty, platform-independent, web-based user interfaces quickly and (relatively) easily
• JSPs are straightforward to use, even with limited Java programming background. We’ll use basic constructs and not get into any particularly complex stuff.

I use JBuilder4 in this tutorial to implement the JSP examples. I also briefly explain how to run them using JDK1.3 and the Tomcat JSP server. You could use JBuilder3 to compile the JavaBeans code in the examples below, but will need to use Tomcat to run the JSPs. You can find another basic tutorial, including information on downloading JDK1.3 and Tomcat at:

http://developer.java.sun.com/developer/onlineTraining/JSPIntro/

The example code used in this tutorial is available off the CS392 class share:

http://kula.usp.ac.fj/class-shares/CS392

Download the video.ZIP file, and unzip it to a directory. If using Jbuilder 4 or 5, you can browse the directory structure and open projects. If using JDK1.3/Tomcat, you can use the DOS or LINUX command line to browse the directories, compile programs and deploy JSPs and class files (see the .bat files). To run these, you need to manually start Tomcat and an HTTP browser (e.g. IE5 or Netscape), then go to the URL http://localhost:8080/examples/jsp/video2/ to run them (see examples below).

How JSPs Work

JSPs are server-side files that contain a combination of (usually) HTML mark-ups plus embedded Java code. The mark-ups are rendered in the browser to provide the usual HTML-based user interfaces, while the Java code provides dynamic data look-up and update, as well as data processing logic. Often, Java objects called “JavaBeans” are used with JSPs to encapsulate data processing and user interface behaviour (more on these later…)

When a browser requests a JSP URL, the HTTP server the URL is requested from performs the following actions:
1. a HTTP GET or POST command is sent from the browser to the HTTP server hosting the JSP
2. the HTTP server determines a JSP has been requested and, if it’s the first request or the JSP source has been changed, compiles the JSP to a Servlet (another Java server-side technology, which is basically a HTTP server plug-in, just like a Java Applet is a browser (client) plug-in)
3. Once compiled, the HTTP server loads and runs the JSP’s servlet (a Java object)
4. The Servlet accesses databases/remote objects, does data formatting for output etc etc
5. HTML is returned to the requesting browser, where it is formated




JSP Basics

The following is a cut-down version of the customer_maintenance.jsp file. You can find this in video/customer maintenance JSP/src/video2 (appologies for the weird path – a Jbuilder4 peculiarity…). Open the project video/customer maintenance JSP/CustomerMaintenanceJSP.jpr in Jbuilder4, or use your favourite editor for JDK1.3. I have just included some basic JSP elements in this version here:



Some of the key parts of a JSP include:
• HTML content. This is “static” i.e. doesn’t change. The concept of a JSP is that it contains presentation mark-up (typically HTTP) and in this is embedded dynamic Java code
• Page directives. These tell the JSP server to do certain things with/for your JSPs. Common ones include:
o Importing Java APIs, JavaBean definitions e.g. <%@ page import=”java.util.*” %> is just like putting import java.util.*; at the top of a .java file.
o
• JavaBean identification. JavaBeans are very simple software components – Java objects – often used by JSPs to store data, encapsulate form processing and encapsulate database accesses. tells the JSP to create an object of type PackageName.ClassName, and idenfity it for access in the rest of the JSP page as “BeanName”. The scope tells the HTTP server when to throw this away. Value ‘page’ says create a new one every time this page is accessed. Value ‘session’ says create a new one only one for each user’s “session” (sequence of HTTP requests).
• Bean property access/update e.g. says to set the PropertyName value of Bean BeanName to Value.
• Java variables e.g. <%= BeanName.getPropertyName() %> gets the value of the PropertName property from a JavaBean object called BeanName.
• “Scriptlets”, basically arbitary Java code in the JSP. This is enclosed in <% and %> tags.

Running a JSP

The example programs use an MS Access database called “video.mdb” (in the Video.ZIP file). To run them you first need to set up an ODBC DSN name called “video” to point to this. To do this, go:
• Select Start||Settings|Control Panel on the Windows desktop
• Double-click ODBC Data Sources
• Click on Add
• Select MS Acess Drive, then Finish
• Set Data Source Name to video
• Click Select and choose the video.mdb file (you may have to wander around directories to find it with the Windows 3.1 file browser it has!)

Jbuilder4

Open the CustomerMaintenanceJSP.jpr project file (under video\customer maintenance JSP\). Your Jbuilder screen should look something like the following:



Select Project|Rebuild Project menu item. If you get errors, right-click on CustomerMaintenanceJSP.jpr and select Properties. Check the four properties (for Ouput, Backup, Working and Source) make sense for where you have unzipped Video.ZIP to. Change the start of them if necessary (mine are installed under C:\My Documents\java\video – this is unlikely to be the same place as you use!).

Run the program by selecting Run|Run Project. If you get an error, or nothing happens, right-click the CUstomerMaintenanceJSP.jpr project icon and check the Properties|Run tab. Check under the JSP/Servlet tab the file customer_maintenance.jsp appears (click the “…” button to set/reset it…)

All being well, your screen should now look like:



You can enter e.g. 1 for ID, click Find and, all being well, you should get some stuff displayed!

If you change a JavaBean’s source (.java) file, you need to stop the HTTP server and re-run it (click on the red box at the bottom left of the screen to stop it, then select Run|Run Project again).

JDK1.3/Tomcat

Download the tomcat installation ZIP file and unzip this to C:\tomcat. Follow the instructions with it to start it up:
1. Start a DOS command window
2. CD to C:\Tomcat
3. Set JAVA_HOME to where you have your JDK1.3 installation
4. Type bin\startup
5. A new DOS window should open with Tomcat http server messages displayed e.g.:



To check its running, open IE5 or Netscape and go to http://localhost:8080/. A pretty picture and text should appear. Note that Jbuilder4 starts a Tomcat session up itself (you’ll see the start-up messages for this appear whenever you run a JSP in Jbuilder4)…

You need to put files in two places for Tomcat to use them:

C:\Tomcat\webapps\jsp\examples\jsp\<> - for .jsp files
C:\Tomcat\webapps\jsp\examples\Web-inf\classes\<> - for JavaBean .class files

Change directory to video/customer maintenance JSP/. Type “compile” to have the required JavaBean files compiled for you (these live in src/video2). Type “run” to have files copied to the above directories.

To run the JSP, point your browser to: http://localhost:8080/examples/jsp/video2/

Note that Tomcat will automatically re-compile a changed JSP file. However, if you change and re-compile a JavaBean source (.java) file, you need to stop Tomcat (select its DOS window and go CTRL-C) and re-start it, as it can’t dynamically reload the changed Bean code.

What happens when you run a JSP? The following things occur:

1. Point browser to URL e.g. http://localhost:8080/examples/jsp/video2/customer_maintenance.jsp
2. HTTP GET request is sent by browser to the http server (localhost:8080 means the Tomcat server running on your machine)
3. The HTTP server asks its JSP engine to compile the requested JSP to a Java servlet (only if the JSP source has changed since last accessed by the HTTP server, or it’s the first time the JSP was requested)
4. Once compiled, the servlet is loaded by http server’s servlet engine and run
5. The servlet instantiates any JavaBeans it requires (i.e. Java objects)
6. The servlet returns HTML data to the requesting browser via http server



Its important to remember that JSPs are compiled on-the-fly to servlets. This can explain some of the weird error messages you get when starting a JSP (in Jbuilder4) or going to a JSP page in IE5/Netscape. For example, if I introduce a syntax error into the scriptlet code of a JSP e.g. add:

<% this is bad Java code; %>

I get the following result in Jbuilder4 (and same result in IE5/Netscape window if going to this JSP):



This can make debugging JSPs a little tricky. That’s why later on we’ll see that putting most of our Java code into JavaBeans associated with the JSP is good – its both easier to manage the code, reuse it and to debug it!

JavaBeans and JSPs

Things called “JavaBeans” are used to hold data in JSPs, particular when processing information entered by the user on a form. They are also often used to provide processing logic for the JSP. Basically a JavaBean is a very simple “component” object – one that has getXXX() and setXXX() methods for every “property” of the component. A Java system can find out, dynamically at run-time, all the properties of a JavaBean and get/set their values. So, for example, CustomerData is a JavaBean I have developed which holds information about a customer. It has getID()/setID(), getName()/setName() etc functions to allow the JSP to read/write these property values. Here is the OOD diagram for this JavaBean. Note it inherits common properties/functions from a PersonData class (so we can define e.g. Staff, Manager etc JavaBeans that are also Person specialisations):


Some of the Java code implementing this Bean (in video/Shared/video2/CustomerData.java) is shown on the right. JavaBean objects can also have any other Java function – we’ll see this used later for form processing (i.e. a processRequest() function).

Form Processing with JSPs

Data display (output) with JSPs is easy – we have HTML markups+Java code. How do we get input from the user???

With HTML-based user interfaces, the normal way is to use HTML forms. These are enclosed in
tags, and typically include the usual HTML tags (,

,

,
,

    ,
    , etc) plus marked-up text, along with tags for data entry (text fields, radio and check-box groups, list boxes, etc) and actions (buttons). When we click a button in an HTML form, the contents of the form are sent to an HTTP server using an HTTP POST request. The JSP can read the entered data which is stored by the HTTP server as named POST command parameters, using either the Request data structure provided by the HTTP server, or more commonly from one or more JavaBean objects the POST data is stored into.

    A (cut-down) version of the customer maintenance form is shown below:


    Key elements in a JSP form include:
    • HTML
    tag & other HTML content. Note the FORM tag has two attributes: type and action. Type says what HTTP request to send (normally POST), while action is a URL i.e. the thing that needs to handle this request on the server. In this example, it is the SAME JSP page. Later, we’ll see how we can give action a DIFFERENT JSP page to handle the POST request (which gives a multiple-page metaphor user interface for the user to interact with…)
    • Page directives and JavaBean identification (as before)
    • One or more page directives to set JavaBean properties. The most commonly used one is . This says to set all the JavaBean properties that match parameter values (i.e. data entered by the user on the form) sent by the POST command. We can set individual properties too e.g. says to set only the PropertyName property of bean BeanName to be the value of the PropertyName parameter sent with the HTTP POST command.
    • Java scriptlets and variables, that use the JavaBeans/HTTP POST request parameters
    • HTML FORM input types e.g. text = a text field. Fields are named so that we can access their values when the form is submitted to an HTTP server. The name of text fields, option groups etc is the HTTP POST parameter name we can read/set JavaBean properties to. For example, the Java line request.getParameter(“ID”) will return the ID value the user has entered on the form for a customer. The JSP script line (or property=”ID”) will set the CustomerData JavaBean’s ID property to this value. This is usually much more convenient than lots of request.getParameter(“…”) lines in your code! 
    • HTML FORM input action types e.g. submit means a button to submit the form to the server. These are named and given a unique value, so that when the form is submitted, the JSP can tell which button was pushed. For example, the Java line request.getParameter(“action”) will return “find” or “new” depending on which button was pressed.

    What happens when we first go the JSP form page shown above?

    When first displayed, the fields are blank, request parameter values blank and JavaBean properties also blank. When the user enters values in the text fields, the form is ready for submission.



    When the user clicks on one of the buttons, the browser sends a POST request to the HTTP server:



    When the JSP’s servlet is run, the line:



    sets the customer_data JavaBean’s properties to same-named form values i.e. does setID(), setName() etc to ID, name etc form text entry field values.

    The lines:





    tell the JSP what text field values/buttons to bind to in the request data stucture sent to HTTP server by the browser.

    The line:

    request.getParameter("action")

    gets the value of the POST parameter named “action” – in this case it returns “find”, which means the user clicked on the find button in the form.

    The line:

    request.getParameter(“ID”)

    returns 1, meaning the user entered 1 in the ID text field.

    The lines

    customer_data.getID(), .getName(), getAge()

    return 1, john, 23, being the values entered by the user in the ID, name and age fields.

    Other HTML Form Elements

    We say two kinds of HTML form elements above: input text fields and submit buttons. Other input elements include option lists, check-boxes, pop-up menus, radio button groups and so on.

    The following JSP shows examples of each kind of HTML form input type being used:





    <br>Input types example <br>

    Input types example







    <%@ page language="java" import="test.*" %>
    <%@ page import="java.util.*" %>




    <% if(request.getParameter("action") != null) { out.println("
    text1 = "+input_types.getText1());
    out.println("
    text2 = "+input_types.getText2());
    out.print("
    check1 = ");
    for(int i=0;iselect1 = "+input_types.getSelect1());
    out.println("
    select2 = "+input_types.getSelect2());
    out.println("
    radio1 = "+input_types.getRadio1());

    }

    %>

    Text fields






    Check boxes


    Apples

    Grapes

    Oranges

    Melons


    Option list (list box - 10 items shown at one time)




    Option list (pop-up menu)




    Radio buttons


    Apples

    Grapes

    Oranges

    Melons


    Submit button








    The following shows the InputTypes code used to store the results from these input element types. Note that a check box input element can hold multiple values, so we use an array of strings to hold the values checked by the user.


    package test;

    public class InputTypes
    {

    String text1 = "";
    public String getText1()
    { return text1; }
    public void setText1(String text1)
    { this.text1 = text1; }

    String text2 = "";
    public String getText2()
    { return text2; }
    public void setText2(String text2)
    { this.text2 = text2; }

    String check1[] = new String[] {};

    public String[] getCheck1()
    { return check1; }

    public void setCheck1(String [] check1)
    { this.check1 = check1; }

    String select1 = "";
    public String getSelect1()
    { return select1; }
    public void setSelect1(String select1)
    { this.select1 = select1; }

    String select2 = "";
    public String getSelect2()
    { return select2; }
    public void setSelect2(String select2)
    { this.select2 = select2; }

    String radio1 = "";
    public String getRadio1()
    { return radio1; }
    public void setRadio1(String radio1)
    { this.radio1 = radio1; }

    }


    Dynamic Content in JSPs

    How do we get dynamic content in a JSP page? I use a “data manager” JavaBean. In the example below, I use an implementation of the CustomerManager class we saw earlier from our video system OOD:



    When this JSP is run, two JavaBeans are instantiated by the HTTP servlet. CustomerManagerImp is used to select, insert, update and delete customers. CustomerData holds one customer’s details for use by the JSP. The CustomerManagerImp JavaBean may interact with a relational database (or other persistency mechanism, or even remote objects e.g. via CORBA or RMI) to look-up or update data.

    Note that the CustomerManagerImp bean scope is specified as session, NOT page. This means each user gets a different CustomerManagerImp object instantiated, but the same one is reused each time a form is submitted, whereas a new CustomerData is instantiated and properties set each time the form is submitted. There is no need to re-create the manager each time, as it’s the same for all data objects it manages. We want a different CustomerData object created for each submission so old property values are reset correctly.

    These are the kinds of input/output forms we can produce using data manager Beans:



    Recall our CustomerManager class from our video system OOD. This used the DataManager Service Object (i.e. Operating System service) to store/retrieve data. We will use a relational database to store our data in a persistent form. There are examples of VideoManager, CustomerManager, RentalManager etc in the video system JSPs.



    Some of the code in video/Shared/video2/CustomerManagerImp.java implementing our CustomerManager class is shown on the right hand side above. This contains select, insert, update, and delete functions. We could instead put all the code in these functions directly into our JSP between <% and %> tags. However, the big advantages of using a manager JavaBean object is that it cleanly encapsulates all access to ur database (OR: remote objects; files; XML; data cache; etc), is reusable in many different JSPs (and Java applications too), and it allows us to change the data manager implementation WITHOUT changing user interface & processing code in the JSP.

    JDBC API

    How do we read/write database information in Java? The standard approach is to use the Java Database Connectivity (JDBC) API (i.e. import java.sql.*). This is a Java implementation of the Open Database Connectivity standard (ODBC). We will use JDBC to run very simple Structured Query Language (SQL) commands on ODBC-compliant dastabases. We could also use native drivers for non-ODBC compliant databases or to improve performance, still accessing these via JDBC. We’ll use MS Access as our database, but we could use SQL Server, Interbase, Oracle etc if we wanted to. We’ll “hide” ALL JDBC calls in various data manager classes e.g. CustomerManager, VideoManager etc for the reasons given above. NEVER put JDBC commands directly in a JSP (though it is possible to do so…).

    I have defined a simple interface for accessing JDBC (in video/Shared/video2/MySQLConn.java). This is outlined below:



    The following code in video/Shared/video2/CustomerManagerImp.java uses this database connectivity class to run SQL commands to SELECT, INSERT etc data in our MS Access database:



    In selectCustomer(), we first run a query by calling db.selectQuery(). SELECT * from customer WHERE customer_id = <> says to get the row with ID equal to the one supplied by the caller (I assume you’re all very familiar with SQL from 222, 230 and 280…). We then check a row was actually found (rs.next() == true), and if not return null (no CustomerData). If one is found, we get each customer record row field value (getInt(“id”), getString(“name”), etc etc) and create a new CustomerData object (new CustomerData(id,name,…)).

    InsertCustomer() is easier – we just build an SQL INSERT command and call db.execute() to run it.

    Debugging JDBC commands from JSPs can be a bit tricky. I suggest if you have errors with your SQL commands, print them out by doing the following:

    <>

    try {
    eg. CustomerData c = customer_manager.selectCustomer(…);

    } catch (Exception e) {
    out.println(“
    Exception occurred in selectCustomer():
    ”);
    out.println(e.toString());
    }

    and in your problematic database function put e.g.

    try {
    sql = …
    db.executeQuery(sql);

    } catch (Exception e) {
    throw new Exception(“SQL command = ‘”+sql+”’; Error: “+e.toString());
    }

    This way you will see the SQL command and database error printed out for you…

    What happens when this JSP runs? The following outlines the basic steps:



    The POST command parameters are put into the CustomerData Bean, then the JSP runs a selectCustomer(customer_data.getID()) function. This returns null if no customer with that ID exists, else returns a new CustomerData object. The data in this CustomerData object can then be read and printed out to the user.

    The following lines show part of the processing code for handling the user action (i.e. which button clicked on):

    if(customer_data.getAction().equals("find"))
    {

    if(customer_data.getID() == 0)
    out.println("ENTER A CUSTOMER ID");
    else {
    CustomerData c2 = customer_manager.selectCustomer(MySQLConn.getInstance(),customer_data.getID());
    if(c2 == null)
    out.println("Customer with ID "+customer_data.getID()+" not found");
    else
    out.println("Found customer");

    if(c2 != null) {
    customer_data.setID(c2.getID());
    customer_data.setName(c2.getName());
    customer_data.setAge(c2.getAge());
    customer_data.setPassword(c2.getPassword());
    customer_data.setAddress(c2.getAddress());
    customer_data.setPhone(c2.getPhone());
    }
    }
    }

    The following lines handle displaying the found CustomerData properties in the HTML form fields:




    ID: 0) ? ""+customer_data.getID() : "" %>
    >


    Name: >



    Age: 0) ? ""+customer_data.getAge() : "" %>
    >



    Address:
    >



    Phone:
    >

    The value property for an HTML FORM INPUT field, if set, results in the value being displayed in the text field (or radio button/check box set, list box item selected etc).

    JSP Form Structure

    There are several ways we can design our JSP-based user interfaces. These are summarised below:



    The most basic is where we shove all code: presentation mark-up, processing logic and data management, into the JSP script itself. This is a bad way to do things for many reasons, but chief among them is that it gets unwieldy for all but the most trivial examples.

    The second approach has HTML and Java processing/data management code in the JSP, with JavaBeans to hold data e.g. POSTed form content. This is slightly better, though putting processing logic and data management code (i.e. JDBC etc calls) into the JSP itself is bad practice. It makes the JSP and associated code hard to reuse and ties the presentation and processing logic to particular data management strategy, which may change during development.

    A better approach is to have the JSP responsible for mark-up and form processing, with Beans for both holding and managing data (i.e. CustomerManager+CustomerData etc).

    The “best” approach, however, is generally accepted to be one where the JSP holds solely HTML mark-up and Java code to access Bean content, with a Bean (or servlet) responsible for handling screen processing logic, typically making use of other Java classes. For example, we might have customer_maintenance.jsp + CustomerInterface.java (bean that does form processing logic) + CustomerManager.java (does DB access etc) + CustomerData (holds individual customer data).

    From here on I’ll use the last approach. Here is an example of the revised customer maintenance facility using this approach. The customer_maintenance2.jsp (in video/customer maintenance JSP/src/video2/) holds only HTML mark-up and JSP Java code to read JavaBean properties and call JavaBean functions. The CustomerInterface.java class provides processing logic for adding, updating, deleting and finding customers. This uses the CustomerManager/CustomerData classes which provide customer data management and representation respectively.



    Here is the JSP code from customer_maintenance2.jsp:




    <br>Customer Maintenance <br>

    Customer Maintenance







    <%@ page import="video2.*" %>
    <%@ page import="java.util.*" %>







    <% customer_interface.processRequest(customer_data); %>

    <%= customer_interface.getMessage() %>





    ID: 0) ? ""+customer_data.getID() : "" %>
    >


    Name: >



    Age: 0) ? ""+customer_data.getAge() : "" %>
    >



    Address:
    >



    Phone:
    >


















    When posted, the form content is processed not by the JSP script but by the CustomerInterface.processReqest() function. Part of this code is shown below:


    Below is an example of the code in the “action handlers”. These basically correspond to the addCustomer(), updateCustomer() etc. functions in CustomerInterface from our OOD diagram…

    public void doFind(CustomerData customer_data)
    {
    if(customer_data.getID() == 0)
    setMessage("ENTER A CUSTOMER ID");
    else {
    try {
    CustomerData c2 = customer_manager.selectCustomer(LConn.getInstance(),customer_data.getID());
    if(c2 == null)
    etMessage("Customer with ID "+customer_data.getID()+" not found");
    else
    etMessage("Found customer");
    if(c2 != null) {
    stomer_data.setID(c2.getID());
    customer_data.setName(c2.getName());
    customer_data.setAge(c2.getAge());
    customer_data.setPassword(c2.getPassword());
    stomer_data.setAddress(c2.getAddress());
    customer_data.setPhone(c2.getPhone());
    }
    } catch (Exception e) {
    etMessage("Can't do selectCustomer() - error: "+e.toString());
    }
    }
    }

    When we run this JSP, the following interactions occur:



    The JSP receives a POST command, which is processed by the compiled servlet for the JSP. The CustomerIntertface.processRequest() function is called, which then calls CustomerManager.findCustomer() etc. The JSP’s servlet then reads values from the CustomerData bean and put them in the HTML FORM fields for the user.

    Video Search Example #1

    Let’s look briefly at one more JSP example – the customer searching for videos. There are two versions of this – one where the user has a single JSP used for all searching tasks, and another where a “multiple page” metaphor is used (different JSPs for entering search details, seeing search results and seeing video details). Use video/video search JSP/VideoSearchJSP_2.jpr (first version) and video/video search JSP/VideoSearchJSP3.jpr (second version). For your information there is a VideoSearchJSP.jpr, but that includes all the processing login in the JSP script – the other versions use a VideoInterface.java Bean to encapsulate the form processing logic. The first version of the video search facility looks something like this when run it:


    The JSPs and Beans used here are structured as follows:



    The user firstly logs in by supplying user name and password. A CustomerManager is used to look up these details and the returned CustomerData’s properties compared to those entered on the form. Normally we’d then either 1) forward this request to a secure (HTTPS) server and/or generate a session “certificate”, passed onto the subsequent JSPs to validate all requests sent from them to the server (I haven’t bothered to do this in customer_login2.jsp or video_search2.jsp). The video_search2.jsp JSP script is then “forwarded” to (run) by customer_login2.jsp. When the user enters video title part/category and clicks “find”, the VideoInterface.java Bean’s processRequest() method works out a video search is to be done. This calls VideoManaher.findVideos() which returns a Vector (i.e. list) of VideoData objects that match the selection criteria. The video_search2.jsp iterates (loops through) this list, displaying information about each video found.

    Here is some of the video_search2.jsp code used in this example:

    Video Search


    <%@ page language="java" import="video2.*" %>
    <%@ page import="java.util.*" %>



    <% video_interface.processRequest(request.getParameter("action"),video_data); %>
    <%= video_interface.getMessage() %>


    <% if(video_interface.getVideo() != null) { out.println("ID: "+video_interface.getVideo().getID()+"
    ");
    out.println("Name: "+video_interface.getVideo().getTitle()+"
    ");
    ...
    %>

    ...

    If video_interface.getVideo() is not null, this means a “details” request was sent (the user asking for a particular video’s full details) and these are printed. The code:

    Enumeration e = video_interface.getVideos().elements();
    while(e.hasMoreElements())
    {
    VideoData video = (VideoData) e.nextElement();
    … do stuff with video object …
    }

    is used to step through each item in the Vector of videos looked up in the database. For each video, we generate HTML OPTION tags for the list box selection element.

    Here is some of the code in VideoInterface.java used to process the user’s requests:

    public class VideoInterface
    {
    private VideoManager video_manager = new VideoManagerImp();
    public void processRequest(String action, VideoData video_data)
    {
    if(action.equals("Search"))
    doFindVideo(video_data);
    else if(action.equals("Details"))
    doVideoDetails(video_data);
    }
    private Vector videos = new Vector();
    public void doFindVideo(VideoData video_data)
    {
    if(video_data.getTitle() == null)
    setMessage("Enter a title value");
    else
    {
    try {
    videos = video_manager.selectVideo(MySQLConn.getInstance(),
    video_data.getTitle(),video_data.getCategory());
    setMessage(videos.size()+" videos found...");
    } catch (Exception e) {
    setMessage("Error selecting videos: "+e.toString());
    }
    }
    ...

    In the VideoManagerImp.java Bean, the selectVideos() function is similar to selectCustomer() that we’ve seen before, except that it can return more than one object – hence it returns a Vector type (we could use an array too, but Vectors can have any size i.e. are dynamic arrays, which are more convenient to handle, I find). Here is the code from VideoManagerImp.findVideos():

    public Vector selectVideo(MySQLConn db, String title_part, String acategory) throws Exception
    {
    String query = "SELECT * FROM video WHERE title LIKE '%"+title_part+"%'";

    if(!acategory.equals(""))
    query = query+" AND video.category = '"+acategory+"'";

    ResultSet rs = db.executeQuery(query);

    Vector result = new Vector();

    while(rs.next()) {
    int id = rs.getInt("id");
    String title = rs.getString("title");
    String category = rs.getString("category");
    float cost = rs.getFloat("cost");
    int nights = rs.getInt("nights");
    String rating = rs.getString("rating");
    int num_copies = rs.getInt("num_copies");


    result.addElement(new VideoData(id,title,category,cost,nights,rating,num_copies));
    }

    rs.close();

    return result;
    }

    We first built up a SELECT statement of the form SELECT * from video WHERE title LIKE ‘%…%’ AND category = ‘…’ i.e. find all videos whose title contains the title_part string and whose category (if one is supplied) is equal to acategory. We then loop through the list of result set rows returned by the database, creating VideoData objects and adding them to our result Vector data structure. Simple, huh?? :-)

    Video Search Example #2

    An alternative video search facility is shown below. This uses a “multiple page” metaphor i.e. multiple, different HTML pages/JSPs vs. the same format HTML page/JSP as the previous example. This video search facility is functionally equivalent to the previous one, but has a different “look and feel” for the user.


    The key component interactions for this example are illustrated below. With this version of the video search facility, each JSP specifies another JSP to handle its form processing i.e. data entered on the video_search3.jsp form is processed by video_search4.jsp and video_search4.jsp’s form data is processed by video_search5.jsp.



    The code for video_search3.jsp is shown below. This provides the user with a text field to enter video title part and select from a pop-up menu a video category (the default being blank, or any category).A single submit button posts this HTML form to the HTTP server, with the
    tag indicating that the video_search4.jsp script be used to process the form.




    <br>Video Search <br>

    Video Search







    <%@ page language="java" import="video2.*" %>
    <%@ page import="java.util.*" %>



    Part of title:
    Category:










    The code for video_search4.jsp is shown below. Note this uses the SAME VideoInterface JavaBean as video_search3.jsp and the previous search facility, video_search2.jsp! Only the presentation has changed, not the processing logic for this version of the search facility. Note the use of a HTML hypertext link () to go to video_search5.jsp to process the user request (show selected video details), rather than an OPTION list as used in video_search2.jsp (though we could change this to use an option list too, if we wanted too). This code produces HTML of the form:

    …video name…




    <br>Video Search <br>

    Video Search






    <%@ page language="java" import="video2.*" %>
    <%@ page import="java.util.*" %>







    <% video_interface.processRequest(request.getParameter("action"), video_data); %>

    <%= video_interface.getMessage() %>




    <% Enumeration e = video_interface.getVideos().elements(); while(e.hasMoreElements()) { VideoData video = (VideoData) e.nextElement(); out.println(video.getTitle()+"Details
    ");
    }
    %>






    Another Search





    Debugging JSPs – Some Techniques

    JSPs and their associated JavaBeans can be a real pain to debug. This is because the JSPs are compiled on-the-fly to a servlet. Tracking down where an error is occurring can be a bit of effort. JBuilder 4 has some debugging support built-in, but this does’t appear to work very well with the Tomcat that comes with it. I don’t know if Jbuilder 5 is any better – it may allow tracing into JSP and JavaBean code which will help a lot.

    Let’s look at a few common errors that can occur when using JSPs and associated JavaBeans:
    1. syntax error in JSP
    2. wrong name/class for JavaBean declaration
    3. NullPointerException in JSP
    4. NullPointerException in JavaBean
    5. SQL Exception in JavaBean

    1. Syntax Error in JSP

    Adding:

    <% This is bad stuff; %>

    looks something like the following when the compiler detects it in Jbuilder/IE5:






    The Tomcat engine has generated a Servlet source file and is trying to compile it. It should be relatively easy to track down the JSP source file line the error is occurring on. I find doing a Find in the text editor I’m using is often the quickest way!

    2. Wrong name/class for JavaBean declaration

    Example:



    This can produce a real weird error message (LHS) if wrong name is used (as shown below). If you see names appearing that you don’t think you’ve used, look closely at your Bean/other declarations…



    Using Tomcat and JDK1.3 rather than Jbuilder, you may get an error saying the class can’t be located because you haven’t put it in the right place (JavaBean .class files go in e.g. c:\tomcat\webapps\examples\Web-inf\classes\<>, whereas the JSP files go in …\examples\jsp\<>)

    3. NullPointerException in JSP

    This is sometimes in the JSP itself; somes in the JavaBean its using (and the JSP is catching the exception). Example:



    was generated by:

    <% customer_interface = null; customer_interface.processRequest(customer_data); %>

    in the JSP 

    To find out where NullPointer (and other) exceptions are occurring, I do the following:
    1. Add System.out.println(“*** HERE1”); etc debugging “traces” to my JSPs/JavaBeans
    2. Add try { … } catch (Exception e) { System.out.println(“*** Error … “+e.toString()); to my JSPs/JavaBeans

    System.out.println() messages go to the Tomcat output screen (the bottom pane in Jbuilder; a DOS window if using JDK1.3/Tomcat):



    Was generated by:

    <% try { System.out.println("*** HERE1"); customer_interface = null; System.out.println("*** HERE2"); customer_interface.processRequest(customer_data); System.out.println("*** HERE3"); } catch (Exception e) { System.out.println("Caught: "+e.toString()); } %>

    4. NullPointerException in JavaBean

    I find the same approach works for these. For example, I comment out the constructor in CustomerInterface.java:

    private CustomerManager customer_manager; // = new CustomerManagerImp();

    and we now get (when doing a Find customer):



    I find this by adding tracing (and try+catch, if it wasn’t there) to the doFindCustomer() method:

    public void doFind(CustomerData customer_data)
    {
    System.out.println(“*** HERE1”);
    if(customer_data.getID() == 0)
    setMessage("ENTER A CUSTOMER ID");
    else {
    try {
    System.out.println(“*** HERE2”);
    CustomerData c2 = customer_manager.selectCustomer(MySQLConn.getInstance(),customer_data.getID());
    System.out.println(“*** HERE3”);


    }

    5. SQL Exception in JavaBean

    Basically can be found the same way as above. I also find printing out the SQL command indespensible. Just make sure you do this BEFORE running the SQL command :

    public synchronized CustomerData selectCustomer(MySQLConn db, int ID) throws Exception
    // locate customer by ID value
    {
    System.out.println(“*** selectCustomer() SQL = “+"SELECT * FROM customer WHERE customer.id = "+ID);

    ResultSet rs = db.executeQuery("SELECT * FROM customer WHERE customer.id = "+ID);

    if(rs.next()) {


    }

    6. Using the Jbuilder Debugger

    A big advantage of using Jbuilder is the debugger. You can break-point lines, step through lines and evaluate expressions at run-time, without having to add code to print things out (like with JDK):



    Debugged processes run quite slow but it’s a good way to track down things that aren’t working properly.

    Here’s an example of debugging a JSP using breakpoint + evaluation expression:


Tidak ada komentar:

Posting Komentar