CHAPTER 11

image

Custom Tag

This chapter will demonstrate how to create custom tags and use them in JSPs. This will require a more detailed explanation of how tags work, as well as covering new topics such as XML and tag libraries. The database access classes (created in Chapter 10) will be used in the server-based application to insert, display, and delete information from a database. We will also demonstrate how the MVC architecture makes incorporating these functions immensely easier.

At the end of this chapter, you should understand:

  • XML
  • Tag libraries
  • Tag handlers
  • URI
  • The Web Deployment Descriptor
  • Arrays

At the end of this chapter, you should be able to:

  • Create and use custom tags
  • Create and use custom visual components
  • Access a database from a server-based application

Tags

JSTL and JSP tags are very easy to use. Just as driving a car doesn’t require knowing how an internal combustion engine works, using a tag does not require understanding how tags work. This is precisely how tag creators meant it to be! Tags were created so that page designers can easily invoke complex functions. In the previous examples, however, the number of bean tags required was quite large and beyond what a page designer should be required to know. Custom tags will be used to eliminate this problem by further simplifying what the page designer must code. However, creating a tag requires a deeper understanding how tags work.

Tags actually invoke a type of Java class called a “tag handler. Tag handler classes are usually defined as a subclass of either the TagSupport or BodyTagSupport classes. The examples in this chapter will define tag handlers as subclasses of TagSupport. As the TagSupport name implies, the tag handler will inherit many variables and methods that do much of the “tag work.”

As mentioned earlier, JSP and JSTL tags come with RAD. What this means is that RAD ensures that the Java classes (i.e., the tag handlers that perform the tag functions) are accessible to the JSPs. For example, the tag handlers for JSP tags are stored in a file that RAD will automatically check when the JSP is run. This means that to implement a JSP tag (like the include tag) the programmer simply inserts the tag into the source code. RAD will find the correct tag handler class.

JSTL tags are not as simple. When a JSTL tag is added, RAD not only inserts the tag into the source code but also inserts a taglib (tag library) directive. The directive identifies the file (i.e., tag library) that contains the tag definition. The tag definition specifies which tag handler class should be invoked for the tag. For instance, when the JSTL if tag was added to the JSP, RAD added the following taglib directive:

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

The URI (Uniform Resource Identifier) value can be an actual file within the project such as /WEB-INF/tls/TNT.tld or an alias. In this chapter, you will create a folder named tls in WEB-INF and then, within tls, a tag library file called TNT.tld. A tag library URI (i.e., an alias) of http://www.tnt.com/taglib will then be created and associated with /WEB-INF/tls/TNT.tld. This association is defined in a project file called the Web Deployment Descriptor.

Notice that the taglib directive also defines a prefix of c for the JSTL tags. This means that when a JSTL tag (that is defined in the jstl/core tag library) is inserted in the page, the JSTL tag keyword must begin with the letter c followed by a colon. In other words, the prefix identifies which directive the server should use to locate the tag library associated with this tag.

In fact, RAD inserted the following JSTL tags when the if tag was added to the JSP:

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

The actual JSTL tag keyword is if but notice that it is preceded by c:. So, in this example, the c: tells the server that the tag library is located at http://java.sun.com/jsp/jstl/core. The server then goes to the Web Deployment Descriptor to get the actual location of the tag library.

Got it? Let’s recap. When the server encounters a JSP tag in the page, the server:

  • A.  Reads the tag prefix
  • B.  Within the JSP, finds the tag library directive associated with the tag prefix
  • C.  Using the directive’s URI, goes to the Web Deployment Descriptor and retrieves the tag library file name and location
  • D.  Goes to the taglib file and retrieves the name and location of the tag handler class associated with the tag
  • F.  Runs the tag handler class

With the if tag, the tag handler evaluates a condition. If the condition is true, the body of the tag will be embedded into the response object. For example, if the body contained the text “Yowser!” and the condition was true, the text “Yowser!” would be embedded in the page and appear in the browser.

Who cares? Well, we do. We need a simple tag to create and populate the Employee bean from the JSP fields. In addition, we are also going to create a tag that creates a specialized state choice field that limits the user to only valid state abbreviations. By creating a state field tag, we will be able to use it on multiple JSPs rather than defining a state choice field for each JSP. More important, if a state must be added to or deleted from the list, only the tag handler will have to be changed, not every JSP that displays the state value. Finally, the application will be modified to display the tax amount and gross salary for an employee on the same page as all the other employee information.

Creating a Custom Tag

As mentioned, we will create a custom tag (getEmp) to replace the following bean tags in EnterEmpInfoJSP:

<jsp:useBean id="EmpBean" class="c9java.Employee" scope="request">
<jsp:setProperty name="EmpBean" property="empStreet"
                    param="streetAddrTF" />
<jsp:setProperty name="EmpBean" property="exemptions" param="exmpDDM" />
<jsp:setProperty name="EmpBean" property="empState" param="stateTF" />
<jsp:setProperty name="EmpBean" property="empNum" param="empNumTF" />
<jsp:setProperty name="EmpBean" property="empName" param="empNameTF" />
<jsp:setProperty name="EmpBean" property="empZip" param="zipTF" />
<jsp:setProperty name="EmpBean" property="payRate" param="hPRTF" />
<jsp:setProperty name="EmpBean" property="empCity" param="cityTF" />
</jsp:useBean>

We will do this by creating:

  • A tag handler class called CrtEmpBean that is a subclass of TagSupport. CrtEmpBean will perform the same functions that the bean tags did (i.e., create and populate an Employee bean). CrtEmpBean will use the EmpExtractor class to create the Employee object and then define the Employee object as a Java bean with a scope of request.
  • A folder called tls (tag libraries) in WEB-INF.
  • Within tls, a tag library file called TNT.tld with an entry to associate the custom tag getEmp and the tag handler class CrtEmpBean
  • An entry in the Web Deployment Descriptor to define the URI http://www.tnt.com/taglib and tie it to /WEB-INF/tls/TNT.tld

We will then use the custom tag in EnterEmpInfoJSP, by inserting:

  • A taglib directive that defines the prefix TNT and ties it to the URI http://www.tnt.com/taglib
  • The custom tag with the prefix TNT (<TNT:getEmp/>)

Tutorial: Creating a Custom Tag

Let’s try it

  1. In the TutorialsWeb project, click on the WebContent folder to select it.
  2. Click File, New, Folder, specify c11 as the new folder name, and click the Finish button.
  3. From the WebContent/c9 folder, copy EnterEmpInfoJSP.jsp and EnterEmpInfoForm.html into c11.
  4. In c11/EnterEmpInfoForm.html, ensure that the form action is specified as EnterEmpInfoJSP.jsp. If it isn’t, change it to EnterEmpInfoJSP.jsp.
  5. In TutorialsWeb/Java Resources/src, create a folder called c11.
  6. From c9java, copy Employee and EmpExtractor to c11.
  7. In src/c11, create a Java class called CrtEmpBean with a super class of TagSupport and no method stubs.

The following source code will be inserted in CrtEmpBean and displayed in Page Designer:

package c11;
import javax.servlet.jsp.tagext.TagSupport;
public class CrtEmpBean extends TagSupport {
}

Although the generated code is not very impressive, the variables and methods inherited from TagSupport will make this class function as a tag. However, at least one inherited method has to overridden and coded to perform the needed application functions.

The Tag Handler

As mentioned, CrtEmpBean inherits many methods from TagSupport. We will focus on the doStartTag and doEndTag methods that are inherited from TagSupport. It was stated earlier that when the tag is encountered in the JSP, the server runs the associated tag handler class. Specifically, when the start tag is encountered, the server runs the doStartTag method and when the end tag is encountered, the doEndTag method is run.

In the example, we want the doStartTag method to:

  • A.  Run EmpExtractor’s getEmployeeInstance to create an Employee object from the request
  • B.  Define the returned Employee object as a bean with a scope of request

Several things will be needed to do this. First, private variables of type Employee and EmpExtractor are required. Second, the HttpServletRequest class needs to be imported into CrtEmpBean. This is required because getEmployeeInstance is expecting an HttpServletRequest, but the request object is of type ServletRequest. So, the ServletRequest object must be cast as an HttpServletRequest. Finally, we will be using the ever-helpful PageContext object (provided by the server) to get the request and define the Employee object as a request bean (or, said another way, define the Employee object as an attribute of the request).

The code to get the request object is:

pageContext.getRequest()

Because the returned request must be cast into an HttpServletRequest, this statement should be preceded with the following to cast the request:

(HttpServletRequest)

This results in:

(HttpServletRequest)pageContext.getRequest()

Then the HttpServletRequest needs to be passed to EmpExtractor. Do this by embedding the above statement in the method call as follows (where ee is the EmpExtractor variable):

ee.getEmployeeInstance(
(HttpServletRequest)pageContext.getRequest());

To define the returned Employee object as a request bean, we need to get the request again (using the page context’s getRequest method again). Then use the request’s setAttribute method to define the employee object as a bean called EmpBean. The statement to do that is as follows (where emp is the Employee variable):

pageContext.getRequest().setAttribute("EmpBean", emp);

Tutorial: Defining the Tag Handler Class

Time to define the tag handler class:

  • 1.  In CrtEmpBean, add the following import statement after the existing import statement:
    import javax.servlet.http.HttpServletRequest;
  • 2.  In CrtEmpBean, add the following statements to create a class Employee variable called emp and both an EmpExtractor object and EmpExtractor class variable called ee.
    private Employee emp;
    private EmpExtractor ee = new EmpExtractor();
  • 3.  In CrtEmpBean, click Source, then Override/Implement Methods. . .
  • 4.  At the Override/Implement Methods window, click on the doStartTag() checkbox to select it.
  • 5.  Make sure the insertion point option is After ‘ee” and click the OK button.

RAD creates a doStartTag method. Notice the return statement. Even though we are overriding the superclass’ doStartTag method (to create and populate the Employee bean), the superclass’ doStartTag method is still executed. This is because the superclass’ doStartTag method performs many functions we still want to occur. For instance, the doStartTag method returns a value indicating success or failure of the method. This still must occur for the tag to work. Therefore, the superclass’ doStartTag method is executed and its return value is returned as our doStartTag method’s return value.

  • 6.  Before the return statement, add the following two statements to create the Employee object, populate its properties from the data in the request, and define the Employee object as a bean called EmpBean:
    emp = ee.getEmployeeInstance((HttpServletRequest)pageContext.getRequest());
    pageContext.getRequest().setAttribute("EmpBean", emp);

    The code should look like the following:

    package c11;
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.TagSupport;
    import javax.servlet.http.HttpServletRequest;
    public class CrtEmpBean extends TagSupport {
     private Employee emp;
     private EmpExtractor ee = new EmpExtractor();
     public int doStartTag() throws JspException {
                 emp = ee.getEmployeeInstance((HttpServletRequest)
     pageContext.getRequest());
                 pageContext.getRequest().setAttribute("EmpBean", emp);
                 return super .doStartTag();
     }
    }
  • 7.  Save CrtEmpBean.

Defining a Tag

The tag handler class (CrtEmpBean) has been created but the tag has not yet been defined. A tag is defined in a tag library. A tag library is a file with an extension of tld (tag library descriptor) that contains XML (Extensible Markup Language). XML is fast becoming the glue that holds the Internet together. XML is a markup language just like HTML is a markup language. However, HTML is limited to defining Web pages. XML can be used to define any type of information: data, documents, file locations, etc. Really, XML is a language that allows a programmer to define a language. However, we will be using XML in a much more limited capacity.

In the case of a tag library, the server expects the XML to identify a tag and its associated tag handler class. There are other optional XML statements and we will look at one of these later in the chapter. The server also requires that the tag library file (of type tld) be in the WEB-INF folder.

Tutorial: Defining a Tag

Let’s define a tag:

  • 1.  In the Project Explorer, expand the WebContent folder and select WEB-INF.
  • 2.  Click on File, New, and then Folder.
  • 3.  At the New Folder window, specify tls as the Folder name.

The folder tls should appear in the Enterprise Explorer and be selected.

  • 4.  Click on File, New, and then File. (If File isn’t an option, select Other, expand the Simple option, select File, and then click the Next button.)
  • 5.  In the file name, specify TNT.tld and click the Finish button.

RAD will display the empty file.

  • 6.  Enter the following XML:
    <taglib>
          <tag>
                  <name>getEmp</name>
                  <tagclass>c11.CrtEmpBean</tagclass>
          </tag>
    </taglib>

This defines the tag (getEmp) and the tag handler (c11/CrtEmpBean) that will be run by the server when the tag is encountered.

  • 7.  Save TNT.tld
  • 8.  In EnterEmpInfoJSP source code, add the following taglib directive before the existing JSTL core taglib directive:
    <%@taglib uri="/WEB-INF/tls/TNT.tld" prefix="TNT"%>
  • 9.  In EnterEmpInfoJSP, replace the following tags:
    <jsp:useBean id="EmpBean" class="c9java.Employee" scope="request">
    <jsp:setProperty name="EmpBean" property="empNum" param="empNumTF" />
    <jsp:setProperty name="EmpBean" property="empStreet"
            param="streetAddrTF"/>
    <jsp:setProperty name="EmpBean" property="exemptions" param="exmpDDM"/>
    <jsp:setProperty name="EmpBean" property="empZip" param="zipTF"/>
    <jsp:setProperty name="EmpBean" property="empState" param="stateTF"/>
    <jsp:setProperty name="EmpBean" property="payRate" param="hPRTF"/>
    <jsp:setProperty name="EmpBean" property="empName" param="empNameTF"/>
    <jsp:setProperty name="EmpBean" property="empCity" param="cityTF"/>
    </jsp:useBean>

with these start and end tags for the custom tag:

<TNT:getEmp>
</TNT:getEmp>

Remember, the bean tags are being deleted because CrtEmpBean’s doStartTag method will perform these functions (with the help of the EmpExtractor and PageContext objects).

  • 10.  Save EnterEmpInfoJSP.

Time to test.

  • 11.  Run c11/EnterEmpInfoJSP on the server.
  • 12.  Specify the employee name as joe, pay rate as 10, select Display and click the Submit button.

The browser window should look like Figure 11-1.

Although not very pretty, this proves that the Employee bean was created and that DispEmpInfoJSP was able to access the bean. More important, this means that the custom tag, getEmp, worked!

When to Create Custom Tags

Does this seem like a lot of work to duplicate what can be done with already existing tags? Well, it’s not as much work as it may seem. Some of the work was set-up that will not have to be repeated (e.g., creating the tls folder and the tld file). In addition, although the custom tag didn’t save you, the programmer, any time, the number of tags needed in the JSP was cut down substantially and will save the page designer time. Also, all those bean tags and parameters are difficult for a non-programmer to understand and use; therefore the chance of error was greater and the time to implement longer.

So, when should a custom tag be used? Obviously, if there are no tags to supply the needed function, a custom tag is needed. If the amount of coding in the JSP, whether tags or scriptlets, is beyond the capability of the page designer, the programmer should create a custom tag(s). Also, if the required function is needed in many pages, there are two advantages to using the custom tag. One, the function is coded only once, in the tag handler class (i.e., the page designer does not enter all the bean tags in multiple pages). Two, any changes to the function are made only once in the tag handler class. If the bean tags needed to be modified, the designer would have to change every page that contained the bean tags. So, the bottom line is that if a function is not available, used on many pages, or very complex, a custom tag should be created.

In the above example, we short-stepped the custom tag implementation process. We specified the tag library and path in the directive rather than defining a URI in the Web Deployment Descriptor and using the URI in the directive. The advantage to using a URI is that if the tag library is moved or renamed, only the Web Deployment Descriptor needs to be modified. If the actual path is specified in the directive, every page that uses that tag library has to be updated.

So, we will create a URI for the tag library. In addition, a new custom tag for a state drop-down menu will be created. We will then create new JSPs to use the custom tag and show how a custom tag is easily reused and modified. Finally, we will demonstrate how to pass information to a tag handler using a tag attribute.

Tutorial: Defining a URI

There are many types of deployment descriptors. Essentially, they all contain configuration information that the server will need to deploy an application. The term “configuration information” covers a wide range of information like security settings, data locations and, no coincidence here, tag library locations. The directory path and file that a URI corresponds to is a great example of information “the sever will need to deploy the application” because the application would not work if the deployment descriptor did not contain this information. As mentioned, the advantage is that this is information is specified in one location (a file called web.xml) rather than in all the JSPs and servlets. In RAD, you must create the deployment descriptor.

  • 1.  In the Project Explorer, right-click the project TutorialsWeb and select Java EE then Generate Deployment Descriptor Stub.

A file called web.xml will be created in the WebContent/WEB-INF folder. The file can be edited directly with a text editor but there a more user friendly tool called the Deployment Descriptor Editor.

  • 2.  Invoke the deployment descriptor editor by right clicking the web.xml file, select Open With, then Web Application 3.0 Deployment Descriptor Editor.
  • 3.  Initially the XML source code will be displayed. Change to the Design view by clicking the Design Tab in the lower left corner of the pane (see Figure 11-2).

The Design view makes the Deployment Descriptor look very organized (see Figure 11-3). In actuality, the Deployment Descriptor (the web.xml file) simply contains a lot of XML.

We will use the editor’s Variable view to insert the XML that maps the URI http://www.tnt.com/taglib to /WEB-INF/tls/TNT.tld.

  • 4.  To add the URI entry, click the Add button and from the Add Item window click JSP Configuration then the OK button.
  • 5.  In the Design view, JSP Configuration item will be displayed and be selected. Simply click the Add button again and select Taglib from the Add Item window.

The Design view will be redisplayed with a Details area.

In the source code, RAD inserted the following XML to map the URI to the tld file:

<jsp-config>
 <taglib>
         <taglib-uri> http://www.tnt.com/taglib</taglib-uri >
         <taglib-location>/WEB-INF/tls/TNT.tld</taglib-location>
 </taglib></jsp-config>
  • 7.  In EnterEmpInfoJSP, change the TNT taglib directive to the following:
    <%@taglib uri= "http://www.tnt.com/taglib " prefix="TNT
  • 8.  Save EnterEmpInfoJSP.

Tag Attributes

Attributes are relatively easy to define and even easier to use. As a matter of fact, you have already used attributes in the application. (The include tag inserted into the JSP specified both page and flush attributes.) To define and use an attribute:

  1. In the tag class, define a variable with getter and setter methods
  2. In the tag library, define an attribute with the same name as the variable
  3. Specify the attribute value as part of the tag in a JSP

The state drop-down menu will have an optional attribute called selected that allows a designer to specify a state abbreviation to be selected when the drop-down menu is displayed. The following XML code identifies the tag, tag handler, and defines the tag attribute selected.

       <tag>
                <name>stateDDM</name>
                <tagclass>c11.TNTStateDDM</tagclass>
<attribute>
                        <name>selected</name>
                        <required>false</required>
 </attribute>
        </tag>

The required tag is not required because attributes by default are optional. However, to define a required attribute, the “subelement” required must be specified and its value set to true.

An attribute must be specified in the start tag to make it available to the doStartTag method. The attribute name is specified after the tag name, separated by at least one space. For example, the following would define GA as the selected value in the custom tag stateDDM:

<TNT:stateDDM selected="GA"></TNT:stateDDM >

When the server encounters the keyword selected, the setter (in the TNTStateDDM tag handler class) will be invoked and passed the value GA. The TNTStateDDM class must check the value of the variable selected and generate the appropriate HTML such that the value is selected in the drop-down menu.

How to Generate a Visual Component

The stateDDM tag will generate a drop-down menu that has only three values to choose from FL, GA, and OK. (The tag handler c11.TNTStateDDM, of course, is actually doing all the work. In this case, the work entails inserting the HTML that defines the drop-down menu into the JSP. TNTStateDDM will do this similarly to how servlets manipulate a page. In a servlet, the programmer had to:

  • A.  Create a PrintWriter object
  • B.  Tie the print writer to the response object
  • C.  Run the print writer’s println method and embed the HTML in the response object

The tag handler (TNTStateDDM) will do the same, however, the JSP container (part of the server) makes things much easier by providing a JspWriter that is already associated with the JSP response object. In other words, the tag handler does not have to perform steps A and B from above. Rather the JSP writer is retrieved (using the ever-useful PageContext object) and the write method is executed. The following statement will do this:

pageContext.getOut().write(" HTML to be embedded ");

There is just one small hitch. Notice that the following HTML (which defines a drop-down menu, with the three state abbreviation options, and FL specified as the selected value) contains double quotes and that the write command above requires that the HTML be enclosed in double quotes.

<SELECT name="stateDDM">
        <OPTION value="FL" selected>FL</OPTION>
        <OPTION value="GA">GA</OPTION>
        <OPTION value="OK">OK</OPTION>
</SELECT>

As soon as the first double quote in the HTML is encountered, the RAD source editor will think that the code to be embedded is finished. In other words, if the following write statement (with the double quotes around stateDDM) is specified:

pageContext.getOut().write("<SELECT name="stateDDM">");

RAD will read this far in the statement:

pageContext.getOut().write("<SELECT name="

and think that only <SELECT name= should be embedded in the JSP. To make matters worse, RAD expects an ending parenthesis and semicolon to finish the write statement. When instead RAD runs into the remaining HTML, the entire statement will be flagged as an error.

Fortunately, RAD (and most editors) can be forced to include special characters, such as a double quote, as part of the parameter value rather than as part of the statement’s syntax by preceding the special character with a backslash (). So, each time a double quote appears in the HTML, it must be preceded with a backslash. The correct statement to insert the first line is:

pageContext.getOut().write("<SELECT name="StateDDM">");

TNTStateDDM will set FL as the default selected value but must check the selected attribute to see if another value should be selected instead.

The last thing we will do is change the JSP so that it uses the new tag stateDDM. This is going to be a little tricky. Currently, we import the entire EnterEmpInfoForm.html file that includes a state text field. We no longer want to do that. Instead, we want to include the beginning of the form (up to but not including the current state field definition). Then we want to insert the new custom tag for stateDDM and then an include tag .for the remaining portion of the EnterEmpInfoForm.html file. Two new files called StartEEIF.html and EndEEIF.html will be created to hold the HTML needed to define the form around the new tag. We will then add the include tags for the new files and the stateDDM tag into EnterEmpInfoJSP.

Tutorial: Generating a Visual Component

Let’s generate a visual component:

  1. Close all edit and browser sessions.
  2. In Java Resources/src/c11, create a new Java class called TNTStateDDM with a super class of TagSupportand no method stubs.
  3. In TNTStateDDM, add the following statement to create a class variable called selected with a default value of FL.
    private String selected = "FL";
  4. In TNTStateDDM, click Source, then Generate Getters and Setters. . .
  5. On the Generate Getters and Setters window, click the check box to the left of the variable selected so that both the getter and setter are and click the OK button.
  6. In TNTStateDDM, click Source, then Override/Implement Methods. . .
  7. At the Override/Implement Methods window, click on the doStartTag() checkbox to select it.
  8. Change the insertion point option to Last method and click the OK button.

    The following source code should be in the class:

    package c11;
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.TagSupport;
    public class TNTStateDDM extends TagSupport {
            private String selected = "FL";
            public String getSelected() {
                    return selected;
            }
            public void setSelected(String selected) {
                    this .selected = selected;
            }
            public int doStartTag() throws JspException {
                    return super .doStartTag();
            }
    }
  9. In doStartTag, before the return statement, add the following two statements to define the drop-down menu (make sure there is a blank line between them):
    pageContext.getOut().write("<SELECT name="stateDDM">");
    pageContext.getOut().write("</SELECT>");

    These statements will be flagged as errors because the write method can throw an exception. We will have RAD generate the appropriate try / catch..

  10. Select the statements and click Source, Surround With, and then Try/catch Block.

The try/catch statements will be added and the statements will no longer be flagged as errors.

Arrays

Before we go any further, we have to cover a topic that should have been covered much earlier: arrays. An array is a “structure” that can hold many primitive values or many reference variables of the same type. In other words, an array could be defined to hold multiple int values or multiple String variables. However, an array cannot be defined to hold both int values and String variables. Another way to say this is that arrays are typed. When the array is defined, the type of values it will hold must be specified. So for example, the following would define an array object that can hold seven int values:

new int[7];

Of course, this new array of integers can’t be accessed because it was assigned to a variable. To use this array, an integer array variable (e.g., myFirstArray) must be defined and the array assigned to it as follows:

int [] myFirstArray = new int [7];

Great, we have achieved array! Maybe we should put something into the array? To reference a particular array “bucket,” simply specify the bucket’s index/position number and assign a value using the equal sign. For instance, the following would assign the value 42 to the fifth bucket:

myFirstArray[4] = 42;

You can think about the array as looking like the following:

image

Are you wondering why the value 42 is where it is? Can you guess why? The first bucket has an index number of zero. In other words, the first bucket is referred to as myFirstArray[0]. So, myFirstArray[4] actually refers to the fifth bucket (or position) within the array. To reiterate, an array with a length of seven has seven buckets with position/index numbers ranging from zero to six. You can think of the array and its index numbers as looking like the following:

Index Number 0 1 2 3 4 5 6

image

Be careful, the index numbers are a source of countless errors!

Are you also wondering where all the zeros come from? The JVM inserts initial values when an array is created. For numeric arrays, that value is zero (character arrays are set to the character 0 and referenced variable arrays are set to null).

We are going to use an array to store our state values. Using an array will make adding or deleting states from the stateDDM tag much easier. For example, if we did not use an array, the following code would be needed to define the three state options in a drop-down menu:

<SELECT name="stateDDM">
      <OPTION value="FL">FL</OPTION>
      <OPTION value="GA">GA</OPTION>
      <OPTION value="OK">OK</OPTION>
</SELECT>

If we wanted to add five states, we would have to add five start and end OPTION tags with the new abbreviations specified in the body of the tags. Unfortunately, because the page designer can specify a state to be selected, it’s even more complicated. The tag handler needs to check the selected variable’s value and generate the appropriate HTML for that option to be selected. For example, if selected equals FL, the following HTML must be generated.

<OPTION value="FL" selected>FL</OPTION>

So, the tag handler needs several if statements like the following:

if (selected == "FL"){
 <OPTION value="FL" selected>FL</OPTION>
} else {
        <OPTION value="FL">FL</OPTION>}
if (selected == "GA"){
<OPTION value="GA" selected>GA</OPTION>
} else {
        <OPTION value="GA">GA</OPTION>}
if (selected == "OK"){
<OPTION value="OK" selected>OK</OPTION>
} else {
        <OPTION value="OK">OK</OPTION>}

Now when five states need to be added, the programmer must enter five if/else statements and ten start and end OPTION tags. That’s a lot of typing and, of course, this means mistakes can easily be made. To cut down on the amount of “hard-coded” HTML, a String array will hold the state values and a for loop will:

  1. Read each value in the array
  2. Check if the array value is the selected value
  3. Build the appropriate OPTION tags.

Tutorial: Using an Array

Now let’s use an array

  • 1.  In TNTStateDDM, add the following statements to create a class String array variable called stateArray that has the following three values.
    String[] stateArray = {"FL", "GA", "OK"};

Notice that no size was specified for the array. An array can be assigned values, and the JVM will create an array of the needed size - in this case three.

  • 2.  In TNTStateDDM, add the following statements to create class StringBuffer variables to hold various “pieces” of the OPTION tags.
    StringBuffer optionTagStart = new StringBuffer("<OPTION value="");
    StringBuffer optionSelected = new StringBuffer("" selected>");
    StringBuffer optionNotSelected = new StringBuffer("">");
    StringBuffer optionTagEnd = new StringBuffer("</OPTION>");
    StringBuffer optionTags = new StringBuffer();

Because the HTML to define each option will be constantly changing in the loop, defining optionTags as a StringBuffer is a more computer-efficient choice than defining it as a String. However, because only Strings can be embedded into the JSP, we will need to convert the StringBuffer to a String thereby adding a little extra code.

Notice that when a state is to be selected, only the start tag is different from a non-selected state. In other words, the end tag never changes. Looking closer at the start tags, notice that non-selected and selected OPTION tags actually begin the same. The difference is the characters that follow the value attribute in the start tag. If a value is not selected, then the value in the start tag is simply followed by a double quote and a greater than sign. If the value is selected, then it is followed by a double quote, a space, the keyword selected, and then the greater than sign. So, two strings (optionSelected and optionNotSelected) were created to hold these two possible sets of characters.

  • 3.  In the doStartTag, between the two write statements, insert the following statements
    for ( int ctr = 0; ctr < stateArray.length; ctr++) {
     optionTags.append(optionTagStart).append(stateArray[ctr]);
     if (stateArray[ctr] == this .selected) {
            optionTags.append(optionSelected);
     } else {
            optionTags.append(optionNotSelected);
     }
     optionTags.append(stateArray[ctr]).append(optionTagEnd);
     pageContext.getOut().write(String. valueOf (optionTags));
     optionTags.delete(0,optionTags.length());
     }

You should note several things. The for loop’s counter(ctr) is initialized to zero to correspond to the index value of the array’s first position/bucket. The loops test condition checks that the count is less than the length of the array. Think about that. If the array has a length of three, the largest index value in the array is two (i.e., the array has three values with index values of 0, 1, and 2). We want the for to execute three times for the counter values of 0, 1, and 2. So we want the for to only execute when the variable ctr is less than the length of the array (3).

Inside the loop, the constant text that comprises the beginning of the start OPTION tag (optionTagStart) is concatenated to the state value stored in the first position of the array (i.e., FL). This means that after the first statement in the loop, optionTags has the following value:

<OPTION value="FL

The if statement then compares the value in the first array position to the variable select-ed’s value. Based on whether they are equal or not, either the optionSelected or optionNotSelected string is concatenated to (and finishes) the start OPTION tag. In this case, we’ll assume that no attribute value was specified by the page designer and that the value of selected is the default value FL. This means that the characters stored in optionSelected are appended to optionTags resulting in a value of:

<OPTION value="FL" selected>

Next, the state abbreviation to appear in the drop-down menu (i.e., the value in position 0 of the array) and the end tag are appended to optionTags, resulting in a character string of:

<OPTION value="FL" selected>FL</OPTION>

The OPTION tag for the first state value is converted to a String and written to the JSP. The contents of optionTags is deleted and the loop begins again (the counter value is incremented by one, compared against the length of the array, etc). The loop will execute two more times and the HTML for the two remaining state values will be embedded into the JSP.

Because of the array and loop, if five states had to be added, five state values would simply be added to the array definition. No other java code or HTML statements would be needed to add the five states.

  • 4.  Save TNTStateDDM.

Tutorial: Defining and Using the Custom Tag

We can now define and use the tag

  • 1.  In TNT.tld add the following XML after the getEmp tag definition:
    <tag>
            <name>stateDDM</name>
            <tagclass>c11.TNTStateDDM</tagclass>
            <attribute>
                    <name>selected</name>
                    <required>false</required >
            </attribute>
    </tag>
  • 2.  Save TNT.tld.
  • 3.  Bring up c11/EnterEmpInfoForm.html in the Page Designer and click on the state input field.
  • 4.  Switch to the Source view.

The cursor should be positioned at the beginning of the state field’s INPUT tag (indicated by the first arrow in Figure 11-5).

All the HTML before the INPUT tag will be copied to a file called StartEEIF.html. The HTML after the tag (indicated by the second arrow in Figure 11-5) will be copied to a file called EndEEIF.html. In the JSP, the new stateDDM tag will be inserted and include tags for the new html files will be inserted before and after the stateDDM tag.

  • 5.  Copy all the HTML before the INPUT tag.
  • 6.  In WebContent/c11, create a new Web Page of type HTML/XHTML called StartEEIF.
  • 7.  In StartEEIF, select all the default code.
  • 8.  Paste the code copied from EnterEmpInfoForm over the default code and save StartEEIF.
  • 9.  In EnterEmpInfoForm, copy the HTML after the INPUT tag.
  • 10.  In WebContent/c11, create a new file called EndEEIF and paste the code just copied from EnterEmpInfoForm.
  • 11.  Save EndEEIF and at the Conflict Encoding window click Yes.

Please note that EndEEIF shouldn’t be an HTML file. Because the copied HTML does not define a “complete” page, entering it in an HTML file will generate numerous source code warning messages (that we will ignore) and warnings like the encoding conflict.

  • 12.  Bring up EnterEmpInfoJSP in the Page Designer and select the include tag (i.e., select the form).

If the include tag was selected, the form should be outlined in black and the properties view will show that the jsp:include tab, on the left, is selected (as in Figure 11-6).

  • 13.  Delete the tag by pressing the Delete button.
  • 14.  In the JSP tags drawer, click Include and then click beneath the tag icons.
  • 15.  At the Insert JSP Include window, specify StartEEIF.html and click the OK button.

The first half of the employee form will be displayed in Page Designer. The new state custom tag needs to be inserted after the half form.

  • 16.  Place the insertion point after the include tag by clicking anywhere beneath the half form.
  • 17.  Click JSP, and then Insert Custom. . .

Because the taglib directive is already in the JSP, RAD displays the TNT tag library and all its tags. (Click on the other tag library option if you would like to display all the tags in jstl/core tag library.)

  • 18.  At the Insert Custom Tag window, select stateDDM (as in Figure 11-7), click the Insert button and then the Close button.
  • 19.  In the JSP tags drawer, click Include and then click to the right of the custom tag icon
  • 20.  At the Insert JSP Include window, enter EndEEIF.html as the File name and click the OK button.

Page Designer should look like Figure 11-8.

Does Figure 11-8 surprise you? If so, then the Preview view will also be surprising! Remember the browser can only interpret HTML and scripts. Custom tags and JSP tags are resolved by the server (i.e., the server invokes the tag handler class). So, the only way to test a custom tag is to run the JSP on the server.

Tutorial: Testing the Custom Tag

We’ve built it, so we have to test it:

  • 1.  Run EnterEmpInfoJSP on the server.
  • 2.  In the browser session, click the refresh button.

The page should look like Figure 11-9.

Notice that FL appears as the default value.

  • 3.  Click on the state field’s drop-down button and verify that all the state abbreviations are displayed.
  • 4.  Select OK as the state, 10 as the pay rate, Display as the function, and click the Submit button.

Uh-oh, no state value appears. What happened?

Well, we changed the name of the state field from stateTF to stateDDM and EmpExtractor tries to set the Employee object’s state property from the value of stateTF. So, we have to change EmpExtractor.

  • 5.  Change c11/EmpExtractor to retrieve stateDDM not stateTF.
  • 6.  Rerun the step 4 test and verify that OK is displayed as the state.

Now we will test that the tag attribute was defined correctly and works.

  • 7.  In the Page Designer, click on EnterEmpInfoJSP’s stateDDM custom tag icon (see the first arrow in Figure 11-10).
  • 8.  In the Properties view, enter OK as the value for the attribute selected (see the second arrow in Figure 11-10).

Switching to the Source view would show that RAD has changed the start tag to the following:

<TNT:stateDDM selected="OK">
  • 9.  Save EnterEmpInfoJSP.
  • 10.  In the browser go back to EnterEmpInfoJSP and refresh the page.

OK should be displayed as the selected value in the state drop-down menu.

  • 11.  Switch to the Source view for EnterEmpInfoJSP and change the value for selected to GA.
  • 12.  Save EnterEmpInfoJSP and in the browser refresh the page to show GA is now selected.

Tutorial: Database Access with Tags

We will demonstrate the flexibility and advantages of both the MVC architecture and custom tags by changing the application to work with a DBMS. An Insert JSP (InsEmpInfo.jsp) will be created that allows a user to add employees to the database and that uses the stateDDM custom tag. Two files (StartIEIF.html and EndIEIF) will be created that define the beginning and ending of a form with all the needed data entry fields. New custom tags (insEmp, delEmp) and tag handlers (InsertEmp, DeleteEmp) will be created to perform database inserts and deletions. InsEmpInfo.jsp will use the Employee bean (created by the getEmp tag) and the insEmp and getEmp tags to insert the information.

Specifically, when InsEmpInfo.jsp is first accessed, a data entry form with the stateDDM field will be displayed. After the information has been entered and the form’s submit button clicked, InsEmpInfo will be invoked again. InsEmpInfo will check to see if the request is a post and, if so, execute the getEmp tag (to create an Employee bean) and the insEmp tag (to insert the information).

StartEEIF.html and EndEEIF.html have much of the HTML we need for the new form. Therefore, we will use them as the base for StartIEIF.html and EndIEIF.html, thereby avoiding a lot of typing (and probably mistakes).

  • 1.  In c11, copy and paste StartEEIF.html as StartIEIF.html and EndEEIF.html as EndIEIF.html.

StartIEIF needs to specify the form action as InsEmpInfo.jsp so that when the button is clicked, InsEmpInfo is invoked again by the server. Also, the title should be changed to StartIEIF.html

  • 2.  In the Source view of StartIEIF, change the TITLE and FORM tags to the following:
    <title>StartIEIF.html</title>
    <FORM action="InsEmpInfo.jsp" method="post">

EndIEIF needs to define the remaining data entry fields and the end of the form. Because EndEEIF was copied as EndIEIF, the remaining data entry fields already exist in EndIEIF. However, the function options list box (i.e., display, tax and gross amounts) is also in EndIEIF. So, the HTML that defines the table row holding the function list box and text needs to be deleted.

  • 3.  In the Source view of EndIEIF, delete the following HTML:
    <tr>
     <td align= "right" >
     <font face= "Tahoma" size= "4" color= "black" >
     Function
     </font>
     </td>
     <td>
            <select size= "2" name= "functionLB" >
                    <option value= "Display" >Display</option>
                    <option value= "Gross" >Gross</option>
                    <option value= "TaxAmt" >TaxAmt</option>
            </select>
     </td>
    </tr>
  • 4.  Change the Submit button’s text from Submit to Insert.

The button start tag should look like the following:

<input type="submit" name="submitBtn" value="Insert">
  • 5.  Save EndIEIF.

Because EnterEmpInfoJSP has much of the code we need for InsEmpInfo, we will use EnterEmpInfoJSP as the base for InsEmpInfo and, again, save a lot of typing and mistakes.

  • 6.  In c11, copy and paste EnterEmpInfoJSP as InsEmpInfo.jsp.

InsEmpInfo needs to be modified to include the HTML in StartIEIF and EndIEIF.

  • 7.  In the Source or Properties view of InsEmpInfo, change the appropriate include tag’s page attribute to StartIEIF and EndIEIF.
  • 8.  Save InsEmpInfo.

Let’s make sure InsEmpInfo looks right.

  • 9.  Run InsEmpInfo on the server.

The browser should look like Figure 11-11. Notice that the function box is gone and the button has the text Insert. Clicking the drop-down menu button will show the three state options.

InsEmpInfo must now be modified to create EmpBean and invoke the insert function. However, before that can be done the classes that provide the database functions must be created.

  • 10.  Copy Employee and DBAccess fromTutorials/src/c10 to TutorialsWeb/Java Resources/src/ c11. (If you are working in a complex environment, the particular “database classes” and the DB class need to be copied instead of DBAccess.)

Because the client-based application followed the MVC architecture (i.e., the model is separate from the view and controller), implementing the database functions in a server-based application is almost as simple as copying and pasting the model classes. In other words, because the model was built independently of the view, the classes that comprise the model can be easily used in projects that use different views. If the client-based application had embedded the database functions in a Frame subclass (i.e., combined the view and model functions), the database functions could not have been simply copied into a server-based application.

However, just as with the client-based application, the correct database driver needs to be available for the Employee class. If DB2 or Oracle is being used, the driver must be added to the Web App Libraries in the project’s Java build path.

  • 11.  If the DBMS is DB2 or Oracle, import or copy the DBMS driver file into the WebContent/WEB-INF/lib folder (if the folder lib does not exist, create it).
  • 12.  If the DBMS is Oracle, change the suffix of the driver file from .zip to .jar.
  • 13.  To prove that the driver was added successfully, right click TutorialsWeb and select Properties.
  • 14.  At the Properties for TutorialsWeb window, select Java Build Path, then expand the Web App Libraries item.

The driver file should appear as in Figure 11-12.

If you are using an Access database, you will have to move the database on to the RAD test server. Access databases cannot be accessed remotely, so they must reside on the server.

  • 15.  If you are using Access, copy the TNT.mdb file to the folder containing the RAD test server. For example, if you have a standard installation of RAD with one test server, the server definition would be in C:Program FilesIBMSDP70 untimesase_v8profilesAppSrv01.

If you can’t figure out the location of the server definition, after we create and implement the insert tag, simply run the insert JSP and try to insert an employee. The resulting error messages will display the folder location.

All that needs to be done now is to make the view (InsEmpInfo) invoke the model (i.e., the Employee class’s insert function). As mentioned, a new tag call insEmp will be created to perform the insert function. The tag will be added to InsEmpInfo such that the insEmp tag is executed after the button is clicked.

Tutorial: Modifying the View

Let’s make the necessary changes:

  • 1.  In Java Resources/src/c11, create a new Java class called InsertEmp with a super class of TagSupport and no method stubs.
  • 2.  In InsertEmp, add the following statements to define an Employee class variable called emp.
    private Employee emp;
  • 3.  In InsertEmp, click Source, then Override/Implement Methods. . .
  • 4.  At the Override/Implement Methods window, click on the doStartTag() checkbox to select it, and then click the OK button.
  • 5.  Before the return statement in doStartTag, add the following statement:
    emp = (Employee) pageContext.getRequest().getAttribute("EmpBean");

This statement retrieves EmpBean using the PageContext object. Unfortunately, the bean is returned as a type of Object. So, the Object must be cast as an Employee before it can be assigned to the variable emp.

  • 6.  After the above statement, add the following statement that invokes the insert function.
    emp.doInsert();
  • 7.  Save the file
  • 8.  In TNT.tld, add the following XML to define the new insEmp tag and associate the tag with the tag handler class InsertEmp:
<tag>
        <name>insEmp</name>
        <tagclass>c11.InsertEmp</tagclass>
</tag>
  • 9.  Save TNT.tld.
  • 10.  In InsEmpInfo.jsp, delete the choose, when, and forward tags.

This can be done by deleting the source code in the Source view or by selecting the choose icon in Page Designer (see Figure 11-13) and pressing the Delete key.

  • 11.  After the getEmp end tag, add the insEmp start and end tags and save the file.

The if and custom tags should look like the following:

<c:if test='${pageContext.request.method=='POST'}'>
        <TNT:getEmp>
        </TNT:getEmp>
        <TNT:insEmp></TNT:insEmp>
</c:if>

As with most tags, the custom tags can be specified even more simply as follows:

<TNT:getEmp/> <TNT:insEmp/>

The last modification needed is to add a new state (IN) to all the state drop-down menus throughout the application. If the state drop-down menu had been defined directly in multiple JSPs, all the JSPs would have to be modified. Because the state drop-down menu is a custom visual component (implemented with custom tags), making this application-wide change means simply updating the tag handler.

  • 12.  In TNTStateDDM, add the value IN (for Indiana) to the array definition so that IN appears after GA, and then save the file.

That’s all it takes to change every JSP’s state field.

  • 13.  Run InsEmpInfo on the server.
  • 14.  Click on the state drop-down menu and verify that the value IN appears as an option.
  • 15.  Enter the information as seen in Figure 11-14 and click the Insert button.

The InsEmpInfo page will be redisplayed and all the data removed from the fields. But, did it work? Well, if you can access the database directly, display the Employee table and verify that the record was inserted. However, to prove that the insert worked, we will modify the get-Emp tag (i.e., CrtEmpBean.java) so that database information will be displayed.

Tutorial: Modifying the Tag Handler

CrtEmpBean will be modified to check the database when an employee number is entered on EnterEmpInfoJSP. If there is employee information in the database, then any information that came from the form (i.e., that is in EmpBean) will be overwritten with the database information. As before, the display page will then display the EmpBean data. We will also modify the display page to include the gross salary and tax amounts for the employee and provide the option to delete the employee information from the database.

  1. In CrtEmpBean’s doStartTag method, after the Employee object is assigned to emp but before EmpBean is defined, add the following statement:
    emp.getEmpInfo(pageContext.getRequest().getParameter("empNumTF").toString());

This statement retrieves the employee number entered in the empNumTF field using the request object’s getParameter method. Just as when page context was used to get the Employee bean, a parameter is returned as an object of type Object. In this case, the Object object is converted to a String using its own toString method (rather than casting it, as was done earlier). Finally, the employee number is passed to the Employee class’s getEmpInfo method. This method retrieves employee information from the database and populates all the Employee object’s properties. If there is no employee record, the information entered on the page will not be overwritten.

This is not the most efficient way to perform this function. For instance, the Employee object may be written to twice - once with the form data and then possibly again with the database information. For efficiency, the database should be checked before the form information is added to the employee object. Then, only if there is no information for the employee in the database, should the object be populated with the form information. However, this inefficient solution is simpler to code because only one Java statement is needed.

Notice how easy it was to access the database: one statement. Remember, this was easy because the client-based application was implemented using the MVC architecture. Following the MVC architecture not only standardizes application design, it also makes applications more flexible and easier to modify.

Tutorial: Deleting Records Using a Custom Tag

DispEmpInfoJSP needs two new fields to display the gross salary and tax amounts along with all the other employee information. All the fields will be included on a form with a delete button. When pressed, the delete button will forward the request to a confirmation JSP (ConfirmEmpDel, see Figure 11-18). If the user clicks the confirm button on the page, the request will be forwarded to a delete employee JSP (EmpDel) where the record will be deleted and a message displayed confirming the delete (see Figure 11-19). A new delete tag (delEmp) will be defined and added to the EmpDel JSP.

  • 1.  In JavaSource/src/c11, create a new Java class called DeleteEmp with a super class of TagSupport and no method stubs.
  • 2.  In DeleteEmp, add the following statements to define an Employee class variable.
    private Employee emp;
  • 3.  In DeleteEmp, click Source, then Override/Implement Methods. . .
  • 4.  At the Override/Implement Methods window, click on the doStartTag() checkbox to select it, and then click the OK button.
  • 5.  In the doStartTag method, before the return statement, add the following statement:
    emp = (Employee) pageContext.getRequest().getAttribute("EmpBean");
  • 6.  Add the following statement to invoke the Employee delete function and save the file:
    emp.doDelete();

Is the procedure for creating a custom tag starting to seem familiar? As a quick reminder, the steps are:

  • A.  Create a tag support class
  • B.  Add the XML to the tag library
  • C.  Insert the tag library directive and tag into a JSP

Steps 1 through 6 did A. Step 7 and 8 will do B and, after creating two JSPs, steps 20 through 24 will do C.

  • 7.  In TNT.tld, add the following XML to define the new delEmp tag and associate the tag with the Java tag handler class DeleteEmp:
    <tag>
            <name>delEmp</name>
            <tagclass>c11.DeleteEmp</tagclass>
    </tag>
  • 8.  Save TNT.tld.
  • 9.  In WebContent/c11, create two new JSPs called ConfirmEmpDel and EmpDel.
  • 10.  In ConfirmEmpDel, insert a Form from the Form Tags tray and then insert following centered text (the font is Verdana) into the form:
    Please confirm that employee

    should be permanently deleted from the database
    by clicking the Confirm button
  • 11.  In the JSP Tags drawer, click on Get Property and then click on the blank line (after the first line of text).
  • 12.  At the Insert JSP Get Property window specify the Bean type as session, EmpBean as the Bean name, empName as the Property name and click the OK button.
  • 13.  In Page Designer, select the Get Property tag by clicking at the end of the first line of text and then dragging the cursor to the second line of text.

    This will select the tag and the line breaks (as in Figure 11-15).

  • 14.  In the Properties view, click the text tab (on the left) and then click the bold button (indicated by the arrow in Figure 11-15).
  • 15.  Insert a blank line after the text. Then, in the Form Tags drawer, click on Submit Button and then click on the blank line.
  • 16.  At the Insert Submit Button window, specify ConfirmBtn as the Name, Confirm as the Label, and click the OK button.
  • 17.  If needed, horizontally center the Confirm button on the page.
  • 18.  Select the form and in the Properties view, specify EmpDel.jsp as the action and select Post as the Method.

Page Designer and the Properties view should look like Figure 11-16.

The delEmp tag needs to be added to EmpDel.jsp and EmpDel.jsp should display a message saying the employee information has been deleted.

  • 19.  In the Page Designer view of EmpDel.jsp, click Custom in the JSP Tags drawer and then click anywhere on the page.

The Insert Custom Tag Window will be displayed with no URIs listed in the left pane or tags in the right pane. The taglib directive for the TNT tag library needs to be added to the page so that the delEmp tag can be specified.

  • 20.  On the Insert Custom Tag Window, click the Add. . . button.
  • 21.  Click the radio button for Show all valid URI choices and specify TNT as the Prefix
  • 22.  Scroll down the list, click the checkbox for the www.tnt.com URI name and click the OK button.

The Insert Custom Tag Window will be displayed with the TNT tag library URI displayed in the left pane and the four TNT tags listed in the right pane.

  • 23.  Select delEmp, click the Insert button, and then the Close button.

In the Source view, notice that RAD added the following taglib directive and custom tags:

<%@taglib prefix="TNT uri=" http://www.tnt.com/taglib "%>
<TNT:delEmp></TNT:delEmp>
  • 24.  In Design view, click Get Property and then click to the right of the custom tag.
  • 25.  At the Insert JSP Get Property window, specify session as the Bean Type, EmpBean for the bean name, empName as the Property name, and click the OK button.
  • 26.  After the getProperty tag, add the text: has been deleted from the database.

Even though the employee information will be deleted from the database, the employee bean still exists. Therefore, we can still retrieve the name of the employee that was deleted and display it in the deletion message.

We are now going to add the tax and salary amounts to the display page.

  • 27.  In the Page Designer view of DisplayEmpInfoJSP, click on the last row of the table.
  • 28.  In the Command Bar, click Table, and then Add Row Below.

There should now be two blank rows at the end of the table.

  • 29.  Add the text Gross Salary: and Tax Amount: in the first column of the two blank rows and format the text to match the existing table text.
  • 30.  In the second column of the new rows, add the appropriate getProperty tags to display EmpBean’s gross amount and tax amount properties.
  • 31.  In the Form Tags drawer, click on Submit button and then, in Page Designer, click beneath the table.
  • 32.  At the Insert Submit Button window, specify DeleteBtn as the name, Delete as the Label, then click the OK button.
  • 33.  Horizontally center the button.
  • 34.  In the Forms Tag tray, click on Form then click before the first line of text. Cut and paste all the page components into the form.
  • 35.  In the Properties view, specify ConfirmEmpDel.jsp as the form action and the Method Post.

Page Designer and the Properties view should look like Figure 11-17.

  • 36.  Save all changed files.

Tutorial: Testing the Insert and Delete

First, we will verify that the insert was performed and then test the delete function.

  • 1.  Run c11/EnterEmpInfoJSP on the server, specify 444 as the Employee number, Display as the Function, and click the Submit button.

The Tracy Tester information and a Delete button should be displayed. This proves that the insert performed earlier worked.

  • 2.  Click the Delete button.

An error message will be displayed in the browser saying that the confirm page cannot be displayed. In the console pane, the reason for the error will be a null bean. What happened? When the Delete button was clicked (on the display page), a new request was created and forwarded to the confirm page. The new request does not have an EmpBean. “Why not?” you ask.

Because EmpBean was defined with a scope of request. Because EnterEmpInfoJSP created a new request, the EmpBean was not associated with this new request.

There are many ways to solve this problem. We will change the scope of EmpBean from request to session. The bean scope can be changed very easily because the bean is defined in only one place, the CrtEmpBean class. (If bean tags had been used, many JSPs would have had to be updated.) The statement that defines the Employee object as an attribute of the request will be changed to define the Employee object as an attribute of the session. This means that InsertEmp and DeleteEmp need to be changed to get the bean from the session not the request.

  • 3.  In CrtEmpBean, change the statement that defines the bean to:
    pageContext.getSession().setAttribute("EmpBean", emp);
  • 4.  In InsertEmp and DeleteEmp, change the statement that gets the bean to:
    emp = (Employee) pageContext.getSession().getAttribute("EmpBean");

Notice that the only change to these statements is that instead of invoking the page context’s getRequest method, the getSession method is used.

  • 5.  Save the files.
  • 6.  In the browser, use the back button to redisplay the EnterEmpInfoJSP (444 should be specified as the Employee number and Display as the Function).
  • 7.  Click the Submit button.

Again, the Tracy Tester information and a Delete button should be displayed. This time, however, CrtEmpBean created EmpBean as a session bean.

  • 8.  Click the Delete button.

The Tracy Tester name should be displayed with the text and a Confirm button as in Figure 11-18.

  • 9.  Click the Confirm button.

The EmpDel JSP should be run, resulting in the employee record for Tracy Tester being deleted from the database. The browser will display the text that confirms that the record was deleted (see Figure 11-19).

  • 10.  To verify that the record was deleted, use the browser’s back button to redisplay the Enter-EmpInfoJSP with the employee number 444 specified.
  • 11.  Specify Joe as the employee name, FL as the State, 15 for the pay rate, Display as the function and click the Submit button.

The browser will display the information entered above. This means that there was no information for employee 444 in the database to override the information entered in step 11, which confirms that the Tracy Tester information was deleted from the database.

Checking the Console view will also show a message saying there was a problem getting information from the result set (in the Employee class). Which makes sense because there was nothing returned in the result set when the select statement for employee number 444 was executed.

The server-based application has been upgraded, but to make the coding easier we have violated some standards and introduced inefficiencies. One violation that we have not pointed out is that the application does not separate the view and controller functions. The JSP pages contain forward tags. Really, a servlet should be performing this controller function. The advantage to using a servlet is that if a new page were added or deleted, no other pages would be modified. The MVC architecture would ensure that any navigation changes would be made in one place, the servlet, and not affect the JSPs that comprise the view.

In addition, the application has not been very careful about creating and closing multiple connections. For instance, instead of creating a connection each time an Employee object is created, it would have been more efficient to create a connection when the application is started and then have all the employee objects use that connection.

Fortunately, the next chapter covers Java Server Faces, which provides easy tools to make these improvements.

Results of the Tutorial

Let’s check our results:

  • 1.  In the TutorialsWeb project, a new package in WebContent named c11.
  • 2.  In c11, the following nine new files:
  • ConfirmEmpDel.jsp
  • EndEEIF.html
  • EnterEmpInfoForm.html
  • InsEmpInfo.jsp
  • StartIEIF.htm
  • EmpDel.jsp
  • EndIEIF.html
  • EnterEmpInfoJSP.jsp
  • StartEEIF.html
  • 2.  Inside of JavaResources/src, a new folder called c11 containing the following seven Java files:
  • CrtEmpBean.java
  • DeleteEmp.java
  • Employee.java
  • TNTStateDDM.java
  • DBAccess.java
  • EmpExtractor.java
  • InsertEmp.java
  • 3.  Modifications to DispEmpInfoJSP to display the tax and gross salary amounts and an option to delete an employee record from the database
  • 4.  The employee Web-based application can now insert, display, and delete employee information in a database using custom tags.

Review Questions

  1. What is a tag handler?
  2. When defining a custom tag, what is the purpose of the Web Deployment Descriptor?
  3. When should a custom tag be created?
  4. What is an array?
  5. How is XML used to define a custom tag?
  6. What is the purpose of a tag library directive in a JSP?
  7. How is the TagSupport class used when creating a custom tag?
  8. Name two methods inherited from the TagSupport class.

Review Exercise

The Shipment application will be modified to insert, display, and delete shipment information in a DBMS using custom tags. This will require:

  • A.  Three new tags called crtShipBean, insShip, and delShip
  • B.  Three TagSupport subclasses called CrtShipBean, InsertShip, and DeleteShip
  • C.  Five JSPs and two Web pages to perform the View component of the application.
  • 1.  In ReviewExWeb/WebContent, create a new folder called c11.
  • 2.  In c11, create the following files:
  • DispShip.jsp
  • DisplayShip.jsp
  • ConfirmDel.jsp
  • DelShip.jsp
  • ConfirmIns.jsp
  • EnterShipNum.html
  • ConfirmDel.html
  • 3.  Copy EnterShipInfoJSP from WebContent/c9 into c11.
  • 4.  In ReviewExWeb/Java Resources/src, create a new folder called c11.
  • 5.  In Java Resources: src/c11, create the following Java classes as TagSupport subclasses with no method stubs:
    CrtShipBean                InsertShip                DeleteShip
  • 6.  Copy Shipment.java and DBAccess.java from ReviewEx/src/c10 to Java Resources/src/c11.
  • 7.  In Web Content/WEB-INF/, create a new folder called tls and in tls a new file called TNT.tld.
  • 8.  In TNT.tld, add the XML to define three tags called crtShipBean, insShip, and delShip and associate them with the appropriate Java classes.
  • 9.  Add the XML to define a required attribute called source for the crtShipBean tag.
  • 10.  Create a deployment descriptor stub and add http://www.tnt.com/taglib as tag library reference URI and /WEB-INF/tls/TNT.tld as the location of the tab library.
  • 11.  In c11/EnterShipInfoJSP, change the form action from /ReviewExWeb/ShipInfoServlet to EnterShipInfoJSP.jsp.
  • 12.  In c11/EnterShipInfoJSP before the form, insert an if tag with a test that checks if the request type is a post.
  • 13.  Change c11/EnterShipInfoJSP, so that if the request is a post, the crtShipBean tags are executed with the source attribute specified as request. (Make sure the tags prefixes are TNT.)
  • 14.  Change c11/EnterShipInfoJSP, so that after the ShipBean is created the insShip tags are executed and a JSP forward to ConfirmIns.jsp is executed.

The Shipment application never had an extractor class (as the employee application did). Therefore, the CrtShipBean class will perform that function (i.e., retrieve the Shipment information from the request and populate the Shipment object properties). The Java Resources/ src/c11/CrtShipBean’s doStartTag method needs to be overridden to do the following:

If the source attribute is equal to request:

  • A.  Create a null Shipment object.
  • B.  Retrieve the shipment information (from the request parameter values) and set the appropriate shipment properties.

If the source attribute is equal to database:

  • A.  Create a Shipment object using the shipment number entered in shipNumTF

Then, in either case, define the Shipment object as a session attribute called ShipBean.

  • 15.  To do the above, add the following class variables definitions to CrtShipBean:
    private String source = null ;
    Shipment ship;
  • 16.  Create a getter and setter for the variable source.
  • 17.  Override the doStartTag method and add the following statements to the doStartTag method:
    if (source == "request"){
     ship = new Shipment();
            ship.setShipmentNum(pageContext.getRequest().getParameter("shipNumTF").toString());
            ship.setSupplierName(pageContext.getRequest().getParameter("suppNameTF").toString());
            ship.setRcvMon(pageContext.getRequest().getParameter("MonthDDM").toString());
            ship.setRcvDay(pageContext.getRequest().getParameter("DayDDM").toString());
            ship.setRcvYear(pageContext.getRequest().getParameter("YearDDM").toString());
            ship.setRcvHour(pageContext.getRequest().getParameter("HourDDM").toString());
            ship.setRcvMin(pageContext.getRequest().getParameter("MinuteDDM").toString());
            ship.setRcvAMPM(pageContext.getRequest().getParameter("AMPMDDM").toString());
            ship.setEmployeeNum(pageContext.getRequest().getParameter("empNumTF").toString()); }
    if (source == "database"){
            ship = new Shipment(pageContext.getRequest().getParameter(" shipNumTF").toString()); }
    pageContext.getSession().setAttribute("ShipBean", ship);
  • 18.  Override the Java Resources/src/c11/InsertShip doStartTag method to get the ShipBean (using the PageContext object) and execute its doInsert method.
  • 19.  Change ConfirmIns.jsp so that the following text and the shipment number appear as follows where XXX is the shipment number from the ShipBean.
    Shipment XXX
    has been inserted into the database
  • 20.  Enter the following HTML into EnterShipNum.html to display the text “Enter Ship Number:”, horizontally centered, followed by a text field called shipNumTF:
    <p align= "center" >Enter Shipment Number:
    <input type= "text" name= "shipNumTF" size= "20" ></p>
  • 21.  Create a form on DelShip.jsp and DispShip.jsp and within each form:
  • a.  Add a JSP include tag for EnterShipNum.html
  • b.  Add a horizontally centered Submit button to the bottom and:
    • a.  In DispShip, name the button DispBtn with text of Display
    • b.  In DelShip, name the button DelBtn with text of Delete
  • c.  On a post request, define the form action to return to the same JSP
  • d.  Before the form, insert an if tag with a test that checks if the request type is a post.
  • 22.  In DelShip, if the request is a post, insert the crtShipBean tags with the source attribute defined as database and than a JSP forward tag to ConfirmDel.jsp.

Using the JSP forward tag means that ConfirmDel will be invoked by a post request (because DelShip was invoked by a post request not a get request). This means ConfirmDel should display the confirmation message, if the request is a post, and if the request is a get, the deletion should be performed.

  • 23.  In DispShip, if the request is a post, insert the crtShipBean tags with the source attribute defined as database and then a JSP forward tag to DisplayShip.jsp.

The DisplayShip JSP should display all the ship properties. Bean getProperty tags can be used to retrieve all the property values; however, formatting the retrieved date and time information is cumbersome and redundant. We will change two Shipment class methods to correctly format and return the date and time.

  • 24.  In c11.Shipment, change the getRcvDate method to format the date correctly by inserting the following statement before the return:
    rcvDate = getRcvMon() + "/" + getRcvDay() + "/" + getRcvYear();
  • 25.  In Shipment, change the getRcvTime method to format the time correctly by inserting the following statement before the return:
    rcvTime = getRcvHour() + ":" + getRcvMin() + " " + getRcvAMPM();

Another formatting problem may need to be addressed. Month, day, minute, and hour values less than ten are frequently displayed as single-digit numbers in the drop-down menus. This causes formatting problems when the date and time values are displayed. For example, if the time is five minutes past noon, the value would be displayed as 12:5 PM. In addition, some DBMSs pad string values with spaces to fill up the field. For example, this means that five minutes after three o’clock in the afternoon will look like 3 :5 PM. Again, the best solution is to change the Shipment class to return the information correctly formatted. If you’re having these problems, do steps 26 through 29.

  • 26.  In Shipment’s getRcvHour method, change the return statement to the following so that any trailing spaces are “trimmed off”:
    return rcvHour.trim();
  • 27.  Change the return statements for the month and day values so that trailing spaces are also eliminated.
  • 28.  In Shipment’s getRcvMin method, insert the following statement before the return so that minute values less than 10 are padded on the left with a zero:
    if ((Integer. parseInt (rcvMin.trim()) < 10)
     && (rcvMin.trim().length() < 2) ){
     rcvMin = "0" + rcvMin.trim(); }
  • 29.  In DisplayShip.jsp, define a table with text and JSP getProperty tags to display the ShipBean’s properties as seen in Figure 11-20.

Each of the property tags should specify ShipBean as the Name. For the date and time values, use the rcvDate and rcvTime properties, rather than the six individual properties that make up the date and time.

  • 30.  In ConfirmDel.jsp, add a form with an action of ConfirmDel.jsp when the request type is get.
  • 31.  In the ConfirmDel.jsp form, add text, a getProperty tag for the shipment number, and a confirm button (named ConfirmBtn) as seen in Figure 11-21.
  • 32.  In ConfirmDel.jsp, add if tags to check if the request is a GET (yes, it must be capitalized) and if so, insert the delShip tags and a JSP forward tag to ConfirmDel.html.
  • 33.  Override the JavaSource/c11/DeleteShip doStartTag method to get the ShipBean (using the PageContext object) and execute its doDelete method.
  • 34.  Place the following text in ConfirmDel.html: The shipment has been deleted.

Results of the Review Exercise

After the exercise, we have the following:

  • 1.  In the ReviewExWeb project, a new package in WebContent named c11.
  • 2.  In WebContent/c11, the following new files:
  • ConfirmDel.html
  • ConfirmIns.jsp
  • DisplayShip.jsp
  • EnterShipInfoJSP.jsp
  • ConfirmDel.jsp
  • DelShip.jsp
  • DispShip.jsp
  • EnterShipNum.html
  • 3.  Inside of Java Resources/src, a new folder called c11 containing the following new Java files:
  • CrtShipBean.java
  • DeleteShip.java
  • DBAccess.java
  • InsertShip.java
  • Shipment.java
  • 4.  In WEB-INF, a new folder called tls and within tls, a file called TNT.tld that contains XML to define three new custom tags called crtShipBean, insShip, and delShip.
  • 5.  The shipment Web-based application can now insert, display, and delete shipment information in a database using the custom tags.

Check that the Exercise Was Done Correctly

Finally, we check that everything went as planned:

  • 1.  Save all files with changes.
  • 2.  Run c11/EnterShipInfoJSP on the server.
  • 3.  On the EnterShipInfoJSP page, insert the following shipment information into the database:
  • Employee number: 333
  • Shipment number: 8888
  • Date: August 8th,, 2012
  • Time: 8:08 pm
  • Supplier name: Target

The insert confirmation page should be displayed.

  • 4.  In the browser, specify the following in the URL: DispShip.jsp and press Enter.
  • 5.  Enter 8888 as the shipment number and click the Display button.

Shipment 8888’s information should be displayed as in Figure 11-22.

  • 6.  Display the DelShip page, specify 8888, and click the Delete button.

The confirm deletion page should be displayed.

  • 7.  Click the Confirm button.

The confirm deletion Web page should be displayed saying the shipment was deleted.

  • 8.  Use the browser’s back button to reshow DispShip and click the Display button.

The browser should show the “page cannot be displayed” message because a ShipBean could not be created with information from the database for shipment number 8888. (Actually, the error is thrown when DispShip tries to access the nonexistent 8888 shipment from the result set; specifically a null cursor exception is thrown.) Of course, the exception should be caught and handled by the application and we should fix how the time is displayed, but we will leave that for a rainy day.

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

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