Sep 9, 2022 3:00 AM

What is JSP? Introduction to Jakarta Server Pages

One of the original Java web technologies, JSP is still widely used with servlets and JSTL. Here's how to use Jakarta Server Pages to build dynamic web pages that connect to the Java back end.

AnthiaCumming / Getty Images

Jakarta Server Pages (formerly JavaServer Pages) is a Java standard technology that developers use to write dynamic, data-driven web pages for Java web applications. JSP is built on top of the Java Servlet (aka Jakarta Servlet) specification and is one of the Java web technologies included for ongoing support and upgrades in Jakarta EE.

JSP and servlets typically work together, especially in older Java web applications. From a coding perspective, the most obvious difference between JSP and servlets is that with servlets you write Java code and then embed client-side markup (like HTML) into that code. With JSP, you start with the client-side script or markup, then embed JSP tags to connect your page to the Java back end.

Think of JSP as a way to write markup with superpowers for interacting with the back end. Usually, markup like HTML is sent to the client where it interacts with the back-end server via JavaScript. JSP pre-processes the HTML with special commands to access and use server capabilities, then sends that compiled page to the client.

JSP and JSF

JSP is closely related to JSF, or Jakarta Server Faces (formerly JavaServer Faces). JSF is a Java specification for building model-view-controller (MVC) web applications. It is the standard for Java web frameworks like Eclipse Mojarra, MyFaces, and PrimeFaces. While it's not uncommon to see JSP used as the front end for older JSF applications, Facelets is the preferred view technology for modern JSF implementations.

Do developers still use JSP?

Developers do still use JSP for some applications. It's a simpler technology than more modern approaches like Jamstack, or a template engine like Thymeleaf, but sometimes simple is the way to go.

JSP is a core Java web technology. As developers, we can build JSP pages relatively quickly and easily, and they interact seamlessly with servlets in a servlet container like Tomcat. You could say that JSP is the Java ecosystem equivalent of PHP and ASP in the .NET world.

You will encounter JSP in older Java web applications. From time to time, you may still find it useful for building simple, dynamic Java web pages. As a Java developer, you should be familiar with JSP and how to use it in your programs.

Writing JSP pages

A simple JSP page consists of HTML markup embedded with JSP tags. JSP files have the .jsp extension. The JSP server (also called a JSP container) is configured to direct an HTTP request to a specific JSP page, which is then responsible for rendering an HTTP response.

When the request arrives, the file is processed on the server and the HTML is rendered as the application view, a web page. The embedded JSP tags will be used to call server-side code and data. The ultimate product of the JSP is vanilla HTML that the client browser can understand as-is. The diagram in Figure 1 shows the interaction between HTML, JSP, and the web application server.

IDG

Figure 1. Overview of a Jakarta Server Pages (JSP) page in a web application.

Listing 1 shows a simple JSP page.

Listing 1. A simple JSP page


<html>
  <body>
    <p>${2 * 2} should equal 4</p>
  </body>
</html>

Here, you see a block of HTML that includes a JSP expression, which is an instruction to the Java server written using Expression Language (EL). In the expression ${2 * 2}, the ${} is JSP syntax for interpolating code into HTML. The dollar sign with curly braces tells the JSP processor: “Hold on for a second, we’re about to start talking about something special you need to take care of."  When executed, the JSP page will output the results of executing whatever is inside the expression. In this case, the output will be the number 4.

JSP in the servlet container

JSP pages must be deployed inside a servlet container. In order to deploy a Java web application based on JSP and servlets, you will package your .jsp files, Java code, and application metadata in a .war file, which is a simple .zip file with a conventional structure for web applications.

Once you've loaded the JSP into your servlet container, it will be compiled into a servlet. JSPs and servlets share similar characteristics, including the ability to access and respond to request objects.

How to use JSP with Tomcat

We'll use an example application in Tomcat to get you started with Jakarta Server Pages. If you don't already have Tomcat installed, browse over to the Tomcat download page and select the Tomcat installation for your operating system. As of this writing, Tomcat 10 is the current release, compatible with Jakarta Servlet 6 and Jakarta Server Pages 3.1.

You can install Tomcat as a Windows service, or run it from the command line with /bin/catalina.sh start or /bin/catalina.bat. Either way, start up Tomcat, then go to localhost:8080 to see the Tomcat welcome page shown in Figure 2.

IDG

Figure 2. The Tomcat welcome page.

Implicit objects in JSP

On the Tomcat welcome page, click the Examples link, then click JSP Examples.

Next, open the Implicit Objects Execute web application. Figure 3 shows this example application's output. Take a minute to study the output. The elements it describes are always available by default inside a JSP page.

IDG

Figure 3. Sample output for a JSP page.

Note that no code changes are required between JSP 2.0 and JSP 3.0, which is the current update for Jakarta EE. The Implicit Object example uses JSP 2.0.

Request parameters

Implicit objects are built-in objects accessible via a JSP page. When you are developing a web page, you will use these objects to access things like request parameters, which are the data sent over from the client browser when issuing an HTTP request.

Consider the browser URL for the Implicit Objects application: http://localhost:8080/examples/jsp/jsp2/el/implicit-objects.jsp?foo=bar.

Note that there is nothing special about this page; we are just using it to see how the URL parameter is accessed. The param is ?foo=bar, and you can see it reflected in the output on the web page, where the table shows EL Expression and the value is bar. To test this out, change the URL to http://localhost:8080/examples/jsp/jsp2/el/implicit-objects.jsp?foo=zork, hit Enter, and you'll see the change reflected in the output.

This example is a very simple introduction to using JSP tags to access server-side request parameters. In this case, the JSP page uses the built-in (implicit) object called param to access the web application's request parameters. The param object is available inside the JSP expression syntax that you saw in Listing 1. In that example, we used an expression to do some math: ${2 * 2}, which resulted in the output of 4. In this case, the expression is used to access an object and a field on that object: ${param.foo}. Next, we'll look more closely at the Implicit Objects example.

JSP in a web application

On the Implicit Objects page, click the back arrow, followed by the Source link. This will lead you to the JSP code for the Implicit Objects web application, which is shown in Listing 2.

Listing 2. JSP code for the Implicit Objects web application


<%@page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<html>
  <head>
    <title>JSP 2.0 Expression Language - Implicit Objects</title>
  </head>
  <body>
    <h1>JSP 2.0 Expression Language - Implicit Objects</h1>
    <hr>
    This example illustrates some of the implicit objects available
    in the Expression Language.  The following implicit objects are
    available (not all illustrated here):
    <ul>
      <li>pageContext - the PageContext object</li>
      <li>pageScope - a Map that maps page-scoped attribute names to
          their values</li>
      <li>requestScope - a Map that maps request-scoped attribute names
          to their values</li>
      <li>sessionScope - a Map that maps session-scoped attribute names
          to their values</li>
      <li>applicationScope - a Map that maps application-scoped attribute
          names to their values</li>
      <li>param - a Map that maps parameter names to a single String
          parameter value</li>
      <li>paramValues - a Map that maps parameter names to a String[] of
          all values for that parameter</li>
      <li>header - a Map that maps header names to a single String
          header value</li>
      <li>headerValues - a Map that maps header names to a String[] of
          all values for that header</li>
      <li>initParam - a Map that maps context initialization parameter
          names to their String parameter value</li>
      <li>cookie - a Map that maps cookie names to a single Cookie object.</li>
    </ul>

    <blockquote>
      <u><b>Change Parameter</b></u>
      <form action="implicit-objects.jsp" method="GET">
          foo = <input type="text" name="foo" value="${fn:escapeXml(param["foo"])}">
          <input type="submit">
      </form>
      <br>
      <code>
        <table border="1">
          <thead>
            <td><b>EL Expression</b></td>
            <td><b>Result</b></td>
          </thead>
          <tr>
            <td>\${param.foo}</td>
            <td>${fn:escapeXml(param["foo"])}&nbsp;</td>
          </tr>
          <tr>
            <td>\${param["foo"]}</td>
            <td>${fn:escapeXml(param["foo"])}&nbsp;</td>
          </tr>
          <tr>
            <td>\${header["host"]}</td>
            <td>${fn:escapeXml(header["host"])}&nbsp;</td>
          </tr>
          <tr>
            <td>\${header["accept"]}</td>
            <td>${fn:escapeXml(header["accept"])}&nbsp;</td>
          </tr>
          <tr>
            <td>\${header["user-agent"]}</td>
            <td>${fn:escapeXml(header["user-agent"])}&nbsp;</td>
          </tr>
        </table>
      </code>
    </blockquote>
  </body>
</html>

JSP functions

If you're familiar with HTML, then the code in Listing 2 should be fairly comprehensible. You have the expected HTML <td> elements, followed by the ${ } JSP expression syntax introduced in Listing 1. But notice the value for param.foo:


<td>${fn:escapeXml(param["foo"])}&nbsp;</td>

Here, the fn:escapeXML() is a JSP function.

A JSP function encapsulates a chunk of reusable functionality. In this case, the functionality is to escape XML. JSP offers a variety of functions, and you can also create functions yourself. To use a function, you import its library into your JSP page, then call the function.

In Listing 2, we include the escapeXML function with the following line:


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

The syntax is pretty clear: it imports the required functions and assigns them a prefix (in this case "fn") that can be used in all following expressions.

The Jakarta Standard Tag Library (JSTL)

The import line in Listing 2 calls taglib, which is short for tag library. In this case, we've imported the Jakarta Standard Tag Library (JSTL). Tag libraries define reusable bits of functionality for JSP. JSTL is the standard tag library, containing a collection of taglibs that ship with every servlet and JSP implementation, including Tomcat.

The "functions" library is just one of the taglibs included with JSTL. Another common taglib is the core library, which you import by calling:


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

Like "fn", the "c" designation is conventional; you will see it across most JSP pages.

Securing JSP pages with JSTL

The following example tag is from the JSTL core library:


<c:out value = "${'<div>'}"/>

This tag outputs the <div> tag with the XML already escaped. The function is important because outputting content directly to a web page via ${variable} opens the door to script injection attacks. This simple function is used to protect web pages from such attacks.

The core library also includes various tags for iteration and flow control (like "if ... else" handling).

Calling taglibs in JSP pages

Now that you've got a handle on JSP basics, let's make a change to the example application. To start, locate the Implicit Objects application in your Tomcat installation. The path is: apache-tomcat-8.5.33/webapps/examples/jsp/jsp2/el.

Open this file and locate the functions include:


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

Just below this line, add a new line:


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

Now, hit Return and add another new line:


<c:out value = "${'This is a test of the JSTL Core Library'}"/>

Reload the page at http://localhost:8080/examples/jsp/jsp2/el/implicit-objects.jsp?foo=bar.

You should see your updates reflected in the output. In this example, we are just using the tag library to output text, something we could also do with a JSP expression. Tags open up a range of further capabilities with the same syntax. 

Layout of a JSP web application

Tomcat follows the standard layout for Java servlet and JSP pages. The general structure is a folder with the name of the application, which is deployed inside Tomcat's /webapps directory.

In the Implicit Objects application, the application is /examples. Opening that folder reveals three important children: the /WEB-INF directory, the index.html file, and a set of other directories.

The WEB-INF directory contains metadata that informs Tomcat how to run the application.

The remaining content, including index.html, is directly accessible, just as it would be in a typical web server. Likewise, the implicit-objects.jsp is available to view, and is automatically handled as a JSP page (not an HTML page) by the server.

JSP's request-response architecture

In a typical servlet/JSP application, servlets receive requests and interact with server-side components and services (such as the database) to fulfill them. Once handled, the request result is forwarded to a JSP page, which presents the response based on the data.

A servlet uses the following syntax when sending a request response to a JSP page:


request.getRequestDispatcher("path/to/jsp.jsp").forward(req,res);

Whatever data the servlet has inserted into the various JSP scopes will be accessible to JSP as objects, like the param object you saw earlier. A scope is simply a range of life for a given object. Request and response objects are request scoped, meaning they live for the duration of the request. Other scopes include page scope (living as long as the JSP page does) and session scope (terminating when the user ends the given session).

MVC in JSP and servlet applications

The interaction between servlets and JSP pages follows the classic MVC pattern: the controller object (a servlet) prepares the model object (an item or user object) and sends it to the view (the JSP page) for rendering. MVC's clean separation of concerns has made it a popular and long-lived approach to building software. Struts is one of the oldest and most well-known frameworks implementing MVC with JSP and servlets. Spring MVC also includes built-in support for JSP.

Using Spring MVC is probably the most common approach to JSP development within a larger framework, since it gives you access to the entire Spring ecosystem. A good way to accelerate the process is use a JSP Spring Boot template.

Conclusion

JSP is a well-known and versatile technology for developing Java web application views. Combined with servlets, JSP pages are very powerful and provide access to the entire range of Java capabilities. While Jakarta Server Pages may not be your first choice for developing a modern Java web application, you will encounter JSP pages in legacy applications. It's also a good choice for simpler applications, where you want to quickly connect your HTML front end to server-side Java code. The JSTL tags are capable of handling most web application requirements, and third-party libraries extend that functionality for specific technologies and use cases.