JavaServer Pages


As a follow up to previous post The Servlet API, this post aims to sweeps over some fundamentals of JSP, a technology which thanks to its simple yet extensible design, still to this day, underpins many modern web application frameworks.

JavaServer Pages (JSP) is a technology that helps software developers create dynamically generated web pages based on HTML, XML, or other document types. Released in 1999 by Sun Microsystems.

Scripting

Expressions

Shorthand:

<%=java.util.Date() %>

Longhand:

<jsp:expression>Math.random()</jsp:expression>

Expressions are evaluated and converted into a String, and can use predefined variables.

<p>Hostname: <%= request.getRemoteHost() %></p>
<p>Session ID: <%= session.getId() %></p>

No semicolons are permitted.

Scriptlets

Shorthand:

<%
String queryString = request.getQueryString();
out.println("Freshly served GET data: " + queryString);
%>

Longhand:

<jsp:scriptlet>
response.setContentType("text/plain");
</jsp:scriptlet>

Inserts arbitrary Java code into a JspPage _jspService() method.

The _jspService() method is defined automatically by the JSP processor based on the contents of the JSP page. It is represents the body of the JSP page, is defined automatically by the JSP container.

Scriptlets are not constrained like expressions, and are free to do anything (e.g. modify headers, write logs, loop constructs, etc).

<ul>
<%
Iterator i = portfolio.getItems().iterator();
while (i.hasNext()) {
  Investment stock = (Investment)i.next();
%>
  <li>
    <a href="<%=request.getContextPath()%>/ticker=<%=investment.getTickerCode()%>"><%=investment.getTitle()%></a>
  </li>
<%
} //while
%>
</ul>

Declarations

Shorthand:

    <%! %>

Longhand:

    <jsp:declaration></jsp:declaration>

Declarations are useful for injecting variables or methods into the main body of the Servlet class. JSP pages provide two hooks for initialisation and cleanup activity, jspInit() and jspDestroy() respectively.

<%!
private FooDAO fooDAO;
public void jspInit() {
  fooDAO = (FooDAO)getServletContext.getAttribute("fooDAO");
}
public void jspDestroy() {
  fooDAO.cleanup();
}
%>

Here’s another example:

<h1>Log Report</h1>
<%!
private String generateHeading() {
  return("<h2>" + Math.random() + "</h2>");
}
%>
<%= generateHeading() %>

Generated Servlet code:

Tip: If you’re using Tomcat like me, it stores generated JSP Java in a scratch directory called work, e.g. I found the following Java file smashed_jsp.java for the above JSP page called smashed.jsp here {tomcat}\work\Catalina\localhost\{app}\org\apache\jsp\smashed_jsp.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package org.apache.jsp;

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

public final class smashed_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

private String generateHeading() {
  return ("<h2>" + Math.random() + "</h2>");
}

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  // omitted for brevity

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

    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");
      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("<html>\r\n");
      out.write("<body>\r\n");
      out.write("<h1>Log Report</h1>\r\n");
      out.write('\r');
      out.write('\n');
      out.print(generateHeading() );
      out.write("\r\n");
      out.write("</body>\r\n");
      out.write("</html>\r\n");
    } 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);
    }
  }
}

Notice on line 10 above, how the declaration for method generateHeading is injected into the Java representation of the JSP.

Directives

Syntax:

<%@ page language="java" import="net.bencode" errorPage="fizz.jsp" %>
<%@ page import="java.util.*" %>
<%@ page buffer="20kb" %>
<%@ include file="banner.htm" %>
<%@ taglib uri="cooltags" prefix="ct" %>

A way of flagging special processing or functionality needs of the JSP with the Servlet container.

  • page - page-dependent attributes, such as the scripting language to use, the content (MIME) type, how multithreading is to be handled (isThreadSafe), a class to extend, a package to import, an error page to use, or the JSP page output buffer size.
  • include - specifies a resource that contains text or code to be inserted into the JSP page when it is transpiled. Known as a static include.
  • taglib - specifies a library of custom JSP tags that will be used in the JSP page.

Including and Forwarding

JSP provides two ways to inject chunks of other web resources into itself.

Include Directive

Syntax:

<%@ include file="output.log" %>
<%@ include file="footer.jsp" %>

The include is processed when the Servlet container transpiles the JSP page into Java. Essentially the text defined the specified resource is inlined into the housing JSP definition.

jsp:include Element

Syntax:

<jsp:include page="includedPPage" />
<jsp:include page="date.jsp" />

The jsp:include is processed when the JSP is executed, i.e. at runtime, and can be used for both static and dynamic content. In a dynamic context, the request is sent to the included resource, which is in-turn executed with the result injected into the housing JSP.

Tip: Use the include directive when content of the file rarely changes, it is faster than jsp:include.

Forwarding

Syntax:

<jsp:forward page="/getgains.jsp" />

Same mechanism used by Servlet API. Forwarding is a server side concept, completely transparent from the HTTP client. From the clients point of view, the original resource they requested comes back as a result, and is none the wiser that a chain of server side forwards may have occured in order to accomplish the rendering.

State can be passed into the forward using jsp:param:

<jsp:forward page="/getgains.jsp">
  <jsp:param name="param1" value="value1" />
</jsp:forward>

Redirecting

Syntax (scriptlet):

<%
response.sendRedirect("http://slashdot.org");
%>

Or:

<%
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
response.setHeader("Location", "http://slashdot.org");
%>

Redirection informs the HTTP client that an alternative URL should be requested.

Explicit and Implicit Objects

Explicit Objects

Syntax:

<jsp:useBean id="pageBean" class="mybeans.NameBean" scope="page" />

Defines an instance of the specified class, and will automatically be stored depending on scope needs. Alternatively you can craft your objects within Java scriptlets or declarations.

If you go down the jsp:useBean route, you have available two supporting tags at your disposal:

jsp:setProperty

  • directly specifies a literal value <jsp:setProperty name="pageBean" property="user" value="Smith" />
  • take the value for a specified property from an associated HTTP request parameter <jsp:setProperty name="pageBean" property="user" param="username" />
  • iterates through parameters in the HTTP request and maps them to corresponding bean properties <jsp:setProperty name="pageBean" property="*" />

jsp:getProperty

reads a bean property value, converts it to a Java string, and places the string value into the implicit out object so that it can be displayed as output.

useBean Scopes

  • page - accessible only from within the JSP page where it was created, i.e. is short lived during the request/response cycle.
  • request - accessible from any JSP page servicing the same HTTP request that is serviced by the JSP page that created the object.
  • session - accessible from any JSP page sharing the same HTTP session as the JSP page that created the object.
  • application - accessible from any JSP page used in the same Web application (within any single JVM) as the JSP page that created the object.

Implicit Objects

A set of implicitly created objects, automatically taken care of by the Servlet container. You can just assume these will always exist.

  • page - the JSP page implementation class that was created when the page was translated.
  • request - the HTTP request and is an instance of javax.servlet.http.HttpServletRequest.
  • response - the HTTP response and is an instance of javax.servlet.http.HttpServletResponse.
  • pageContext - the page context of a JSP page (page scope), which is provided for storage and access of all page scope objects of a JSP page instance.
  • session - the HTTP session and is an instance of javax.servlet.http.HttpSession.
  • application - the servlet context for the Web application and is an instance of javax.servlet.ServletContext. Accessible from any JSP page instance in the JVM.
  • out - used to write content to the output stream of a JSP page instance. It is an instance of javax.servlet.jsp.JspWriter, and is associated with the response object for a particular request.
  • config - the servlet configuration for a JSP page and is an instance of javax.servlet.ServletConfig interface.
  • exception - applies to JSP error pages only, and is a java.lang.Exception instance that represents the uncaught exception that was thrown from another JSP page and that resulted in this error page being invoked.

Error Handling

Create a page, for example error.jsp, dedicated to the job of displaying error information. Signal to the container this is the error page by using this directive:

<%@ page isErrorPage="true" %>

When this directive is specified, if possible, the Servlet container will setup an implicit property called exception. Be aware than an exception may not always be available for the container to propagate, for example in a 404 (resource not found) scenario.

<%@ page isErrorPage="true" %>
<html>
<body>
<h1>Error Page</h1>
<p>Don't shoot the messenger, but something bad happened.</p>

<% if (exception != null) { %>
<h3>Message</h3>
<pre><%= exception.getMessage()%></pre>
<h3>Stack</h3>
<pre><%= exception.getStackTrace()%></pre>
<% } %>

<% if (response.getStatus() == 404) { %>
<p>ohh nose, that resource could not be found</p>
<% } %>

</body>
</html>

Other JSP pages can signal to use the error page, with another directive:

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

This directive unfortunately doesn’t scale very well with lots of JSP pages. Also, will only apply to exceptions that are caused by the JSP itself, not underlying Servlets or forwards.

A broader sweeping option, is the error-page element in the deployment descriptor. The below should paint a picture of how it works:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>princeofpersia</display-name>
  <error-page>
    <error-code>404</error-code>
    <location>/error.jsp</location>
  </error-page>
  <error-page>
    <exception-type>javax.servlet.ServletException</exception-type>
    <location>/error.jsp</location>
  </error-page>
  <error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/error.jsp</location>
  </error-page>
</web-app>

Expression Language (EL)

EL (Expression Language) enables the dynamic resolution of Java objects and methods in JSP and Facelets pages. EL expressions take the form of ${foo} and #{bar}. The dollar ${} and hash #{} define immediate evaluation expressions and deferred evaluation expressions respectively.

In the EL 3.0, a new standalone EL processor API is available, and can be used standalone in Java SE code.

Custom Tags

JSTL

Using Tomcat? Tomcat doesn’t come with a JSTL distribution. Grab JSTL API and JSTL Implementation manually or with maven.