3.4. Web Component Client (JSP Client)

A stand-alone Java application is appropriate when the client performs an administrative function on a specific machine with a limited user base. A web component client, on the other hand, can run on any machine with a web browser as long as it is connected to a J2EE application server (either directly or across the Internet). In this section, we'll create a JSP component that is a typical browser-based procedure. This JSP program will be a web-enabled version of the Loan EJB client that we showed you in the previous section.

Introducing Servlets and JSP

If you are already familiar with JSP and servlets, you can skip this section. JSP is really just a front end for servlets, so let's provide an overview of the Java servlet architecture first. Readers wishing a more in-depth treatment can read the Prentice Hall text Core Servlets and JavaServer Pages™ by Marty Hall.

A servlet is a server-side Java software component that allows two-way interaction between a client and server. Servlets execute on a Java-enabled web server and are an efficient and effective way to produce dynamic page content for web-based applications. The web server loads servlets once but each request spawns a new thread rather than a new process. Because the Java Virtual Machine (JVM) executes servlet bytecode, the server is protected from poorly written or malicious servlets. Furthermore, Java provides strong type checking and exception handling to help servlet designers write robust code. Servlets provide support for HTTP protocol, although servlet technology is not specifically limited to HTTP.

HttpServlet Class

The HttpServlet class is abstract so you can subclass and create your own HTTP servlet. To do this, you must override one or more methods. The two most important methods are doGet() and doPost(). The server calls doGet() to handle HTTP GET requests and doPost() to handle HTTP POST requests.

The HttpServlet class defines several useful objects. HttpServletRequest encapsulates client request information and HttpServletResponse contains information returned to the client. The HttpSession object also provides putValue() and getValue() methods, which store and retrieve session data associated by string names.

JSP Engine

Java Server Pages (JSP) provide dynamic content for web pages. With JSP, you can embed Java source code within HTML source files. When a client requests a JSP's URL, the JSP engine (running within the web server) generates Java source code that uses the Servlet API. The web container compiles the servlet code and instantiates a Java thread to execute the servlet. By writing Java code within our JSP source file, we can access other components within the J2EE architecture, such as enterprise Java beans. JSP programs are simpler to write than servlets because the JSP engine generates servlet code for you.

JSP has several types of programming elements: declarations, scriptlets, expressions, directives, implicit objects, and comments. During initialization, the server invokes the jspInit() method if you provide one. The server also places scriptlets and expressions inside the generated _jspService() method, and calls jspDestroy() (if provided) during shutdown. The jspInit() routine is a good spot to place one-time initializations.

Let's examine these JSP elements now.

JSP Comments

The JSP tags <%-- and --%> surround comments, which do not appear in the generated HTML source file. Here's an example of a JSP comment that documents the name of our JSP program.

<%--
  paymentGet.jsp
--%>

Declarations

A JSP declaration starts with <%! and terminates with %>. We use JSP declarations to define class-wide variables and methods. Variables declared within JSP declarations appear outside the _jspService() method. These class-wide variables are initialized when the JSP page is created and have class scope. Here's an example.

<%!
  private Loan loanEJB = null;
  DecimalFormat money = new DecimalFormat("$###,###.00");
  DecimalFormat percent = new DecimalFormat("##.000");
%>

Scriptlets

A scriptlet is a block of Java code executed at request-processing time. The JSP engine compiles scriptlet code in the order that it appears in your program and places it inside the _jspService() method of the generated servlet. Scriptlets appear within the JSP tags <% and %>. The following scriptlet instantiates a Java Date object and writes it to the servlet response stream (out), along with some HTML formatting tags.

<%
  out.println("<h1>Example using scriptlet</h1>");
  out.println("<h2>Hello, today is " +
        new java.util.Date() + "</h2>");
%>

Expressions

An expression is a shorthand notation for a scriptlet that outputs a value in the servlet response stream. Like scriptlets, the generated code appears inside the servlet's _jspService() method. During request processing, the Java VM evaluates the expression and converts it to a Java string. JSP expressions are extremely convenient for writing HTML code without those tedious out.println() statements. Use JSP tags <%= and %> to embed expressions. The following HTML code contains embedded expressions and is arguably more readable than its equivalent scriptlet presented above.

<h1>Example using expressions</h1>
<h2>Hello, today is <%= new java.util.Date() %></h2>

Implicit Objects

A JSP program instantiates several implicit objects through the automatically generated servlet code. These implicit objects simplify JSP authoring because you do not need to declare or instantiate them. Implicit objects are not available inside JSP declarations, but they are available inside scriptlets and expressions. The following table lists several of the most commonly used implicit objects.

Table 3.2. Commonly Used Implicit Objects
Object Scope Use
request Request scope Encapsulates the request; passed as a parameter to _jspService()
response Page scope Encapsulates the response; returned as a parameter to _jspService()
out Page scope Sends output to client
session Session scope Encapsulates session state
exception Page scope Refers to runtime exception that resulted in error page being invoked; only available in error page

One of the important implicit objects is the request object, which is an instance of javax.servlet.ServletRequest. This object is passed to the JSP by the web container as a parameter to the automatically generated _jspService() method. The request object has “request scope,” which means that it is available to all pages processing the same request. A useful ServletRequest method is getRequestURI(), which saves the URL of the current page for later navigation.

The implicit session object is an instance of javax.servlet.http.HttpSession. This object has “session scope,” which means that the same user may share multiple requests. Session objects are convenient for saving and restoring session state in applications where the size of the data is small and easily managed. This is done with the session object's putValue() and getValue() methods.

JSP Directives

The JSP tags <%@ and %> surround JSP directives. Directives are messages to the JSP engine from the JSP file. They do not produce any output to the client. JSP directives have page scope (the results of the directives are available to actions and scriptlets within one page). In the following example, we use a page directive to import Java classes for our Loan EJB. (Without the correct classes named in the import directive, a compilation error occurs when the JSP engine compiles the generated Java servlet code.)

<%@ page import="LoanVO,Loan,LoanHome,javax.ejb.*, javax.nam-
ing.*, javax.rmi.PortableRemoteObject, java.rmi.RemoteExcep-
tion, java.util.*, java.text.*" %>

The JSP payment Client

Our JSP payment program presents an HTML form entitled “Monthly Payment Calculator” which prompts a user for a loan amount, annual interest rate, and term. Figure 3-6 shows the initial screen for this JSP program. After providing input values, the user clicks the “Calculate” button. Figure 3-7 shows the result of this calculation. The program displays the Monthly Payment (Principal and Interest) for the loan values that the user provided. To recalculate, the user clicks “Calculate with Different Parameters” which returns to the original page and saves the most recent input values.

Figure 3-6. Initial Screen for the Monthly Payment Calculator


Figure 3-7. Result Screen for the Monthly Payment Calculator


If you're shopping for a home loan or refinancing, this is a handy program to run from your browser.

paymentGet.jsp

The payment web component consists of two JSP files. The first program, paymentGet.jsp, collects user input, encapsulates data in a request object, and invokes the second program (paymentPost.jsp) to perform the monthly payment calculation. We store user request input in the HttpSession object (in program paymentPost.jsp). With this approach, the user doesn't have to provide all the data fields each time.

Listing 3.10 is the source code for paymentGet.jsp with comments to help explain the JSP tags.

Listing 3.10. paymentGet.jsp
<%--
  paymentGet.jsp
--%>

<%--
  The following scriptlet assigns the current URL to String
  requestURI and then stores this object into the implicit
  session object.
  We then attempt to assign to variables
  s_amount, s_rate, and s_term values stored previously
  in the session object.

  Obviously, the first time the user executes this page,
  these values will be null.
  To avoid null String runtime errors, we assign
  the empty String "" to them if they're indeed null.

  We use this mechanism to save the user's input data.
  Then the user only has to provide input
  for those parameters he or she wants to
  change for subsequent calculation requests.
--%>

<%
  String requestURI = request.getRequestURI();
  session.putValue("url", requestURI);
  String s_amount = (String)session.getValue("amount");
  String s_rate = (String)session.getValue("rate");
  String s_term = (String)session.getValue("term");
  if (s_amount == null) s_amount = "";
  if (s_rate == null) s_rate = "";
  if (s_term == null) s_term = "";

%>
<html>
<head>
    <title>Monthly Payment Calculator</title>
</head>

<body bgcolor=white>
<h1><b><center>
Monthly Payment Calculator
</center></b></h1>

<hr>
<p>
Please supply the following details:
<p>

<%--
  The HTML tag <form> allows us to request user input
  and provide this data to the URL named in the
  action argument: paymentPost.jsp.

  The form's elements include textual input
  to specify the loan amount,
  textual input to specify the rate,
  and a select element that requests
  one of three term lengths, 15, 20, or 30 years.
  We use expressions to provide default values
  for the amount and rate form input elements.
--%>

<form method="post" action="paymentPost.jsp">
Loan Amount: $
<input type="text" name="amount" value="<%= s_amount %>" size="15">
<br>

Interest Rate:
<input type="text" name="rate" value="<%= s_rate %>" size="10"> %
<br>
Loan Term:
<select name="term">

<%--
  The following scriptlet checks the value of s_term
  to determine the default value for the select element.
--%>

<%
    if (s_term.equals("30"))
      out.println("<option selected value="30">30");
    else
      out.println("<option value="30">30");
    if (s_term.equals("20"))
      out.println("<option selected value="20">20");
    else
      out.println("<option value="20">20");

    if (s_term.equals("15"))
      out.println("<option selected value="15">15");
    else
      out.println("<option value="15">15");
%>

</select> Years
<p>

<%--
  The user clicks "Calculate"
  to submit the input data to the JSP named
  in the form tag action argument.
  Clicking "Reset" returns
  the input values to their default settings.
--%>

<input type="submit" value="Calculate">
<input type="reset" value="Reset">
</form>
</body>
</html>

Design Guideline

Our application is very simple, so we store session data inside the implicit session object. In large-scale J2EE applications, it is preferable to save session state inside an EJB component. If the session state represents persistent data, use an entity bean to save the data to permanent storage (a database). If the session state represents conversational state (data relevant throughout the session), use a stateful session bean.


paymentPost.jsp

Now let's examine the second JSP program of our payment web component. File paymentPost.jsp in Listing 3.11 illustrates a few more features of JSP programming and shows the true power and ease of using JSP to interface with EJB components. This program parses user input and creates instances of our Loan EJB and LoanVO objects. The program also invokes the Loan EJB's monthlyPayment() method, displays the results of the calculation, and saves the values submitted by the user in a session object for subsequent calculations.

Listing 3.11. paymentPost.jsp
<%--
  paymentPost.jsp
--%>

<%--
  The following page directive tells the JSP engine to
  import the named classes and packages when compiling
  the generated servlet code.
--%>

<%@ page import="LoanVO,Loan,LoanHome,
LoanObjectException,javax.ejb.*,
javax.naming.*,javax.rmi.PortableRemoteObject, java.rmi.Remo-
teException, java.text.*" %>

<%--
  The following declaration defines class-wide variables
  and methods jspInit() and jspDestroy().
  Recall that these declarations have class scope.
  We must place any method declarations inside a JSP
  declaration.
  We declare a Loan remote interface object and
  initialize it to null.

  We also declare two DecimalFormat objects
  (money and percent)
  to format money values and percent values.

  The web server invokes jspInit() during initialization
  and jspDestroy() during shutdown.
  We put our EJB lookup() and create() calls in jspInit(),
  making this a one-time initialization.
--%>

<%!
  private Loan loanEJB = null;
  DecimalFormat money = new DecimalFormat("$###,###.00");
  DecimalFormat percent = new DecimalFormat("##.000");

   public void jspInit() {
      try {
         InitialContext ic = new InitialContext();
         Object objRef = ic.lookup(
               "java:comp/env/ejb/TheLoan");
         LoanHome home =
               (LoanHome)PortableRemoteObject.narrow(
               objRef, LoanHome.class);
         loanEJB = home.create();

      } catch (Exception ex) {
        System.out.println("Unexpected Exception: "
                 + ex.getMessage());
      }
   }

   public void jspDestroy() {
         loanEJB = null;
   }
%>
<%--
  The following scriptlet accesses the implicit
  session object to obtain the URL of the
  request page.
  It then accesses the implicit request object
  to obtain the user input values for the loan
  amount, rate, and term.

  It stores these values into the session object
  to use as the new default values
  in the request page.
--%>

<%
  String requestURI = (String)session.getValue("url");
  String s_amount =
             (String)request.getParameter("amount");

  String s_rate = (String)request.getParameter("rate");
  String s_term = (String)request.getParameter("term");

  session.putValue("amount", s_amount);
  session.putValue("rate", s_rate);
  session.putValue("term", s_term);
%>

<html>
<head>
    <title>Monthly Payment Calculator</title>
</head>

<body bgcolor=white>
<h1><b><center>
Monthly Payment Principal & Interest Result
</center></b></h1>
<hr>

<%
  Double d_amount;
  Double d_rate;
  int i_term;
  String errorString = null;
  // We make sure all parameters have valid values by
  // placing the Double constructor call and Integer's
  // parseInt() call in a try block.
  // These routines generate a NumberFormatException
  // if the user input contains non-numerical characters
  // or other formatting anomalies.

  try {
    d_amount = new Double (s_amount);
    d_rate = new Double (s_rate);
    i_term = Integer.parseInt(s_term);

    // We create a LoanVO object with the user supplied
    // values and invoke our Loan EJB's business method
    // monthlyPayment().

    LoanVO myloan = new LoanVO(d_amount.doubleValue(),
           d_rate.doubleValue(),i_term);

  double monthly_payment =
         loanEJB.monthlyPayment(myloan);
%>

    <p>
    Amount = <%= money.format(d_amount.doubleValue()) %>
    <br>
    Rate = <%= percent.format(d_rate.doubleValue()) %> %
    <br>
    Term = <%= s_term %> Years
    <br>
    <p>
    <b>Monthly Principal & Interest is: </b>
    <%= money.format(monthly_payment) %>
    <p>

<%
  } catch (NumberFormatException ex) {
  // This is the catch handler for bad user input.
    errorString = "You have left a field empty or " +
      "specified an incorrect value for a number.<br>" +
      "Make sure there are no special characters, " +
      "commas, or symbols embedded in the numbers.";
  } catch (LoanObjectException ex) {
  // This is the catch handler for
  // bad LoanVO object values.
      errorString = "Loan amount must be at least 1 " +
            "<br>and rate cannot be zero.";
  }
  if (errorString != null) {

  // We use html formatting tags to create an error box
  // to display errorString
  // with red lettering so that it will stand out.
%>

<p STYLE="background:#e0e0e0;color:red;
font-weight:bold;border:double thin;padding:10">
<%= errorString %>
</font>
</center>

<%
  } // end if
%>

<%--
  We use an expression inside the html href tag to provide
  a dynamic link to the previous request page.
--%>

<p><a href="<%= requestURI %>">
Calculate With Different Parameters</a>
</body>
</html>

The Role of a JSP Client

What is the role of a JSP within a J2EE application and what are the benefits of using JSP? Since JSP is a web component, it is easily accessible to any client with a browser and an Internet connection. JSP components are simpler to write than servlets because the JSP engine automatically generates servlet code for you. Furthermore, JSP components are really just HTML files with Java code interspersed, so they look more like HTML than Java. The ability to use Java, however, allows developers to provide dynamic content. With JSP, developers can write code to interface with servlets, EJBs, and JavaBeans. Hence, JSP is best used for the “View” or “Presentation” portion of a J2EE application.

In our example, we use JSP to prompt for user input and invoke a business method in our Loan EJB. Once we have the calculation results, simple HTML code within the JSP formats output for the user.

After examining the code in our Loan EJB, you may wonder why we don't just put the monthly payment calculation directly inside the JSP? After all, we could easily write a monthlyPayment() method and place it in a JSP declaration.

The answer is that keeping monthlyPayment() as a business method of the Loan EJB provides more flexibility. Inside the JSP, monthlyPayment() would only be available to that specific JSP. As part of the remote interface of an enterprise Java bean, however, we can access monthlyPayment() from other enterprise Java beans, a Java application client (such as application client AmortClient shown earlier), a servlet, or even another JSP.

Our Loan EJB is meant to provide a well-defined business process that can be invoked from many different clients. In general, JSP programs should not provide business processes.

Packaging the Web Component

You will most likely use a deployment tool to package the JSP web component. Web components belong in Web Archive (WAR) files which have the same format as JAR files, but with a .war extension. JSP pages go directly into the WAR file; the web designer does not “compile” them. At request processing time, the JSP engine (a part of the J2EE application server) transforms the JSP source files into servlet Java source. The Java compiler creates .class files which are executed within a new thread instantiated by the application server.

During the packaging process, you specify any EJB references (in this case, our JSP references the Loan EJB). You will also specify a Context Root (which is like a home directory for “finding” web components) and an alias for naming the initial JSP page. In our example, the Context Root is payment and the alias is paymentGet.

The deployment tool creates a deployment descriptor for the JSP component. Our deployment tool creates the deployment descriptor in Listing 3.12 for the payment web component.

Listing 3.12. Deployment Descriptor for JSP
<web-app>
 <display-name>PaymentWAR</display-name>
 <servlet>
    <servlet-name>PaymentWAR</servlet-name>
    <display-name>PaymentWAR</display-name>
    <jsp-file>/paymentGet.jsp</jsp-file>
 </servlet>

 <servlet-mapping>
    <servlet-name>PaymentWAR</servlet-name>
    <url-pattern>/paymentGet</url-pattern>
 </servlet-mapping>

 <session-config>
    <session-timeout>30</session-timeout>
 </session-config>

 <ejb-ref>
    <ejb-ref-name>ejb/TheLoan</ejb-ref-name>
    <ejb-ref-type>Session</ejb-ref-type>
    <home>LoanHome</home>
    <remote>Loan</remote>
 </ejb-ref>
</web-app>

Note that the deployment descriptor includes the EJB reference information, including its coded name (ejb/TheLoan), type (Session), and the names of the home and remote interfaces (LoanHome and Loan).

Running the Web Client

To run the JSP web component from a browser, you need to specify the URL of the J2EE server machine, the Context Root, and an alias. Here's an example.

http://manny:8000/payment/paymentGet

On port 8000 of machine manny, the Context Root is payment and the alias is paymentGet. If the browser is running on the same machine as the J2EE server, use localhost for the machine name.

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

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