What we expect from a Web site has changed dramatically over the last few years. In the early days of the Web, just finding a site with useful information was a thrill. Today we expect Web sites to be highly dynamic with advanced search capabilities, personalization, online ordering, and accurate shipment tracking functions -- all accessible through an easy-to-use, visually appealing user interface. Developing this type of site requires the cooperation of many people with different skills. Perhaps the largest challenge is keeping the request-processing code and HTML markup separate so they can be worked on independently. JavaServer Pages (JSP) is a popular technology that can be used to accomplish this.
What we expect from a Web site has changed dramatically over the last few years. In the early days of the Web, just finding a site with useful information was a thrill. Today we expect Web sites to be highly dynamic with advanced search capabilities, personalization, online ordering, and accurate shipment tracking functions — all accessible through an easy-to-use, visually appealing user interface. Developing this type of site requires the cooperation of many people with different skills. Perhaps the largest challenge is keeping the request-processing code and HTML markup separate so they can be worked on independently. JavaServer Pages (JSP) is a popular technology that can be used to accomplish this.
Java has proven itself as a great language and platform for server-side applications. Java servlets first appeared in 1997 and have been embraced by all major Web servers as the alternative to Common Gateway Interface (CGI) scripts. As described in last month’s column (available online at http://www.linux-mag.com/2002-04/java_01.html), servlets are applications created by extending certain Java classes. They are managed by a Web container that provides the runtime environment and access to other resources. The container runs in a permanent process, giving servlets a performance advantage over CGI scripts, which can require a new process to be created for each request.
But there’s a problem with servlets: besides the request-processing code, a servlet also includes statements to emit the HTML elements for the response. This makes it virtually impossible for a Web designer without programming experience to modify the design of the Web application, since even a minor design changes requires help from a programmer.
JavaServer Pages (http://java.sun.com/products/jsp) were added to the Java toolbox in 1999 to help solve this problem. A JSP is a text file (with a .jsp suffix) that includes standard HTML elements along with JSP elements (that look similar to HTML) to control the dynamic portions of the page. These can be things such as search results, shopping cart contents, or a delivery tracking number. The JSP elements map to Java methods that are called when Web server processes the request for the JSP. By placing the application logic into a simple HTML-like element, anyone familiar with HTML can add dynamic behavior to a Web page without needing to know Java programming. Conversely, a programmer can develop the application in Java without needing to know how the output will be presented.
While it may sound like JSP replaces servlets, the truth is that JSP is typically used in combination with servlets. In fact, there’s an even closer connection between JSP and servlets.
When the Web container receives the first request for a JSP, it actually converts the JSP into a servlet. This servlet is then compiled and executed by the container, and sends its response to the browser. Subsequent requests for the same JSP invoke the already-compiled servlet. When a JSP is modified, the next request for that page causes the container to translate and compile the modified file.
Let’s take a closer look at what a JSP file might look like.
As mentioned previously, a JSP is a text file with a .jsp file extension to tell the server what it is. The file contains static content plus the JSP elements. The static content is called template text and can be anything the client can handle (HTML, WML, or text). Listing One shows a sample JSP file.
There are three types of JSP elements that can be used in a page: directive elements, scripting elements, and action elements.
A directive element has the form <%@ directive attr= “value” … %> and describes the page itself. These are things that are the same no matter when, or by whom, the page is requested.
There are three directive elements, on lines 1-3. The page directive on line 1 has two attributes that define the type of content (MIME type) the page will contain and an error page to return if there are any runtime errors.
Lines 2 and 3 contain the taglib directive. This directive shows that we wish to make use of a custom tag library. We’ll go into more detail on custom tag libraries when we cover action elements below. For now, just notice that each use of taglib has a different value for its prefix attribute.
Scripting elements were the original way to add dynamic behavior in JSP, by allowing you to place Java code in the JSP file. There are three types of scripting elements:
- A scriptlet (enclosed within <% … %>) that can be used to execute any number of Java statements.
- An expression (enclosed within <%= … %>) that executes one Java expression and places the result in the response.
- A declaration (enclosed within <%! … %>) that declares a Java variable or method.
Line 9 contains a scripting expression of Java code that creates a new java.util.Date object. The container executes the expression, creating the object. It then adds a string representation of the object to the response. This places the current date in the response.
You should avoid using too many scripting elements because it takes us back to the problem we set out to solve: a mixing of code and markup elements. That’s why there’s an easier way: action elements.
Action elements are the preferred way to add dynamic behavior to a Web page, and have mostly superseded scripting elements. JSP supports two types of actions: standard actions and custom actions. Both types must have an XML-style namespace prefix to uniquely identify them.
Standard actions use the jsp prefix and are defined as part of the JSP specification (http://java.sun.com/products/jsp). Line 23 contains a standard action element, <jsp:include>. This action functions like the C and C++ #include directive, placing the contents of the page attribute directly into the the response. In this case, since the page is another JSP, that page is executed and its output placed into the response. This action is typically used for shared page fragments such as headers and footers.
Other standard actions can let you access properties in a JavaBean or even let another Web resource continue the processing of a request. (For more on JavaBeans, see “Bean Soup.”)
JavaBeans is the term used for a Java class that represents a “component” in its broadest sense. They are often used in JSP and servlets to encapsulate information (called properties) about data, such as customers and products. Each instance of a JavaBeans class is called a bean, and every bean contains only properties.
A JavaBeans class has a no-argument constructor. To read and set a property, you use the getPropertyName() and the setPropertyName() methods.
A typical use for a bean would hold information about a GUI widget, such as a text box. It might have properties for the text, font, color, size, etc. Another application could read and modify the bean’s properties.
Beans are also often used to represent business objects, such as a customer bean with properties like name, address, and telephone number. You can think of a bean as a container of information that can be discovered at runtime and accessed by other classes in a generic way, such as by the <c:expr> action elements shown in Listing One.
Despite the similarity in names, JavaBeans and Enterprise JavaBeans (EJB) don’t have a lot in common. Although EJB’s are also components similar to JavaBeans, they must follow a large set of rules and can only be used within a special EJB container that’s part of the J2EE package. For more on Enterprise JavaBeans, see Sun’s J2EE Web site (http://java.sun.com/j2ee/).
Custom actions are Java classes that follow a specific interface. These classes can access the entire set of Java APIs which let you do nearly anything you can do in Java. They are packaged into custom tag libraries that also contain a mapping of an action element to a Java method and are accessed from a JSP via the uri attribute of the taglib directive element.
Each action element also contains a prefix attribute. In lines 2 and 3, we’ve loaded two tag libraries and assigned them the prefixes c and mylib. These custom prefixes are used with the action element to specify which library contains that specific custom action.
Listing One: Sample JSP Page: foo.jsp
1 <%@ page contentType=”text/html” errorPage=”/error.jsp” %>
2 <%@ taglib prefix=”c” uri=”http://java.sun.com/jstl/ea/core” %>
3 <%@ taglib prefix=”mylib” uri=”http://mycompany.com/mylib” %>
7 <h1>Product List</h1>
8 Here’s a list of our products as of
9 <%= new java.util.Date() %>
11 <mylib:getProducts var=”productList” />
14 <c:forEach items=”$productList” var=”current”>
16 <td><c:expr value=”$current.name” /></td>
17 <td><c:expr value=”$current.descr” /></td>
18 <td><c:expr value=”$current.price” /></td>
23 <jsp:include page=”/footer.jsp” />
For example, the action corresponding to the <mylib: getProducts> action element on line 11 can be found in the library associated with the mylib prefix by the taglib directive on line 3.
The call on line 11 to <mylib:getProducts> specifies that the container should call the getProducts action in the tag library associated with mylib. This calls a Java method (probably, but not necessarily called getProducts()). We don’t know exactly what it does, but based on its name, we can assume that it retrieves product information from a database, and saves it in the variable productList, as specified by the var attribute of the getProducts element. Since a custom action is, as its name implies, custom-made for a specific application, it’s up to the Java programmers on the team to decide which custom actions to develop, what they should do, and what they return.
Custom Tag Libraries and the JSTL
Many projects have “reinvented the wheel” by writing custom actions to handle simple tasks. The Apache Jakarta Taglibs Project (http://jakarta.apache.org/taglibs) has a number of custom tag libraries that handle various tasks. One of these is the JSP Standard Tag Library (JSTL, http://jakarta.apache.org/taglibs/doc/standard-doc/intro.html), which is working to set standards that define actions for database access, flow control, XML processing, external resource access, and internationalization, as well as a language for easy access to request parameters and other data. The JSTL is currently in its Early Access Release and is scheduled to be officially released this summer.
The taglib directive on line 2 loads the JSTL Early Access library, and uses “c” as its prefix. The <c:forEach> action on line 14 is a loop that evaluates its body (the elements from lines 15 through to the end of the <c:foreach> action on line 20) once for each element in the collection specified by the items attribute, storing the current element in the variable named by the var attribute. In this example, the collection contains JavaBeans representing products which were retrieved by the <mylib:getProducts> custom action on line 11. The three <c:expr> actions on lines 16, 17, and 18 put the values of the current bean’s properties into the response.
JSP and J2EE
JSP is one of the technologies that makes up the J2EE, or Java 2 Enterprise Edition. J2EE is a collection of Java technologies that are useful for the server side of the enterprise application equation.
For enterprise applications, the system components are often assigned to different “tiers,” that can run on the same or different servers to provide scalability. In J2EE 1.3, the four tiers are the Client Tier, the Web Tier, the Business Tier, and the Enterprise Information System (EIS) Tier. The Client Tier holds general-purpose clients (e.g., HTML or WML browsers) as well as regular GUI applications. The Web Tier is made up of JSP and servlets. The Business Tier is the domain of the Enterprise JavaBeans (EJB). The EIS Tier contains databases and legacy systems. J2EE also includes APIs that can be used to access databases (JDBC), process XML (JAXP, etc.), use a naming and directory service (JNDI), and access a messaging service (JMS), among other things.
|Figure One: J2EE Request Flow|
Figure One shows a scenario involving JSP and all the tiers. A user fills out a form in a Web browser (Client Tier) and submits it. The request is received by a servlet (Web Tier), that validates the input (date and number formats, for instance). It then locates an EJB component (Business Tier) responsible for processing this type of request. The EJB accesses a database (EIS Tier) that returns a result (e.g. a list of items retrieved from the database). When the servlet gets the result, it passes it on to the JSP page, which merges the dynamic data with static markup (a navigation bar, a common header and footer, etc.) and sends back the complete response to the browser. The communication between the servlet and the JSP is based a mechanism defined by the servlet specification: the RequestDispatcher and request attributes. You can read more about the RequestDispatcher in the servlet specification (http://java.sun.com/products/servlet/).
So, do you need a complete J2EE environment to use JSP? Not at all. For a simple application, such as a searchable employee directory, a JSP that accesses a database using a custom action fits the bill perfectly. More complex applications often use a servlet for the request processing and JSP for the user interface. This gives you the best of both worlds: a programmer can use the full power of Java and APIs for request processing in the servlet, and a Web designer can design the site using JSP to add dynamic content. As long as you use only JSP and servlets, all you need is a Web container and the Java 2 Standard Edition (J2SE) environment.
Deploying your JSP
To deploy a JSP on your system you need a Web server that supports the JSP specification. Apache Tomcat 4 is the reference implementation for the JSP 1.2 and the Servlet 2.3 specifications and works great as a JSP development server. For more information on setting up Tomcat, see “Hangin’ With Tomcat” in the October 2001 issue (http://www.linux-mag.com/2001-10/tomcat_01.html).
Once Tomcat is installed, adding a JSP is as simple as placing it in a directory underneath $CATALINA_HOME/ Webapps (remember, Tomcat expects to find applications in the Webapps directory and treats it as though it were equivalent to the document root). For example, you could copy our JSP file foo.jsp to $CATALINA_HOME/Webapps/examples/ jsp/mytest/foo.jsp and then access it by browsing the URL http://localhost:8080/examples/jsp/mytest/foo.jsp. Note that you do not necessarily need to do anything with the web.xml file, unless you need the special functionality it provides (see last month’s column on servlets at http://www.linux-mag.com/2002-04/java_01.html for more on the web.xml file).
Tomcat 4 comes with JSP examples that you can play with, as well as JavaDocs for both the JSP and Servlet APIs. The JSP examples are located in a Web application (directory) named examples, organized according to the standard layout defined by the servlet specification. This layout was described in detail in last month’s column.
By now, you’re hopefully beginning to see how the different pieces of the Java puzzle fit together and you can start to experiment on your own. A useful next step would be to further learn more about taglibs, which are covered in the extensive Tomcat documentation and on the Jakarta site as well (http://jakarta.apache.org/taglibs/). You should also check out the JSP Specification, Sun’s tutorial (http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPIntro.html), and the JSPInsider (http://www.jspinsider.com/index.view) to learn more about JSP.
Hans Bergsten is a member of the working groups for the Servlet, JSP and JSTL specifications, and the author of O’Reilly’s JavaServer Pages book. You can reach him at firstname.lastname@example.org.