Adding a Web Interface to the Agency Case Study

Now that you have learned about most of the features of JavaServer Pages, you are in a position to add a Web front end to the Agency case study. You will only develop a simple, but functional, Web interface; it may not be too pretty, but it will work.

Designing a complete Web site is as much an art as a science, and what is considered good design by one developer may not be considered as good by another. You, too, will have your own views about what comprises a “good” Web site. Rather than get into the aesthetics of Web site design, this section will concentrate on applying the features of JSP in an effective manner.

Structure and Navigation

Designing a good Web site is a lot like designing good Java code. Both require careful logical thought and should incorporate good design principles and practices. A well-designed Java program is easier to maintain and enhance than a badly designed one. Similarly, a well-designed Web site is easy for users to navigate and use. A well-designed Web site will have proportionally less complaints and criticisms than a badly designed site.

In this section, you will only look at the logical structuring and layout of the Web pages and Web applications. The presentation of the page (its look and feel) is a very emotive subject, and what appeals to one user may not appeal to another. Furthermore, your Web page look and feel will almost certainly be constrained (or dictated) by department or corporate standards. The structuring of your Web site may well be guided by local standards or conventions, but even so, you can apply logic and some simple guidelines to improve the navigability and use of the Web site as a whole.

Consider structuring your Web site along the same lines as you store your files in directories. This way, you can use different Web applications to represent different functional areas of your systems, and use the Web application context and aliases to simplify navigation.

Some simple guidelines for good site layout are as follows:

  • Group logically related functionality in a single Web application. By grouping related functionality into one application, you can reduce the learning time required for someone to maintain or link into your application because he or she only needs to study part of the site rather than the whole lot.

  • Use Web component aliases to apply a structure to your Web pages. Consider using multiple aliases for a Web page so that multiple aliases can point to a single page, allowing for logical hierarchical naming conventions. The Agency case study used names to relate functionality by area as follows:

    /customer/create
    /customer/delete
    

    The aliases could equally as well have related logically similar functionality such as

    /delete/customer
    /delete/applicant
    

    Alternatively, both naming schemes could also have been provided. It all depends on how you view the inter-relationships between the various pages in your application.

    Whatever approach you choose, you should always use aliases and not the actual JSP names. This will allow you to restructure your Web site by adding, removing, or renaming JSP files without affecting hyperlinks from other pages.

  • Ensure that no Web pages are dead ends (have no links to another page).

  • Provide navigation links in the same place on every page.

  • Ensure that every page has a link back to your site's home page and, if appropriate, a link to the top level page for this logical area of your system.

In the Agency case study, it has the following logical areas:

  • Customers advertising jobs

  • Applicants registering their locations and skills

  • Administration of the location and skill lookup tables

Looking ahead to Day 15, “Security,” when you will study the role of security within a J2EE application, you can structure your Web application to simplify the implementation of Web page authorization. You will do this by grouping all job and customer functionality under URLs starting with customer as follows:

/customer/advertise
/customer/createCustomer
/customer/deleteCustomer
/customer/updateCustomer

You will also store applicant functionality under pages with URLs starting with applicant as follows

/applicant/register
/applicant/createApplicant
/applicant/deleteApplicant
/applicant/updateApplicant

A Web site will typically have a main page called the portal page (also known as the home page or index page) that provides access to the functionality of the Web application. All clients will have access to the portal page, but they may have to login to use other features of the application. Because J2EE Web authorization is based on URL patterns, intelligent use of aliases for each Web page can ease the implementation of security to the Web application.

The Agency case study will have a portal page that will allow:

  • An existing customer access his or her own details

  • A new customer to be added to the system

  • An existing applicant access to his or her own details

  • A new applicant to register his or her details

  • Access to administration features

You will start by studying some features of the main portal page for Job Agency application. The “Deploying the Case Study JSPs” section, later in this chapter, shows you how to deploy the code you will study.

Look and Feel

Using a consistent look and feel across Web pages is an important criteria principle. Consistent look and feel is supported by using the JSP page include directive and HTML Cascading Style Sheets (CSS).

JSP page include directives can be used to define common features for all pages, such as headers, footers, and navigation links. These directives can be used instead of server-side include directives implemented by some Web servers.

As an example of how to use include files is shown in the following code fragment:

<HTML>
<HEAD>
<TITLE>Agency Portal</TITLE>
<%@include file="header.jsf" %>
<!-- rest of page -->

Each Web page in the case study will include a common header file, shown in Listing 13.11.

Listing 13.11. Full Text of header.jsf
1: <%@page errorPage="/agency/errorPage.jsp" %>
2: <LINK rel=stylesheet type="text/css" href="/agency/agency.css">
3: </HEAD>
4: <BODY>
5: <HR>
6: <jsp:useBean id="agency" class="web.AgencyBean" scope="request" />
7: <H1><jsp:getProperty name="agency" property="agencyName"/></H1>
8: <P>

Note that this file uses the jsf extension to show it is not a complete JSP. The header file defines an error page, a style sheet, and a common page heading that includes the job agency name.

By structuring the Web pages to include a common header file, you can be sure there will be a common look and feel to each page. The header file completes the page <HEAD> section and starts the page <BODY>. This isn't ideal, because the JSP designer has to know that the include file spans two logical components of the HTML page. But it does serve to show how useful include files can be.

The included header file also defines a bean called agency that can be used on the rest of the page to access the agency Session EJB. The level 1 page heading (<H1>) uses the agency name obtained from the agency bean.

If you haven't encountered HTML style sheets before, the simple one used for the agency is shown in Listing 13.12.

Listing 13.12. Full Text of agency.css
1: H1, H2, H3 {font-family: sans-serif}
2: H1 {background-color: navy; color: white }
3: H2 {color: navy }
4: H3 {color: blue }
5: BODY, P, FORM, TABLE, TH, TD {font-family: sans-serif}

Without going into detail, all this style sheet does is define font styles and colors for use with the HTML tags on a Web page that links to this style sheet. Browser support for CSS is erratic, so you may not see all of the desired font changes with your browser. If in doubt about your users' Web browsers, you should not use stylesheets but embed font and color styles on the JSP itself instead.

Returning to the agency portal page, you can use the agency bean defined by the header to access the agency Session EJB functionality. When the user clicks the Show Customer button, the following JSP fragment presents the user with a list of customer names and invokes an advertise.jsp page (via its alias customer/advertise).

<FORM action="customer/advertise">
<TABLE>
<TR><TD>Select Customer</TD>
<TD><SELECT name="customer">
<% Iterator customers = agency.findAllCustomers().iterator(); %>
<% while (customers.hasNext()) {%>
  <OPTION><%=customers.next()%>
<% } %>
</SELECT>
</TD></TR>
<TR><TD colspan=2><input type=submit value="Show Customer"></TD></TR>
</TABLE>
</FORM>

The HTML select tag used on this form has to be encoded as a scriptlet. On Day 14, you will learn how Tag Libraries can be used to define custom tags that support iterative constructs like those required to support the customer select list.

Listing 13.13 shows all the code of the portal page for the Agency application with support for the customer functionality only.

Listing 13.13. Full Text of agency.jsp
 1: <HTML>
 2: <HEAD>
 3: <TITLE>Agency Portal</TITLE>
 4: <%@include file="header.jsf" %>
 5: <%@page import="java.util.*" %>
 6: <H2>Customers</H2>
 7: <H3>Existing Customer</H3>
 8: <FORM action="customer/advertise">
 9: <TABLE>
10: <TR><TD>Select Customer</TD>
11: <TD><SELECT name="customer">
12: <% Iterator customers = agency.findAllCustomers().iterator(); %>
13: <% while (customers.hasNext()) {%>
14:   <OPTION><%=customers.next()%>
15: <% } %>
16: </SELECT>
17: </TD></TR>
18: <TR><TD colspan=2><input type=submit value="Show Customer"></TD></TR>
19: </TABLE>
20: </FORM>
21: <H3>Create Customer</H3>
22: <FORM action="customer/createCustomer">
23: <TABLE>
24: <TR>
25:   <TD>Login:</TD>
26:   <TD><INPUT type=text name=login></TD>
27: </TR>
28: <TR>
29:   <TD>Name:</TD>
30:   <TD><INPUT type=text name=name></TD>
31: </TR>
32: <TR>
33:   <TD>Email:</TD>
34:   <TD><INPUT type=text name=email></TD>
35: </TR>
36: <TR>
37:   <TD colspan=2><INPUT type=submit value="Create Customer"></TD>
38: </TR>
39: </TABLE>
40: </FORM>
41: <H2>Administration</H2>
42: <FORM action="admin/admin"><INPUT type=submit value="Administration Form"></FORM>
43: <P>
44: <HR>
45: </BODY>
46: </HTML>
						

Your exercise to complete at the end of today's lesson will be to add support for registering applicants to this framework.

One last point to raise for the Agency Web pages is that of using a consistent navigation model for each page. JSP include files are an ideal method for including consistent hyperlinks in each Web page. The following code fragment shows how a standard footer with a navigation button for returning to the portal page is included at the end of each Web page, and Listing 13.14 shows the actual footer page.

<%@include file="footer.jsf" %>
</BODY>
</HTML>

Listing 13.14. Full Text of footer.jsf
1: <P>
2: <HR>
3: <P>
4: <FORM>
5: <INPUT type="button" value="Return to Agency Menu" onClick='location="/agency/agency"'>
6: </FORM>
7: <BR>
						

If you consider the structure of jobs and applicants in the case study, you will realize that they have two common components:

  • A location that will be a value from an HTML select list

  • A set of skills (possibly) empty that must also be chosen from a list (in this case, an HTML select list that supports multiple options)

Good Java design practice would be to avoid duplicating the code by putting it in a separate method (or helper class) where the functionality can be reused. With JSP design, you can factor out the common code into a separate include file. The following code fragment shows how the JSP code for customer's advertised jobs uses include files:

<TABLE>
<TR><TD>Description:</TD>
      <TD><input type=text name=description
        value="<jsp:getProperty name="job" property="description"/>">
     </TD>
    </TR>
    <TR><TD>Location:</TD><TD>
      <% String location = job.getLocation(); %>
      <%@include file="location.jsf"%>
    </TD></TR>
    <TR><TD>Skills:</TD><TD>
      <% String[] skills = job.getSkills(); %>
      <%@include file="skills.jsf"%>
    </TD></TR>
</TABLE>

Each included file requires a variable to be defined before including the page (location and skills); this is the equivalent of passing a parameter into a method. This is not an ideal solution; in tomorrow's exercise, you will revisit this code and use tag libraries to develop a cleaner solution.

The previous code is part of the advertise.jsp file (see Listing 13.15 ). This JSP maintains customer details and jobs. It uses two JavaBeans as wrappers around the two Session EJBs called CustomerBean and JobBean. The JobBean wraps around the advertiseJob EJB that uses a compound parameter to identify each job (customer login and job reference). Creating this bean requires careful coding, as shown next. The list of customer jobs must be processed on the Web page in a loop implemented as a Java scriptlet, as shown in the following fragment:

<% String[] jobs = cust.getJobs(); %>
<jsp:useBean id="job" class="web.JobBean" scope="request">
  <jsp:setProperty name="job" property="customer" param="customer"/>
</jsp:useBean>
<% for (int i=0; i<jobs.length; i++) {%>
  <% job.setRef(jobs[i]); %>
  <H3><jsp:getProperty name="job" property="ref"/></H3>
...
<% } %>

Due to the way beans are defined on the page, this code has to be slightly clumsy. The bean is defined once before the Java loop and the customer part of the compound key are defined. Each time round the loop, the bean's setRef() method is called to set the next job reference; this method creates the appropriate advertiseJob Session EJB for use in the body of the loop. An alternative and much better approach is to use a custom tag, as shown on Day 14, “JSP Tag Libraries.”

Listing 13.15 shows the entire advertise jobs page. The include files location.jsf and skills.jsf are included on the CD-ROM—not shown here.

Listing 13.15. Full Text of advertise.jsp
 1: <HTML><HEAD>
 2: <TITLE>Advertise Customer Details</TITLE>
 3: <%@include file="header.jsf" %>
 4: <%@page import="java.util.*" %>
 5: <jsp:useBean id="cust" class="web.CustomerBean" scope="request" >
 6:   <jsp:setProperty name="cust" property="login" param="customer"/>
 7: </jsp:useBean>
 8: <H2>Customer details for: <jsp:getProperty name="cust" property="login"/></H2>
 9: <FORM action="updateCustomer">
10: <INPUT type=hidden name=login value="<jsp:getProperty name="cust" property="login"/>">
11: <TABLE>
12:   <TR><TD>Login:</TD><TD> <jsp:getProperty name="cust" property="login"/></TD></TR>
13:   <TR><TD>Name:</TD><TD><input type=text name=name value="<jsp:getProperty name="cust"
 property="name"/>"></TD></TR>
14:   <TR><TD>Email:</TD><TD><input type=text name=email value="<jsp:getProperty
 name="cust" property="email"/>"></TD></TR>
15:   <% String[] address = cust.getAddress(); %>
16:   <TR><TD>Address:</TD> <TD><input type=text name=address value="<%=address[0]%>"></TD></TR>
17:   <TR><TD>Address:</TD> <TD><input type=text name=address value="<%=address[1]%>"></TD></TR>
18: </TABLE>
19: <INPUT type=submit value="Update Details">
20: <INPUT type=reset>
21: </FORM>
22: <FORM action="deleteCustomer">
23: <input type=hidden name=customer value="<%=cust.getName()%>">
24: <input type=submit value="Delete Customer <%=cust.getName()%>"></TD></TR>
25: </FORM>
26: <H2>Jobs</H2>
27: <% String[] jobs = cust.getJobs(); %>
28: <jsp:useBean id="job" class="web.JobBean" scope="request">
29:   <jsp:setProperty name="job" property="customer" param="customer"/>
30: </jsp:useBean>
31: <% for (int i=0; i<jobs.length; i++) {%>
32:   <% job.setRef(jobs[i]); %>
33:   <H3><jsp:getProperty name="job" property="ref"/></H3>
34:   <FORM action="updateJob">
35:     <TABLE>
36:       <TR><TD>Description:</TD> <TD><input type=text name=description value="<jsp
:getProperty name="job" property="description"/>"></TD></TR>
37:       <TR><TD>Location:</TD><TD>
38:       <% String location = job.getLocation(); %>
39:       <%@include file="location.jsf"%>
40:       </TD></TR>
41:       <TR><TD>Skills:</TD><TD>
42:       <% String[] skills = job.getSkills(); %>
43:       <%@include file="skills.jsf"%>
44:       </TD></TR>
45:     </TABLE>
46:     <INPUT type=hidden name="customer" value="<jsp:getProperty name="job"
 property="customer"/>">
47:     <INPUT type=hidden name="ref" value="<jsp:getProperty name="job" property="ref"/>">
48:     <INPUT type=submit value="Update Job">
49:   </FORM>
50:   <FORM action="deleteJob">
51:     <INPUT type=hidden name="customer" value="<jsp:getProperty name="job"
 property="customer"/>">
52:     <INPUT type=hidden name="ref" value="<jsp:getProperty name="job" property="ref"/>">
53:     <INPUT type="submit" value='Delete Job <jsp:getProperty name="job" property="ref"/>'>
54:   </FORM>
55: <% } %>
56: <H2>Create New Job</H2>
57: <FORM action="createJob">
58: <TABLE>
59: <TR>
60:   <TD>Ref:</TD>
61:   <TD><INPUT type=text name=ref></TD>
62: </TR>
63: <TR>
64:   <INPUT type=hidden name="customer" value="<jsp:getProperty name="cust"
 property="login"/>">
65:   <TD colspan=2><INPUT type=submit value="Create Job"></TD>
66: </TR>
67: </TABLE>
68: </FORM>
69: <%@include file="footer.jsf" %>
70: </BODY>
71: </HTML>
						

To complete the customer functionality, the Web interface requires separate pages for

  • Creating a new customer

  • Deleting a customer

  • Updating a customer

  • Creating a new job

  • Deleting a job

  • Updating a job

Rather than reproduce all of these pages, the page for updating a customer is shown in Listing 13.16 (the remainder can be examined on the CD-ROM). Each page simply creates the appropriate agency, customer, or job bean using the request parameters, and calls the necessary business method.

Listing 13.16. Full Text of updateCustomer.jsp
 1: <HTML>
 2: <HEAD>
 3: <TITLE>Update Customer</TITLE>
 4: <%@include file="header.jsf" %>
 5: <jsp:useBean id="cust" class="web.CustomerBean" scope="request" >
 6:   <jsp:setProperty name="cust" property="login" param="login"/>
 7: </jsp:useBean>
 8: <% cust.updateDetails(request.getParameter("name"), request.getParameter("email")
,request.getParameterValues("address")); %>
 9: <H3>Updated <jsp:getProperty name="cust" property="login"/> Successfully</H3>
10: <%@include file="footer.jsf" %>
11: </BODY>
12: </HTML>
						

Error Page Definition

The very last file to examine for the case study is the error page file shown in Listing 13.17.

Listing 13.17. Full Text of errorPage.jsp
 1: <%@ page isErrorPage="true" %>
 2: <%@page import="java.util.*, java.io.* " %>
 3: <HTML>
 4: <HEAD>
 5: <TITLE>Agency Error Page</TITLE>
 6: </HEAD>
 7: <BODY>
 8: <H1>Agency Error Page</H1>
 9: <H2>There has been an error in processing your request.</H2>
10: The following information describes the error:
11: <H3>Request Parameters</H3>
12: <TABLE border=1>
13: <%
14: Enumeration params = request.getParameterNames();
15: while (params.hasMoreElements()) {
16:   String name = (String)params.nextElement();
17:   out.println("<TR><TD>"+name+"</TD>");
18:   String[] values = request.getParameterValues(name);
19:   for (int i=0; i<values.length; i++) {
20:     out.println("<TD>"+values[i]+"</TD>");
21:   }
22:   out.println("</TR>");
23: }
24: %>
25: </TABLE>
26: <H3>Request Attributes</H3>
27: <TABLE border=1>
28: <%
29: Enumeration attrs = request.getAttributeNames();
30: while (attrs.hasMoreElements()) {
31:   String name = (String)attrs.nextElement();
32:   out.println("<TR><TD>"+name+"</TD>");
33:   out.println("<TD>"+request.getAttribute(name)+"</TD>");
34:   out.println("</TR>");
35: }
36: %>
37: </TABLE>
38: <H3>Session Attributes</H3>
39: <TABLE border=1>
40: <%
41: Enumeration sess = session.getAttributeNames();
42: while (sess.hasMoreElements()) {
43:   String name = (String)sess.nextElement();
44:   out.println("<TR><TD>"+name+"</TD>");
45:   out.println("<TD>"+session.getAttribute(name)+"</TD>");
46:   out.println("</TR>");
47: }
48: %>
49: </TABLE>
50: <H3>Exception</H3>
51: <%=exception%> <%=exception.getMessage()%>
52: <H3>Stack Trace</H3>
53: <%
54: StringWriter buf = new StringWriter();
55: PrintWriter sout = new PrintWriter(buf);
56: exception.printStackTrace(sout);
57: out.println(buf.toString());
58: %>
59: </BODY>
60: </HTML>
						

This error page is designed for use during development. When an exception occurs, this page displays information about the exception and various Java variables derived from the request, servlet, and page contexts.

At the top of Listing 13.17 is the line

<%@ page isErrorPage="true" %>

This tells the translation phase to include a variable called exception that refers to the exception that caused the page error. This exception is used to display a stack trace on the error page. The first line of the stack trace will identify

  • The name of the generated servlet

  • The line number where the exception occurred

  • The exception that was thrown

  • A brief description of the error

This information can be used to trace back the error to the original JSP file by using the Java code listing for the generated servlet.

For a fully-developed and deployed application, it would be better for the error page to display a user-friendly error message and report the error (perhaps via JavaMail) to an administrator.

The Agency case study error pages are designed to illustrate the principles involved in error reporting and are not necessarily an example of best practice.

Deploying the Case Study JSPs

In today's lesson, you have used a large number of files to create the Web interface to the job agency Session beans. Building and deploying the Web application is relatively straightforward if you perform the following steps:

1.
Start up deploytool and create a new Web component and add it to a new WAR file called web.

2.
Add the following JSP files from the src/jsp directory to this war file:

  • admin.jsp

  • advertise.jsp

  • agency.css

  • agency.jsp

  • createCustomer.jsp

  • createJob.jsp

  • createLocation.jsp

  • createSkill.jsp

  • deletCustomer.jsp

  • deleteJob.jsp

  • deleteLocation.jsp

  • deleteSkill.jsp

  • errorPage.jsp

  • footer.jsf

  • header.jsf

  • location.jsf

  • modifyLocation.jsp

  • modifySkill.jsp

  • skills.jsf

  • updateCustomer.jsp

  • updateJob.jsp

  • updateLocation.jsp

  • updateSkill.jsp

3.
Add the following class files from the web directory to this WAR file:

  • AgencyBean.class

  • CustomerBean.class

  • JobBean.class

4.
Add the following class files from the agency directory to this WAR file:

  • Advertise.class

  • AdvertiseHome.class

  • AdvertiseJob.class

  • AdvertiseJobHome.class

  • Agency.class

  • AgencyHome.class

  • DuplicateException.class

  • NotFoundException.class

  • Register.class

  • RegisterHome.class

5.
Click Next, select JSP for the EJB component, and the click Next.

6.
Set the JSP Filename to agency.jsp and accept the default Web component name of admin.

7.
Click Next twice and add a page alias of /agency.

8.
Click Next four times to get to the EJB References page. Add the EJB references shown in Table 13.4 (they are all Session beans with a remote interface):

Table 13.4. Case Study Web Application EJB References
Coded name Home i/f Remote i/f JNDI name
ejb/agency agency.AgencyHome agency.Agency ejb/agency
ejb/advertise agency.AdvertiseHome agency.Advertise ejb/advertise
ejb/advertiseJob agency.AdvertiseJobHome agency.AdvertiseJob ejb/advertiseJob

9.
Click Finish.

10.
Now you will need to create Web components in the same WAR file for every other JSP. You have added all of the required files, so all you need to do is define the JSP page and alias. Table 13.5 lists all the pages you need to define, including the admin JSP page you just added in step 6.

Table 13.5. Case Study Web Application JSP Components
JSP Filename Alias
advertise.jsp /customer/advertise
admin.jsp /admin/admin
createCustomer.jsp /customer/createCustomer
createJob.jsp /customer/createJob
createLocation.jsp /admin/createLocation
createSkill.jsp /admin/createSkill
deletCustomer.jsp /customer/deleteCustomer
deleteJob.jsp /customer/deleteJob
deleteLocation.jsp /admin/deleteLocation
deleteSkill.jsp /admin/deleteSkill
errorPage.jsp /errorPage
updateCustomer.jsp /customer/updateCustomer
updateJob.jsp /customer/updateJob
updateLocation.jsp /admin/updateLocation
updateSkill.jsp /admin/updateSkill

11.
When you have added all of the Web components, you can deploy the Web application with Tools, Deploy. You do not need to return the client JAR file, so click Next twice.

12.
On the WAR Context Root screen, enter a root context for your Web application of agency.

13.
Click Finish and, if you've entered everything correctly, you will have deployed your case study Web interface.

You must have previously deployed the Agency application with which the Web interface can communicate. Any version of the Agency case study from Day 5, “Session EJBs,” Day 6, “Entity EJBs,” Day 10, “Message-Driven Beans,” or Day 11, “JavaMail” will suffice.

You can access the case study application using http://localhost:8000/agency/agency.

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

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