JSP Tutorial For Beginners
JSP is a server side technology which helps to create dynamic, platform-independent java web applications and is mainly used for implementing the presentation layer. In this tutorial, we will look into the essentials of the JSP technology with illustrating some simple code.
As a prerequisite of this post, we assume you have knowledge what is HTML, web server and Java programming language and how web application work over HTTP.
1. What is JSP?
Java Server Pages (JSP) code is likely HTML with bits of Java code in it. Very basically, in order to create a JSP code, you can take any existing HTML page and change its extension to “.jsp” instead of “.html”. Then you can put Java code in it with some structures called Scriptlet, Directive, Expression. In the code below, the JSP file shows the current time:
<html> <body> The current time is <%= new java.util.Date() %> </body> </html>
In the other code, we make some calculations:
<html> <% int a = 5; int b = 8; %> <body> The first number is : <%= a %> <br/> The second number is : <%= b %> <br/> The sum is : <%= ( a + b ) %> <br/> </body> </html>
As you see, in a JSP file, HTML and Java code are mixed. You can also access to the entire family of Java APIs, including the JDBC API to access enterprise databases in the JSP file. The main structure is the HTML. But with Java in it, you can access the wide-ranging Java APIs and libraries. With this flexible nature, Web Application Programmers can concentrate on how to process the information in the presentation layer ( HTML, GUI part ).
JSP is an extension of Servlets and every JSP page first gets converted into servlet by JSP container before processing the client’s request. The Servlet is older Java technology than JSP. It consists of pure Java code and holds the capabilities of the servers, HTML protocol. The Servlet code enables to have HTML codes in it. But this process is cumbersome and error prone, when it comes to writing a complex HTML response. JSP helps in this situation and provide us to write normal HTML page and include our java code only where it’s required.
Now, let’s see the principal JSP elements and try to explain them briefly.
1.1 JSP Syntactic Elements
In a JSP file, the Java code is usually written in a Scriptlet tags with a format like below:
<% Java code %>
A scriptlet can contain any number of Java statements, variable or method declarations that are accessible from anywhere within the JSP page.
Variable or method declarations can be also written between the Declaration tags ( <%! %>
):
<%! int a, b; public int sum( int i1, int i2 ) { return i1 + i2; } %>
JSP Expression tag ( <%= %>
) contains Java statement that is evaluated, converted to a String and written to the output stream of the response. For example, to write the content of the variable “name” to the screen, we can use <%=name%>
. The scriptlet equivalent of this: <% out.print( name ); %>
. Please note that in the expression tag, you don’t have to put semicolon (;) at the end of the line, but in the scriptlet you do.
Following is the syntax of JSP comments:
<%-- JSP comment. Ignored by the JSP engine. --%>
1.2 JSP Implicit Objects
JSP Implicit Objects are the useful coding objects that the JSP Container makes available to developers in every JSP page. We can call them directly in scriptlets without any declaration. There are 9 JSP implicit objects. We show them and their counterpart Servlet and Java objects below:
Object | Type |
---|---|
request | javax.servlet.http.HttpServletRequest |
response | javax.servlet.http.HttpServletResponse |
pageContext | javax.servlet.jsp.PageContext |
session | javax.servlet.http.HttpSession |
application | javax.servlet.ServletContext |
out | javax.servlet.jsp.JspWriter |
config | javax.servlet.ServletConfig |
page | java.lang.Object |
exception | java.lang.Throwable |
<% out.print( "Hello " + request.getParameter( "username" ) ); %>
In this code, two implicit objects ( out, request ) are used. The “username” parameter is fetched from the request object and after concatenating the “Hello” word, printed to the client with the out implicit object.
1.3 JSP Directives
JSP directives are messages and instructions to the JSP container, telling it how to translate a JSP page into the corresponding Servlet. Directives have this syntax:
<% @ directive { attr=”value” }* %>
There are three directives. Here is the list:
Directive | Sample Syntax | Description |
---|---|---|
page | <%@ page import=”java.util.*,java.text.*” %> ( Imports other Java libraries into the JSP page ) | The page directive defines a number of page dependent properties and communicates these to the JSP container. Page directive attribute list is: language, extends, import, session, buffer, autoFlush, isThreadSafe, info, errorPage, isErrorPage, contentType, pageEncoding, isELIgnored, deferredSyntaxAllowedAsLiteral, trimDirectiveWhitespaces. |
include | <%@ include file=”otherPage.jsp” %> ( Merge the content of the other jsp file ) | The include directive is used to substitute text and/or code at JSP page translation-time. This directive tells the container to insert the content of other files with the current JSP. |
taglib | <%@ taglib uri=”/WEB-INF/c.tld” prefix=”c”%> ( Declares the external taglib. Tablib uri can be an url address or tld tag library file path ) | The taglib directive in a JSP page declares that the page uses a tag library, uniquely identifies the tag library using a URI and associates a tag prefix that will distinguish usage of the actions in the library |
1.4 JSP Actions
JSP actions are the basically predefined functions based on XML syntax. They get the JSP container to do some behaviours, actions. They may affect the current out stream and use, modify and/or create objects.
The syntax for an Action element is:
<jsp:action_name attribute="value" />
Here is the list of the some JSP Actions:
Action | Description | Sample Code |
---|---|---|
jsp:useBean | Associates an instance of a Java programming language object. Try to find an existing java object. If the object is not found it will attempt to create the object using attributes. | <jsp:useBean id=”connection” class=”com.myapp.Connection”/> |
jsp:setProperty | Sets the values of properties in a bean. Properties in a Bean can be set from one or more parameters in the request object, from a String constant, or from a computed request-time expression. | <jsp:setProperty name=”user” property=”userobj” param=”username” /> |
jsp:getProperty | Places the value of a bean instance property, converted to a String, and print it. This simply means inserting it into the implicit “out” object. | <jsp:getProperty name=”user” property=”name” /> |
jsp:include | Provides for the inclusion of static and dynamic resources in the same context as the current page. | <jsp:include page=”/static/copyright.html”/> |
jsp:forward | Allows the runtime dispatch of the current request to a static resource, a JSP page or a Java servlet class in the same context as the current page. | <jsp:forward page='<%= whereTo %>’ /> |
jsp:param | This action element is used to provide key/value information. This element is used in the jsp:include, jsp:forward, and jsp:params elements. | <jsp:param name=”name” value=”value” /> |
jsp:plugin | This tag is replaced by either an <object> or <embed> tag, as appropriate for the requesting user agent, and emitted into the output stream of the response. | <jsp:plugin type=”applet” code=”Molecule.class” codebase=”/html”><jsp:params>…</jsp:params></jsp:plugin> |
jsp:attribute | Defines an attribute value for another JSP action element instead of in the value of an XML attribute. | <jsp:attribute name=”even”> |
jsp:text | This action can be used to enclose template data in a JSP page, a JSP document, or a tag file. | <jsp:text>This is some content</jsp:text> |
jsp:output | This action is used to modify some properties of the output of a JSP document or a tag file. | <jsp:output xmlns:jsp=”http://java.sun.com/JSP/Page” omit-xml-declaration=”true”/> |
1.5 JSP – Standard Tag Library (JSTL)
JSP Standard Tag Library (JSTL) is a set of useful tags to simplify the JSP development. It provides tags to control the JSP page behavior, iteration and control statements, internationalization tags, and SQL tags. JSTL is part of the Java EE API and included in most servlet containers. There are five groups of JSTL: core tags, sql tags, xml tags, internationalization tags and functions tags.
In the code snippet below, there is a simple loop coded with JSTL. Without any tag library or tags, we can write the counterpart code with scriptlets that contain Java code in it. But external tag libraries provide more simple and useful capabilities to us. We can do more with writing less.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <c:forEach var="number" begin="5" end="10"> <c:out value="${number}"></c:out> </c:forEach>
1.6 JSP – Expression Language (EL)
JSP Expression Language (EL) simplifies to access application data stored in JavaBeans properties. EL also includes arithmetic, relational and logical operators. There are two constructs to represent EL expressions: ${expr} and #{expr}. EL also has its own operators, keywords and implicit objects.
The “param” implicit object holds request parameters as strings. In the code below, EL statement ${param.name}
retrieves the “name” parameter of the request. In the second line, you see the plus operator evaluates the addition calculations.
<h1>Welcome ${param.name}</h1> <p>The result is ${a + b}</p>
2. Overview
In our example, you see a simple issue tracking management web application with a single JSP page that contains the issue list and a form to insert a new issue. When you submit a new issue, this issue is appended to the list below with ‘OPEN’ status and ‘current time’ created date by default. In the list, the status of the each issue item can be changed by the buttons in its row. ‘CLOSE’ status issues are not listed and when you click on the close, the item you close is removed from the list. The background colors of the rows depend on their status. The rows of the ‘OPEN’ status issues are pink, ‘FIX’ status issues are green.
Our preferred IDE is Eclipse. We use ‘Maven’ for the dependency management. We create a dynamic web application and deploy it into the Tomcat server. Before, I have explained how to create a Maven dynamic web application in the Eclipse, how to define a “Tomcat” server and add the application to it in my other example. You can examine: Logback Mapped Diagnostic Contexts (MDC) Example
We add three dependencies to the Maven “pom.xml” file:
Dependencies in the pom.xml
<dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.187</version> </dependency> </dependencies>
We keep the issue records in a H2 memory database. We add “Standard Tag Library (JSTL)” jar file to the classpath. Because we use it in somewhere in the JSP code. We create two Servlets classes, so in order to compile it in our environment, we add servlet-api as provided. Anyway jsp-api and servlet-api jar files are already exist in the Jsp Container ( Tomcat Server ). So after compilation, you do not need to put these files in your project package ( war, ear ). If you put different version of the jsp/servlet jar files in the project package, probably you will get errors while deploying. For example, I executed this example in Tomcat 8. Apache Tomcat version 8.0 implements the Servlet 3.1 and JavaServer Pages 2.3 specifications from the Java Community Process. So I deliberately add the Servlet “3.1” version to the pom.xml file.
3. Implementation
In a JSP application, putting all of the Java codes in the JSP pages is not a good practice. You should separate the presentation layer from the business logic. In this way, you can easily adapt the application to a new look without changing the infrastructural codes.
As I mentioned before, we store the issue records in a H2 memory database. We put the database implementation codes in a new Java class, not in the JSP page. To keep simple dependency list, we choose pure JDBC approach for database access, not an ORM tool like Hibernate, or another helper framework like Spring JDBC. The code of our database access class “DbOperations” is below. We call it in the JSP page to perform the database layer executions.
DbOperations.java
package com.javacodegeeks.examples.jspexample.db; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List; import com.javacodegeeks.examples.jspexample.db.entity.Issue; public class DbOperations { private static DbOperations theInstance = new DbOperations(); private Connection connection; private DbOperations() { try { Class.forName( "org.h2.Driver" ); connection = DriverManager.getConnection( "jdbc:h2:mem:testdb", "sa", "" ); // Create table final PreparedStatement ps = connection .prepareStatement( "CREATE TABLE ISSUE( ID INT PRIMARY KEY auto_increment, TITLE VARCHAR, OPENEDBY VARCHAR, PRIORITY VARCHAR, STATUS VARCHAR DEFAULT 'OPEN', COMMENT VARCHAR, CREATE_DATE TIMESTAMP DEFAULT NOW() )" ); ps.executeUpdate(); } catch ( final ClassNotFoundException e ) { e.printStackTrace(); } catch ( final SQLException e ) { e.printStackTrace(); } } public static DbOperations getTheInstance() { return theInstance; } public void addNewIssueRecord( final String title, final String openedBy, final String priority, final String comments ) { try { final PreparedStatement ps = connection .prepareStatement( "INSERT INTO ISSUE( TITLE, OPENEDBY, PRIORITY, COMMENT ) VALUES ( ?, ?, ?, ? )" ); ps.setString( 1, title ); ps.setString( 2, openedBy ); ps.setString( 3, priority ); ps.setString( 4, comments ); ps.executeUpdate(); } catch ( final SQLException e ) { e.printStackTrace(); } } public List getAllIssues() { final List issueList = new ArrayList(); try { final PreparedStatement ps = connection .prepareStatement( "SELECT ID, TITLE, OPENEDBY, PRIORITY, STATUS, COMMENT, CREATE_DATE FROM ISSUE" ); final ResultSet rs = ps.executeQuery(); while ( rs.next() ) { final Issue issue = new Issue(); issue.setComments( rs.getString( "COMMENT" ) ); issue.setCreateDate( new Date() ); issue.setId( rs.getInt( "ID" ) ); issue.setOpenedby( rs.getString( "OPENEDBY" ) ); issue.setPriority( rs.getString( "PRIORITY" ) ); issue.setStatus( rs.getString( "STATUS" ) ); issue.setTitle( rs.getString( "TITLE" ) ); issueList.add( issue ); } } catch ( final SQLException e ) { e.printStackTrace(); } return issueList; } public void updateIssueRecord( final String id, final String newStatus ) { try { final PreparedStatement ps = connection .prepareStatement( "UPDATE ISSUE SET STATUS = ? WHERE ID = ?" ); ps.setString( 1, newStatus ); ps.setInt( 2, Integer.parseInt( id ) ); ps.executeUpdate(); } catch ( final SQLException e ) { e.printStackTrace(); } } }
At the top of the JSP page, we place the “taglib” and “page” JSP directives to import the backend Java classes and Servlets in the application and JSTL tag libraries.
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <?xml version="1.0" encoding="ISO-8859-1" ?> <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ page import="com.javacodegeeks.examples.jspexample.db.DbOperations"%> <%@ page import="java.util.*"%> <%@ page import="com.javacodegeeks.examples.jspexample.db.entity.*"%>
Bootstrap is a popular HTML, CSS, and JS framework. It contains predefined css classes, icons that help the developers to form the gui look easily. We use it to build the jsp page appearance. The html codes that generate the “new issue form” are below:
<div style="width: 500px; margin-left: 50px; margin-top: 20px;"> <div class="col-md-12 col-sm-6 col-xs-12"> <div class="panel panel-default"> <div class="panel-heading clearfix"> <i class="icon-calendar"></i> <h3 class="panel-title">Add New Issue</h3> </div> <div class="panel-body"> <form id="issueForm" method="post" class="form-horizontal row-border" action="/jspexample/addIssue"> <div class="form-group"> <label class="col-md-3 control-label">Title</label> <div class="col-md-9"> <input type="text" name="title" class="form-control" /> </div> </div> <div class="form-group"> <label class="col-md-3 control-label">Opened By</label> <div class="col-md-6"> <select class="form-control" name="openedby"> <option value="Bob">Bob</option> <option value="George">George</option> <option value="Ali">Ali</option> </select> </div> </div> <div class="form-group"> <label class="col-md-3 control-label">Priority</label> <div class="col-md-6"> <select class="form-control" name="priority"> <option value="High">High</option> <option value="Medium">Medium</option> <option value="Low">Low</option> </select> </div> </div> <div class="form-group"> <label class="col-md-3 control-label">Comments</label> <div class="col-md-9"> <textarea rows="6" class="form-control" name="comments"></textarea> </div> </div> <div class="form-group"> <label class="col-md-3"></label> <div class="col-md-9"> <input type="submit" value="Submit" /> </div> </div> </form> </div> </div> </div> </div>
The Html codes of the issue list are below. Later, we will discuss the fundamental lines and explain them.
<% List< Issue > issueList = DbOperations.getTheInstance().getAllIssues(); pageContext.setAttribute("issueList", issueList); Map< String, String > issueColors = new HashMap< String, String >(); issueColors.put( "OPEN", "#E2C8C8" ); issueColors.put( "FIX", "#C1E212" ); pageContext.setAttribute("issueColors", issueColors ); %> <div style="width: 800px; margin-left: 50px; margin-top: 30px;"> <% if ( issueList.size() > 0 ) { %> <div class="col-md-11"> <div class="panel panel-default"> <div class="panel-heading"> <i class="icon-calendar"></i> <h3 class="panel-title">Issue List</h3> </div> <div class="panel-body"> <table class="table table-hover col-md-11"> <thead> <tr> <th class="col-md-2">Title</th> <th class="col-md-2">Opened By</th> <th class="col-md-1">Priority</th> <th class="col-md-2">Create Time</th> <th class="col-md-1">Status</th> <th class="col-md-1">Fix</th> <th class="col-md-1">Close</th> <th class="col-md-1">Reopen</th> </tr> </thead> <tbody> <c:forEach items="${issueList}" var="item"> <c:if test="${item.status ne 'CLOSE'}"> <tr style="background-color: ${issueColors[item.status]}"> <td><c:out value="${item.title}"/></td> <td><c:out value="${item.openedby}"/></td> <td><c:out value="${item.priority}"/></td> <td><fmt:formatDate value="${item.createDate}" pattern="dd-MM-yyyy HH:mm" /></td> <td><c:out value="${item.status}"/></td> <td><input type="button" <c:if test="${item.status == 'FIX'}"> disabled="disabled" </c:if> onclick="location.href = '/jspexample/updateIssue?id=<c:out value="${item.id}"/>&newStatus=FIX'" value="Fix" /></td> <td><input type="button" onclick="location.href = '/jspexample/updateIssue?id=<c:out value="${item.id}"/>&newStatus=CLOSE'" value="Close" /></td> <td><input type="button" <c:if test="${item.status == 'OPEN'}"> disabled="disabled" </c:if> onclick="location.href = '/jspexample/updateIssue?id=<c:out value="${item.id}"/>&newStatus=OPEN'" value="Reopen" /></td> </tr> </c:if> </c:forEach> </tbody> </table> </div> </div> </div> <% } %> </div>
First of all, the issue records are retrieved from the database through the DbOperations
instance. In the JSP page, we can access to the other Java classes in the classpath. Please note that we already import the DbOperations
class with JSP page directive at the top of the page. A compilation error occurs in the JSP page, unless you import an external Java class name.
<%@ page import="com.javacodegeeks.examples.jspexample.db.DbOperations"%> ... % List< Issue > issueList = DbOperations.getTheInstance().getAllIssues();
Notice the “if statement” before the issue list code. We will show the list, if only the issue list has at least one item. The html codes between the false condition statements are not rendered, because they are not added to the Jsp counterpart Servlet class by the compiler.
<% if ( issueList.size() > 0 ) { %> .... // Issue list HTML codes. <% } %>
We use JSTL tag library in the JSP page. <c:forEach
tag creates the loop and for each item in the “issue list”, a table row is printed. In the loop, the issues with ‘CLOSE’ status are not displayed in the list. We construct the “if statement” with the <c:if
JSTL tag. As you see, the condition is tested with ${item.status ne 'CLOSE'}
. This code is an example of JSP expression language. ne
is represented as ‘not equal’ and it is one of the JSP EL relational operators. The others are == (eq), != (ne), (gt), = (ge).
<c:forEach items="${issueList}" var="item"> <c:if test="${item.status ne 'CLOSE'}">
How can we set different background colors to the issue rows depending on their status? We store the color codes in a “Map” of which the keys are their status data:
Map issueColors = new HashMap(); issueColors.put( "OPEN", "#E2C8C8" ); issueColors.put( "FIX", "#C1E212" );
we access this map with an expression language pattern while determining the background color of the issue row:
<tr style="background-color: ${issueColors[item.status]}">
We use the JSTL fmt (format) tag in order to format the issue “createDate” date variable:
<td><fmt:formatDate value="${item.createDate}" pattern="dd-MM-yyyy HH:mm" /></td>
We do not want the “fix button” being active if the issue status is already ‘FIX’ and in a same manner, the “reopen button” should be active if the issue status is not ‘OPEN’. We provide it inserting JSTL “if statement” in the button HTML code and put disabled="disabled"
code if the relevant condition is true:
<td><input type="button" <c:if test="${item.status == 'FIX'}"> disabled="disabled" </c:if> ...
In the example project, there is a simple “Java bean” class like below:
package com.javacodegeeks.examples.jspexample.db.entity; public class Company { private String name; private String establishYear; public String getName() { return name; } public void setName( final String name ) { this.name = name; } public String getEstablishYear() { return establishYear; } public void setEstablishYear( final String establishYear ) { this.establishYear = establishYear; } }
To give an example of Jsp actions, we write a string “A company since 1998” in the page. “A” refers to the “name” variable and “1998” refers to the “establishYear” variable of the “Company” java bean. useBean jsp action uses the current java bean instance or creates new one if it does not exist. setProperty jsp action enables to set value to the property of the bean. getProperty jsp action inserts the property of a JavaBean into the output. In the example code, we print the values of the “Company” bean properties ( name and establishYear ) after setting values ( “A”, “1998” ) to them:
<div> <jsp:useBean id="companyBean" class="com.javacodegeeks.examples.jspexample.db.entity.Company" /> <jsp:setProperty property="name" name="companyBean" value="A"/> <jsp:setProperty property="establishYear" name="companyBean" value="1998"/> <b><jsp:getProperty property="name" name="companyBean"/></b> company since <b><jsp:getProperty property="establishYear" name="companyBean"/></b> </div>
Now I would like to mention the Servlets in the example. When we click on the “submit” button in the form, the “doPost” method of the “AddIssueServlet” servlet evaluates this action. The parameter values are transported via the request object. In this “doPost” method, these parameter values are taken and used to insert a new issue record in the database. Then the servlet invokes the jsp page to render again with the Servlet sendRedirect
method. The name of the our JSP page is “index.jsp”. Please note that “index.jsp” page is the default welcome page, so you do not have to write it explicitly. Thus we only set “/jspexample/” ( context root name of the application ) as the parameter of the “sendRedirect” method call:
package com.javacodegeeks.examples.jspexample.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.javacodegeeks.examples.jspexample.db.DbOperations; @WebServlet( value = "/addIssue" ) public class AddIssueServlet extends HttpServlet { private static final long serialVersionUID = -1L; @Override protected void doPost( final HttpServletRequest request, final HttpServletResponse response ) throws ServletException, IOException { final String title = request.getParameter( "title" ); final String openedBy = request.getParameter( "openedby" ); final String priority = request.getParameter( "priority" ); final String comments = request.getParameter( "comments" ); DbOperations.getTheInstance().addNewIssueRecord( title, openedBy, priority, comments ); response.sendRedirect( "/jspexample/" ); } }
Clicking the “fix”, “close” and “reopen” buttons in the issue list rows fires another Servlet event in order to update the status of the current issue:
package com.javacodegeeks.examples.jspexample.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.javacodegeeks.examples.jspexample.db.DbOperations; @WebServlet( value = "/updateIssue" ) public class UpdateIssueServlet extends HttpServlet { private static final long serialVersionUID = -1L; @Override protected void doGet( final HttpServletRequest request, final HttpServletResponse response ) throws ServletException, IOException { final String newStatus = request.getParameter( "newStatus" ); final String id = request.getParameter( "id" ); DbOperations.getTheInstance().updateIssueRecord( id, newStatus ); response.sendRedirect( "/jspexample/" ); } }
4. Download the Eclipse Project
This code demonstrates JSP basics in a simple example. Download link is below.
You can download the full source code of this example here : jspexample