JavaServer Pages, (JSPs)

In this part of the Java EE 5 tutorials, we will work with JavaServer Pages (JSPs).

JavaServer Pages (JSP) technology provides a simplified, fast way to create dynamic web content. JSPs are compiled into servlets by a JSP compiler. A JSP page is a text-based document. It can contain two types of text: static data and JSP elements, which determine how the page constructs dynamic content.

JavaServer pages is an integral part of the Java EE platform. Huge enterprise applications are layered. The JSP pages represent the presentation layer of the application. In the MVC (Model, View, Controller) pattern, this is the View part. The data is processed by the business logic of the application. The model loads the data from the database. The data is sent by the controller to the appropriate JSP page for displaying.

The JavaServer Pages consists of several key features:

JSP pages go through two phases: translation phase and execution phase. The JSP page is translated once per page. The JSP page is executed once per request. Internally, the JSP page is transformed into servlet, which is then compiled.

JSP pages have a .jsp extension.

Scripting elements

We have declarations, expressions and scriptlets. Scripting elements are used to manipulate objects and perform calculations. Scripting in done in the Java language. Each of them is put inside specific tags.

<%! declaration %>
<% scriptlet %>
<%= expression %>

A declaration is used to declare variables and methods in a JSP page. A scriptlet is a piece of Java code. It performs some dynamic action within a JSP page. It can manipulate objects or print some text or HTML data. An expression outputs data, which is displayed in a browser.

Celsius to Fahrenheit

In the following example, we use all three elements.

index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Fahrenheit</title>     
    </head>
    <body>
        <h2>Celsius to Fahrenheit</h2>
        <%!
            double fahr1, fahr2, fahr3;
            int cels1 = 20;
            int cels2 = 36;
            int cels3 = 45;

            double calculate(int cels) {
                return cels * 9 / 5.0 + 32;
            }
        %>

        <%
            fahr1 = calculate(cels1);
            fahr2 = calculate(cels2);
            fahr3 = calculate(cels3);
        %>

        <p>
            <%= cels1 %> Celsius is <%= fahr1 %> Fahrenheit<br>
            <%= cels2 %> Celsius is <%= fahr2 %> Fahrenheit<br>
            <%= cels3 %> Celsius is <%= fahr3 %> Fahrenheit<br>
        </p>
    </body>
</html>

In the example, we convert Celsius temperature to Fahrenheit.

<%!
  double fahr1, fahr2, fahr3;
  int cels1 = 20;
  int cels2 = 36;
  int cels3 = 45;

  double calculate(int cels) {
      return cels * 9 / 5.0 + 32;
  }
%>

In this declaration, we declare six variables and one function.

<%
  fahr1 = calculate(cels1);
  fahr2 = calculate(cels2);
  fahr3 = calculate(cels3);
%>

In the scriptlet, we perform the computation.

<p>
 <%= cels1 %> Celsius is <%= fahr1 %> Fahrenheit<br>
 <%= cels2 %> Celsius is <%= fahr2 %> Fahrenheit<br>
 <%= cels3 %> Celsius is <%= fahr3 %> Fahrenheit<br>
</p>

In the expressions, we output the variables.

Celsius to Fahrenheit
Figure: Celsius to Fahrenheit

From JSP to a servlet

Next we will show, how a container transforms a JSP page to a servlet.

index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <style>
            * { font-size: 12px; font-family: Verdana }    
        </style>
        <title>SimpleJSP</title>
    </head>
    <body>

        <%= "Simple JSP page" %>

    </body>
</html>

We will have this simple JSP page. All it does is print some text. We will look, how a container transforms the page into a servlet.

index_jsp.java
/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/8.0.27
 * Generated at: 2016-09-14 10:03:49 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

 String var = "Simple JSP page"; 
  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private static final java.util.Set<java.lang.String> _jspx_imports_packages;

  private static final java.util.Set<java.lang.String> _jspx_imports_classes;

  static {
    _jspx_imports_packages = new java.util.HashSet<>();
    _jspx_imports_packages.add("javax.servlet");
    _jspx_imports_packages.add("javax.servlet.http");
    _jspx_imports_packages.add("javax.servlet.jsp");
    _jspx_imports_classes = null;
  }

  private volatile javax.el.ExpressionFactory _el_expressionfactory;
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public java.util.Set<java.lang.String> getPackageImports() {
    return _jspx_imports_packages;
  }

  public java.util.Set<java.lang.String> getClassImports() {
    return _jspx_imports_classes;
  }

  public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
    if (_el_expressionfactory == null) {
      synchronized (this) {
        if (_el_expressionfactory == null) {
          _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
        }
      }
    }
    return _el_expressionfactory;
  }

  public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
    if (_jsp_instancemanager == null) {
      synchronized (this) {
        if (_jsp_instancemanager == null) {
          _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
        }
      }
    }
    return _jsp_instancemanager;
  }

  public void _jspInit() {
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {

final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
return;
}

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html;charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                        null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\n");
      out.write("<!DOCTYPE html>\n");
      out.write("<html>\n");
      out.write("    <head>\n");
      out.write("        <title>Simple JSP page</title>\n");
      out.write("    </head>\n");
      out.write("    <body>\n");
      out.write("\n");
      out.write("        ");
      out.write("\n");
      out.write("\n");
      out.write("        ");
      out.print( var );
      out.write("\n");
      out.write("\n");
      out.write("    </body>\n");
      out.write("</html>");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try {
            if (response.isCommitted()) {
              out.flush();
            } else {
              out.clearBuffer();
            }
          } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

This is the code generated by Apache Tomcat. Note that different containers will generate different code. To see the servlet code in Netbeans IDE, we we right click on the JSP page in the Projects window and select option View Servlet. (Before showing the servlet, the JSP page must be executed first.)

Directives

Directives are messages to the JSP container. There are three main directives:

The page directive

The page directive defines several properties for a JSP page.

index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <title>Партизанская</title>
    </head>
    <body>
        <pre>
   По долинам и по взгорьям
Шла дивизия вперед,
Чтобы с бою взять Приморье -
Белой армии оплот.

Наливалися знамена
кумачом последних ран,
Шли лихие эскадроны
Приамурских партизан.

Этих лет не смолкнет слава,
Не померкнет никогда,
Партизанские отряды
Занимали города.

И останутся как в сказке,
Как манящие огни,
Штурмовые ночи Спасска,
Волочаевские дни.

Разгромили атаманов,
Разогнали воевод,
И на Тихом океане
Свой закончили поход. 
        </pre>
    </body>
</html>

The example illustrates the pageEncoding attribute of the page directive. We display text of a song in russian language.

<%@page contentType="text/html" pageEncoding="UTF-8"%>

The directive sets the encoding to UTF-8. It covers also the Russian language. If we would not set this encoding, the JSP page would use the default ISO-8859-1 encoding. The page would not display the text correctly.

Партизанская
Figure: Партизанская

The contentType attribute defines the MIME type. It tells the browser, how to interprete the data. The default contentType is text/html. In this case, the client browser interpretes all the HTML code. The <br> is a new line, <p></p> a paragraph etc.

index.jsp
<%@page contentType="text/plain" pageEncoding="UTF-8"%>

<html>
    <head>
        <style>
            * { font-size: 12px; font-family: Verdana }    
        </style>
        <title>ContentType</title>
    </head>
    <body>

       <b>Plain text content type</b>

    </body>
</html>

If we set the contentType to text/plain, we tell the browser to interprete all textual data as simple text. So the HTML tags are not interpreted and are simply displayed.

Plain text
Figure: Plain text

The errorPage attribute

We can use the errorPage attribute to handle exceptions in the JSP page.

index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page errorPage="errorPage.jsp" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <%
            int num = 77 / 0;  
        %>
    </body>
</html>

An exception occurs in this JSP page. Our exception will raise when we try to divide by zero.

<%@page errorPage="errorPage.jsp" %>

With the errorPage attribure, we tell the container to show the errorPage.jsp if there is some exception.

errorPage.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page isErrorPage="true" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Error occurred</title>
    </head>
    <body>
        <h2>Error</h2>

        <%= exception.getMessage() %>
    </body>
</html>

Here we process the exception.

<%@page isErrorPage="true" %>

With the isErrorPage attribute, we make the exception object available to this JSP page.

<%= exception.getMessage() %>

We display the error message.

Error page
Figure: Error page

If we do not provide an error page, we get an error message from the container.

Error 500
Figure: Error 500

The import attribute

The import attribute includes a Java class into the namespace of a JSP page.

index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page import="java.util.Date"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>

        <p>
            Today's date: <%= new Date() %>
        </p>

    </body>
</html>

The JSP page shows today's date.

<%@page import="java.util.Date"%>

We import the java.util.Date class.

Imported class
Figure: Imported class

The include directive

The include directive enables us to organize the code effectively. All websites have repeating code. An example is the common copyright notice or navigation menu. If the website grows larger, it gets time consuming to correct the code in all files. When the year changes, we should change the copyright notice in all files.

style.css
.container {
    display: flex;
    flex-flow: column;
}

.center {
    border:1px solid #4B8699;
    margin:1px 0px 1px 0px;
    min-height: 50vh;
}

.header {
    border: 1px solid #4B8699;
    text-align:center;
}

.footer {
    border: 1px solid #4B8699;
    text-align:center;
}

This is the style.css file.

index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <title>Including</title>
        <link rel="stylesheet" href="style.css" type="text/css">
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body class="container">

        <div class="header">
            <%@ include file="WEB-INF/jspf/header.jspf" %>
        </div>

        <div class="center">
        </div>

        <div class="footer">
            <%@ include file="WEB-INF/jspf/footer.jspf" %>
        </div>

    </body>
</html>

We divide our page into three parts. We use include directive to include the header and footer.

<%@ include file="WEB-INF/jspf/footer.jspf" %>

Here we include the footer. The included code fragments have a .jspf ending.

footer.jspf
<%@ page pageEncoding="UTF-8" %>
<div><b>ZetCode</b> @ 2007 - 2016 Jan Bodnar</div>

If we use include files, we need to update the text only once.

Including files
Figure: Including files

The taglib directive

The taglib directive defines a tag library and prefix for the custom tags used in the JSP page. We will use this directive later in our Java EE 5 tutorials. When we will work with custom JSP tags.

Deploying a web application

We will deploy our first web application, using the Resin application server.

index.jsp
<html>
<head>
<title>Date</title>
</head>
<body>

<p>
Date: <%= new java.util.Date() %>
</p>

</body>
</html>

The simple JSP file consists of HTML code and Java code. Here we use a JSP expression which will output the current date.

$ ls
index.jsp

In our working directory, we have only one file named index.jsp. And now, we need to deploy it to the server.

Deployment of web applications is similar to installing classical programs on desktop. These are steps needed to run the web application.

In Java EE a web application is called a web module. It is the simplest deployable unit.

$ ./httpd.sh start
Resin/3.1.3 started -server ''.

First, we start the Resin server. The httpd.sh script is located in the bin directory.

$ jar -cvf date.war *
added manifest
adding: index.jsp(in = 110) (out= 85)(deflated 22%)

We create a web archive.

$ ls
date.war  index.jsp

We have created a war file.

$ mv date.war /home/vronskij/bin/resin/webapps/

We move the war file to the Resin AS webapps subdirectory. Here you must provide your own path to the directory depending on where you have installed the Resin server. By moving the war file to the webapps directory, the application is deployed and we can test it. Note that it is possible to deploy a web application, while the server is running.

Our JSP file displays current date. We write http://localhost:8080/date/ to our web browser to test the outcome. The localhost:8080 means that we test our application on our local machine and the Resin server listens on 8080 port. The date path is called the context path. It is the context root or path to our application. We can have several applications deployed at one time. The context path can be specified in configuration files. When it is not, than it is equal to the WAR file name.

Date
Figure: Date

In this chapter, we have covered Java Server Pages.