JavaServer Pages for Enterprise-Level Computing

  Scott Snyder is a Software Engineer at IBM and part of the team responsible for the performance of the IBM WebSphere family of e-business software servers. He can be contacted at [email protected].

THE SERVLET API allows Web developers to use the Java programming language as a development environment for dynamic Web page creation, execution of complex business logic, and communication with third-tier data sources. However, these three activities are very distinct from each other and require different types of software development skills.

Web page creators are generally more concerned with the aesthetic aspects of the page (i.e., the placement and design of pictures, backgrounds, and frames) and less concerned about the source of the dynamic data and the data manipulation required to get it into the form required by the client request. Also there are times when information about the request is needed, such as the browser type, so that client- or request-specific content can be provided in the Web page. It would be nice to allow Web page designers to have access to this information without requiring them to learn Java, write servlets, compile them, and deploy them on their Web servers.

To give designers access to the Servlet API without them going through the write, compile, deploy cycle, Sun has defined JavaServer Pages to enable Java as a server side scripting language.

JavaServer Page Technology
The JavaServer Pages (JSP) technology uses standard HTML pages with special tags that are defined by the JSP specification. JSP uses <% and %> tags to delimit a JSP scriptlet—a set of Java code that is compiled and run as if it were in the service method of a servlet (which, in fact, it will be). Any Java code can be placed within a scriptlet, so the entire Java language can be used for scripting. In addition, the JSP specification predefines the following variables available for use in a JSP page:

  • request—An instance of javax.servlet.http.
    HttpServletRequest
    set to the client request.
  • response—An instance of javax.servlet.http.
    HttpServletResponse
    set to the client response.
  • in—An instance of java.io.BufferedReader set
    to the servlet input.
  • out—An instance of java.io.PrintWriter set to
    the servlet output.
As an example, Listing 1 is a simple JSP page that can detect the type of browser that the client is using and send the appropriate HTML content. Because there is no standard for Dynamic HTML, it may be necessary to test for the type of browser so that advanced features of each browser can be exploited. It is more efficient to determine the type of browser on the server than have to send all the page variations to the client and have some client-side script interpret the appropriate page information.

In Listing 1, a string variable is initialized with the value of the user-agent obtained using the getHeader method of the request object, and then searched for the appropriate strings to identify the Netscape or the Internet Explorer browser. Instead of returning anything fancy, a string is sent to the servlet output indicating the client type, or if it is an unknown client, the useragent string. Dynamic content is sent to the client by sending strings to the out output stream object, which is a PrintWriter predefined to correspond to the servlet output.

To output an individual expression, one can more conveniently use the JSP expression tags <%= and %>. To see how they could be used to further personalize this JSP page, see Listing 2. At the top of the page, expression tags are used to evaluate the address of the remote host as well as the day and time. The processing of the JSP expression implicitly calls out.print() for the expression being evaluated as well as doing the string conversion using a toString method as seen in the <%=today%> call. This in place expression evaluation can be used like the original server-side include (SSI) variables, and most third-party servers that support JSP still support the legacy NCSA tags used for SSI. But JSP technology can do more than simple SSI. Using the BEAN tag, several JSP pages can reuse business logic encapsulated in a JavaBean. But first, let's see how JSP pages are processed.

JSP Under The Covers
JSP files are usually processed by servlet-enabled Web Servers through a step called Page Compilation. Typically, when a file with the extension *.jsp (or *.shtml for legacy SSI files) is requested a page compile servlet is called with the JSP file as a parameter. The JSP file is read off the disk, parsed, and the static portions stored. Then a servlet is dynamically constructed, the output of which will contain the appropriate client response. This servlet is compiled by the server and if the compilation is successful, it is loaded by the class loader just like any other servlet on the server. The next time the JSP file is requested, the page compile servlet confirms that the file has not changed on disk and executes the already loaded servlet. This makes JSP significantly faster than traditional SSI because the source document is parsed only once. Once compiled, processing of JSP files is as efficient as any other servlet.

By default, the scriptlets and JSP expressions are placed in the service method of the dynamically constructed servlet (which I will abbreviate DCS). But the name of the method of the DCS that the scriptlets and JSP expressions are placed in can be specified using JSP directive tags. JSP directives use the general syntax <@>directive_name = "string_value" %>, where currently the valid directive names are:

  • language—The scripting language used in the file. Currently the only valid language, and the default, is "java".
  • method—The method that scriptlets and JSP expressions are placed in the DCS.
  • import—A comma-delimited list of packages that the DCS imports.
  • content_type—The MIME type of the DCS response. The default is "text/html".
  • implements—A comma-delimited list of Java interfaces that the DCS inherits from.
  • extends—The Java class that the DCS inherits from. This can be any valid Java class.
Class-wide variables and methods can also be declared using the The runat=server is required to indicate that this tag is for server-side processing and not to be passed on to the browser.

As this syntax indicates, almost any servlet functionality can be added to the DCS through the use of JSP directives, expressions, scriptlets, and SCRIPT tags. While this flexibility is powerful for dynamically constructing a stand-alone servlet, the real power of JavaServer Pages is in how they can be used to interact with other servlets and beans on the server.

Separating Business Logic From Display
The most powerful form of dynamic page composition that JSP supports is by using the BEAN tag. Using this tag, JSP pages can access instances of JavaBeans that were created from a class file, referred to from an HTTP session, or passed in by a servlet. The BEAN tag has several attributes controlling its name, datatype, whether introspection will be used, whether the bean needs to be dynamically constructed, and so on; see the 0.91 JSP draft specification1 for full details.

Listing 3 and Listing 4 show examples of the power of using JavaBeans with JSP. Mortgage_direct.jsp. Listing 3 is essentially an HTML form with a BEAN tag that instantiates the MortgageBean class (Listing 4). In this example, the user types in loan amount, interest rate, and loan duration and the bean calculates the monthly payment and inserts the result into the page.

When the form is submitted, an instance of the bean is looked for in the context of the DCS. If one is not available and the create attribute is set, the DCS will create an instance of the bean of a type specified by the type attribute. When the introspect attribute of the BEAN tag is equal to "yes", the set methods of the instantiated bean that correspond to the form's name variables will be run. This allows the form data to be brought into the bean and affect the results of the bean's methods. In this example, the named fields are amount, interestPerPeriod, and numberOfPayperiods, and the form button name is action.

Figure 1 shows a pictorial representation of the JSP file in a browser and the connection between the three form fields, the reply and the form button, and the bean methods that are called when the button is pressed. Because bean methods can be invoked directly from the JSP page, mortgage_direct.jsp has an explicit call to getReply() to get the monthly payment. Notice that the MortgageBean (containing the formula for calculating monthly loan payback) must still know the format of the data as it is entered into the form, thus linking the business logic to the Web page display.

figure 1

Figure 1. Pictorial representation of the JSP file in a browser and the connections called when a button is pressed.

Up until now, the examples of the Java-Server Page technology have used JSP as a scripted version of SSI where the client requests the JSP page and content is dynamically filled in for you. This model is fine for simple environments where the amount of dynamic content is limited or the interaction with the business logic is not that extensive. However it forces the Web page designer to work with and manipulate potentially large amounts of Java code. What would be more typical on large Web sites is that servlets would be used to contain some form of business logic. This could include calculations, database access to mainframe or legacy systems, or anything that servlets would normally be used for, but should not include generation of the client response. The design of the client response (the dynamically constructed HTML page) is essentially an aesthetic one, requiring graphic artists, or Web page designers, and should not be hardcoded into the servlet. Page designers need to have access to HTML design tools that can work on page content independently of the source of the dynamic content. By separating the presentation from the business logic, the look and organization of Web sites can be updated without requiring modifications of the servlets driving the response.

figure 2

Figure 2. Diagram of the JSP request model.

Figure 2 is a diagram of the JSP request model. In it a client request is made to a servlet. This servlet implements the appropriate business logic and places the data that needs to be sent to the output in an instance of a bean. This bean can be used for any purpose required by the application, including possibly JDBC access to databases, but must include public accessor (get) methods to get the private bean data that needs to be accessible to the JSP page. If the bean can be made accessible to a JSP file designated as the output, then BEAN tags can be used to access the required dynamic content. To support this functionality, Sun has defined two new interface API's.

  • com.sun.server.http.HttpServiceRequest implements the javax.servlet.http.HttpServletRequest interface and adds a setAttribute method that allows an object and a key to be stored with the request.
  • com.sun.server.http.HttpServiceResponse implements the javax.servlet.http.HttpServlet Response interface and adds a callPage method that passes a JSP page (or HTML page) to the response for output.
Listings 5-8 show the mortgage calculator implemented with a servlet invocation. This application follows the JSP request model diagram in Figure 2 except that it does not access a database as shown in the figure.

Initially, the client fills out a regular HTML form (Listing 5), which submits a POST request to MortgageServlet (Listing 6); in Figure 2 this is the Request arrow pointing to the servlet at position 1. The doGet and doPost methods call a performTask method, which takes the form attributes, does the appropriate scaling, instantiates the MortgageBean (Listing 7), and sends the scaled form parameters to the bean to be processed; this is position 2 in Figure 2.

The MortgageBean is not instantiated in the standard way using the new() method but as:


myMortgageBean = (MortgageBean)
java.beans.Beans.instantiate(getClass().getClass-
Loader(), "MortgageBean");
This is because the new() method uses the default system class loader, which may not be the same as the servlet class loader. Because the instance of the MortgageBean (myMortgageBean) must be accessible to the servlet constructed from the JSP page via the pagecompile process, it must be instantiated with the servlet class loader so that it will be visible to the DCS.

When the performTask method of the servlet is finished updating myMortgageBean, it calls the setAttribute method of HttpServiceRequest to store the bean instance with the request and then uses the callPage method of HttpServiceResponse to send a JSP file as the client response; this is position 3 in Figure 2. The JSP page (Listing 8) returns the mortgage information and fills out a duplicate of the original static form so that additional requests can be made.

Notice that the MortgageBean can now be implemented more generally because it does not have to know how the form attributes are being sent; it leaves that to the servlet. This aids reuse as different servlets can use the MortgageBean to calculate mortgages without any concern about how the input to the mortgage calculation is obtained.

In a way, the bean definition acts as a contract between the servlet writer and the Web page designer. The Web page designer is guaranteed to have access to certain state information and methods by the servlet writer; he is generally unconcerned as to how that information is obtained, and cares only that it is available when required. The servlet writer is not concerned with how the bean information will be presented to the client; only that he fulfill the interface requirements of the bean.

This Just In
JSP draft specification 0.922 was released on October 7, 1998. Most JSP implementations are based on the 0.91 draft specification as in the above discussion. Some changes introduced in the 0.92 JSP draft specification are:

  • The BEAN tag has been renamed to USEBEAN.
  • The INTROSPECT attribute of the BEAN tag is now a separate tag called SETFROMREQUEST.
  • The CREATE attribute of the BEAN tag is now a separate tag called SETONCREATE.
  • The com.sun.server.http.HttpServiceResponse.call Page(String uri, HttpServletRequest request) method has been replaced by javax.servlet. ServletContext.getRequestDispatcher(String uripath) and the com.sun.server.http.HttpServiceRequest. setAttribute(String key, Object o) method have been replaced by javax.servlet. ServletRequest. setAttribute (String key, Object o) with the new Java Servlet Development Kit 2.0 (JSDK 2.0) specification.
  • Hierarchical naming was introduced in referring to bean properties so that one could say MyBean:myProperty instead of MyBean.my Property or as in the original 0.91 specification <%= MyBean.getMyProperty() %>.
  • A tag was introduced so that bean properties could be accessed directly without explicitly using the get method for that property i.e., <%= MyBean.getMy Property() %>.
  • A tag has been added to support the display of multivalued properties using the above hierarchical naming with both implicit and explicit loop indices (used in conjunction with the DISPLAY tag above).
  • Conditional inclusion of statements with the and tags.
  • Implicit beans, exception and request environment, are created, which are used to hold error information and request information, respectively.
  • Beans can now exist for the life of an application, as well as for the original request and session.
  • The METHOD, IMPLEMENTS, and EXTENDS directives have been removed.
What can we infer from these changes? The bean attributes have been promoted to full tags, perhaps as a way of applying them to container objects other than beans. The hierarchical naming as well as the DISPLAY and LOOP tags also seem to support this because they remove the Java-specific syntax to property access.

Servlets are being promoted as being part of a Web application, a "set of cooperating resources...that share information to achieve some end functionality."2

The removal of the METHOD, IMPLEMENTS, and EXTENDS directives seems to indicate that Sun is encouraging developers not to place too much business logic within the JSP page, but to encapsulate it within a bean or a servlet.

JavaServer Pages is an exciting and rapidly evolving technology for server side Java, as you can see from the number of changes in the specification from 0.91 to 0.92, and will be a key component, along with Enterprise JavaBeans, in Sun's positioning of Java as the premier tool for server and enterprise level computing.

References

  1. The 0.91 JSP draft specification is no longer available on the Sun Web site. Check any third-party server vendor that supports JSP e.g., IBM's WebSphere Application Server documentation at www.software.ibm.com/webservers/appserv/doc/guide/asgl1mst.html.
  2. The 0.92 draft specification is available from Sun at java.sun.com/products/jsp/jsp092.html.