JSP

  1. What is JSP?
  2. Directives
    1. page directive
    2. include directive
    3. taglib directive
  3. Scripting
    1. Declarations
    2. Expressions
    3. Scriptlets
  4. Actions
    1. jsp:useBean
    2. jsp:setProperty
    3. jsp:getProperty
    4. jsp:param
    5. jsp:include
    6. jsp:forward
  5. Implicit Objects
    1. out
    2. request
    3. response
    4. pageContext
    5. session
    6. application
    7. config
    8. page
    9. exception
  6. Things to check in JSP syntax
    1. Differences between include directive and include action
    2. The relationship between a ServletContext and a web application
    3. The meaning of the session attribute of the page directive
    4. The meaning of the scope attribute of the jsp:useBean action
  7. JSP Examples
    1. JSP error handling in the early Servlet/JSP spec
    2. JSP error handling in the current Servlet/JSP spec
    3. Cookie
    4. Using the include directive to separate pages
    5. Login using JavaBeans (using session)
    6. Modify the 'Login using JavaBeans (using session)' to be an example using Action.
    7. JSP that shows uploaded files
    8. JSP which downloads files
    9. JSP that uploads files

1. What is JSP?

In the Creating a new web application chapter, we changed the myapp application to the ROOT application. (The DocuementBase for the myapp application is C:/www/myapp.) All the examples below, such as the servlet chapter, should be practiced in the ROOT application. Write the JSP file in C:/www/myapp or its subdirectories with a regular editor, not Eclipse.

JSP has emerged as a Java-side countermeasure for ASP as Microsoft's ASP becomes popular. JSP is a servlet-based technology. Strictly speaking, JSP does not respond to client requests. The JSP is translated into a servlet1 by a servlet container, such as tomcat, and this servlet responds to the client's request. Servlets are a technique for dynamically creating HTML pages. However, it has been difficult to write Java code and HTML code together. The servlet must create the HTML design as a Java string and pass it as an argument to a method in the output stream. This means that the HTML code is inserted into the Java code in Servlet. In JSP, this is the opposite. Java code is inserted into the HTML design. This means that JSPs can be written more easily than servlets in writing design and code together.2 JSP is a useful technique when you need to show your users the dynamically generated HTML with a complex design.

Create a hello.jsp file in the top-level directory of your ROOT application (C:/www/myapp) and visit http://localhost:8080/hello.jsp.

/hello.jsp
<html>
<body>
Hello, World!
</body>
</html>

When Tomcat first receives a /hello.jsp request, Tomcat creates a servlet from hello.jsp as follows:

// .. omit ..

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>\n");
  out.write("<body>\n");
  out.write("Hello, World!\n");
  out.write("</body>\n");
  out.write("</html>\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);
}

// .. omit ..

Because hello.jsp is created in the top-level directory of the ROOT application, the full path to the generated servlet is CATALINA_HOME\work\Catalina\localhost\_\org\apache\jsp\hello_jsp.java. Tomcat compiles this servlet, creates a servlet object from the servlet bytecode, and invokes the service method of the servlet object. When hello.jsp request arrives again, Tomcat checks whether the hello.jsp file has been changed. If hello.jsp has not changed, Tomcat checks whether the servlet object is loaded. If the servlet object is in memory, Tomcat call the service method of the servlet object. If the servlet object is not in memory, Tomcat create a servlet object. If hello.jsp is changed, Tomcat make a servlet Java source from hello.jsp.

2. Directives

Directives provide general information about a JSP to a Servlet Container. There are three directives: page, include, and taglib.

2.1 page directive

<%@ page {attribute="value"} %>
attribute="value" Description
language="scriptLanguage" the server-side language to compile the page (mostly java)
import="importList" The Java package or Java package list that the page imports. Lists are separated by commas (,).
session="true | false" Sets whether the page uses session data (default is true).
errorPage="error_uri" relative path of the error page that handles the JSP exception.
isErrorPage="true | false" whether the page is a error page (default is false).
contentType="ctinfo" Set the MIME type and charset of the response.
pageEncoding="charset" the charset of the JSP file. Specifies the same as the charset specified by contentType.

If omitted, there are many attributes to which the default value applies. Therefore, you do not need to set all attributes. The contentType attribute can only be set once and is set in most of the first page directives. You can set multiple import attributes.

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ page import="java.util.HashMap,java.util.ArrayList" %>

There are two page directives in this example. The first directive above sets the response of content type to text/html (HTML Documents) and the character set of response content to UTF-8. UTF-8 is currently the most popular character set on the Internet. The second page directive has only the import attribute set. The Java codes in JSP will use java.util.HashMap and java.util.ArrayList. You can also set the import attribute on the first page directive, but doing so is not recommended. You can change the above as follows.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.ArrayList" %>

It is recommended to code this way because it is easy to see.

2.2 include directive

The include directive is used to insert a document into a servlet which is made from a JSP. The document to be inserted must exist within the web application.

<%@ include file="header.jsp" %>

2.3 taglib directive

The taglib directive specifies the tag library used by the JSP page. A tag library is a technique for creating a tag that changes to Java code when converted to a servlet. If you can use tags instead of Java code in JSP, you can manage your design efficiently. However, with the advent of a large number of tag libraries, programmers have become increasingly reluctant to use tag libraries.

The tag library uses prefix and uri to uniquely distinguish its tag set.

<%@ taglib uri="tagLibraryURI" prefix="tagPrefix" %>

The uri is a URI Information that uniquely names the tag library. The prefix is used to distinguish the tag libraries within a JSP page.

I will not discuss how to create a tag library. The JSP Standard Tag Library (JSTL) included in the JSP specification is covered in the JSP Project.

3. Scripting

Scripting is used to insert Java code into JSP pages. There are three scripting: Declarations, Expressions, Scriptlets,

3.1 Declarations

Declarations are used to declare servlet instance variables and methods within a JSP page. The following declaration is converted to an instance variable of the servlet class.

<%! String name = new String("Alison"); %>

The following declaration is converted to instance method of the servlet class.

<%! 
public String getName() {
	return name;
} 
%>

3.2 Expressions

The expression is converted to a string by the servlet container. If the expression is not converted to a string, a ClassCastException is thrown. The following expression prints Hello, Alison to the web browser.

Hello, <%=getName()%>

3.3 Scriptlets

You can insert Java statements freely within scriptlets. A Java statements in <% ...%> are included in the servlet's _jspSevice() method when a servlet is made from a JSP.

4. Actions

Actions are used to create or modify objects.

4.1 <jsp:useBean>

This action creates a bean or finds the bean that was created. First, it looks for objects that use the same scope and id. If the object is not found, it creates the object according to the given scope and id attributes.

<jsp:useBean id="name" scope="application" class="net.java_school.db.dbpool.OracleConnectionManager" />
<jsp:useBean>'s attributes
attribute Description
id The key to identify the object instance in the same scope.
scope The range in which the generated bean's reference is valid, page(default), request, session, application
class FQCN(Fully Qualified Class Name) 패키지를 포함한 클래스 이름
type The superclass or interface of the class defined in the class attribute.

<jsp:useBean id="cart" scope="request" class="example.Cart" /> is like the following scriptlet:

<%
    example.Cart cart;
    cart = (example.Cart) request.getAttribute("cart");
    if (cart == null) {
        cart = new example.Cart();
        request.setAttribute("cart", cart);
    }
%>

4.2 <jsp:setProperty>

This action is used to set the property value of the bean.

<jsp:useBean id="login" scope="page" class="example.User" />
<jsp:setProperty name="login" property="passwd" />

The above code is like the scriptlet below.

<%
    example.User user;
    user = (example.User) pageContext.getAttribute("user");
    if (user == null) {
        user = new example.User();
        pageContext.setAttribute("user", user);
    }
    String _jspParam;
    _jspParam = request.getParameter("passwd");
    if (_jspParam != null && !_jspParam.equals(""))
        user.setPasswd(_jspParam);
%>
<jsp:setProperty>'s attributes
Attribute Description
name The name of the bean instance defined in <jsp:useBean>.
property Beans property to change the value. If property="*", all properties of the bean are modified by calling any setter method that matches all parameter names in the HTTP request. But if the value of the parameter is "", the property of the corresponding bean is not modified.
param The value of the param attribute is one of the parameter names of the HTTP request. The value of the beans property set in the property attribute is set to the param attribute value.
value Change the property of the bean to the string defined in the value attribute.

Suppose you have the following form page.

<form action="register.jsp" method="post">
    <input type="text" name="id" />
    <input type="password" name="passwd" />
</form>

Suppose there is the following action in register.jsp that receives the value entered in the form by a user:

<jsp:setProperty name="user" property="*" />

The above action is like the scriptlet below.

<%
    String _jspParam;
    _jspParam = request.getParameter("passwd");
    if ( _jspParam != null && !_jspParam.equals("") )
        user.setPasswd(_jspParam);
    _jspParam = request.getParameter("id");
    if ( _jspParam != null && !_jspParam.equals("") )
        user.setId(_jspParam);
%>

Suppose you have the following form page:

<form action="signUp.jsp" method="post">
    <input type="text" name="member_id" />
</form>

Suppose you have the following action in signUp.jsp that receives a form input value:

<jsp:setProperty name="user" property="id" param="member_id" />

The above action is like the scriptlet below.

<%
    String _jspParam;
    _jspParam = request.getParameter("member_id");
    if (_jspParam != null && !_jspParam.equals(""))
        user.setId(_jspParam);
%>

As you can see in the example above, if the name of the bean's member variable and the name of the form's parameter are not equal, you need to use the param attribute.

The following is an example of the setProperty action.

<jsp:setProperty name="user" property="id" value="admin" />

The above setProperty action is like the following scriptlet.

<%
    user.setId("admin");
%>

As in the example above, the setProperty action is used to set the property value of the bean.

4.3 <jsp:getProperty>

The getProperty action takes the property value of the bean and puts it into the output stream.

<jsp:getProperty name="name" property="propertyName" />
<jsp:getProperty>'s attributes
Attribute Description
name The name of the bean instance
property a property of bean instance

4.4 <jsp:param>

This action is used to define the parameters to pass to <jsp:include> and <jsp:forward>.

<jsp:param name="name" value="value" />

4.5 <jsp:include>

This action is used to add static (HTML) or dynamic web components (JSP, Servlets) to a JSP page.

<jsp:include page="urlSpec" flush="true">
	<jsp:param ... />
</jsp:include>
<jsp:include>'s attributes
Attribute Description
page Relative path of the resources to be included
flush Whether the buffer is flushed

4.6 <jsp:forward>

This action is used for forwarding. Forwarding means that the resource that is requested by the client passes control to another resource. <jsp:forward> can have <jsp:param> as its child element, in order to pass parameters to the target resource to which control is passed. The page attribute is the relative address of the target resource to which control is passed.

<jsp:forward page="relativeURL">
	<jsp:param .../>
</jsp:forward>

5. Implicit Objects

An implicit object is an object used in a JSP and can be used immediately without any effort to obtain a reference value.

5.1 out

It is a reference to the instance of javax.servlet.jsp.JspWriter abstract class type. It used to write data to the response stream. Create helloworld.jsp in the root directory of your ROOT application as shown below and visit http://localhost:8080/helloWorld.jsp.

/helloWorld.jsp
<html>
<body>
<%
out.println("Hello, World!");
%>
</body>
</html>

Compare the servlet made from hello.jsp with the servlet made from helloworld.jsp. The full path of each servlet is:

  • CATALINA_HOME\work\Catalina\localhost\_\org\apache\jsp\hello_jsp.java
  • CATALINA_HOME\work\Catalina\localhost\_\org\apache\jsp\helloworld_jsp.java

5.2 request

This is a reference to the instance of javax.servlet.http.HttpServletRequest interface type. This reference allows you to access request parameters, information sent by the user in the header, and information about the user. Create request.jsp in the root directory of your ROOT application as shown below and visit http://localhost:8080/request.jsp?user=alison

/request.jsp
<html>
<body>
<%
out.println("Hello, " + request.getParameter("user"));
%>
</body>
</html>

5.3 response

It is a reference to the instance of javax.servlet.http.HttpServletResponse interface type.

5.4 pageContext

This is a reference to the instance of javax.servlet.jsp.PageContext abstract class type. It provides access to all available resources within the JSP. For example, it provides access to resources such as ServletRequest, ServletResponse, ServletContext, HttpSession, and ServletConfig.

5.5 session

This is a reference to the instance of javax.servlet.http.HttpSession type. It is used to read and store session data. Create session.jsp in the root directory of your ROOT application as shown below and visit http://localhost:8080/session.jsp several times.

/session.jsp
<html>
<head>
  <title>session</title>
</head>
<body>
<%
Integer count = (Integer)session.getAttribute("count");
  
if (count == null) {
	count = new Integer(1);
	session.setAttribute("count", count);
} else {
	count = new Integer(count.intValue() + 1);
	session.setAttribute("count", count);
}
out.println("COUNT: " + count); 
%> 
</body>
</html>

5.6 application

It is a reference to the instance of javax.servlet.ServletContext interface type.

5.7 config

It is a reference to the javax.servlet.ServletConfig inferface type instance. The ServletConfig type instance contains servlet initialization parameter information.

5.8 page

It is a reference of type Object that refers to the servlet instance. This is why you cannot declare a variable named page in JSP scripting. This is not much use.

5.9 exception

The exception implicit object provides access to the uncaught exception that occurred in a JSP. The exception variable can only be used within pages whose page directive's isErrorPage attribute is set to true.

6. Things to check in JSP syntax

6.1 Differences between include directive and include action

If you use the include directive, one servlet made from one JSP into which all JSPs combined will responds to the client's request. If you use the include action, the JSP in the include action becomes an independent servlet and participates in creating a single response. In other words, a directive is interpreted once when converted to a servlet, but in the case of an action it is interpreted each time it is requested. Therefore, theoretically, it is better to use the include directive when the content of the included page does not change on demand, and the include action if the content of the included page changes on demand.

6.2 The relationship between a ServletContext and a web application

According to the servlet specification, only one ServletContext object is created per web application. ServletContext has methods that communicate with the server-side components of the web application and the servlet container. So ServletContext serves as a common repository for server-side components such as JSPs and servlets. The resources stored in ServletContext exist for the lifetime of the web application.

6.3 page directive's session attribute

If the session attribute of the page directive is set to false, such as <%@ page session="false" ..>, the page can not create a session object nor can it obtain a reference to an existing session object. If you try to access the session object while session is set to false, an error occurs.

6.4 jsp:useBean action's scope

The scope attribute of <jsp:useBean> determines how far to use the JavaBean. Depending on how the scope attribute is specified, the bean object is referenced without being destroyed on multiple pages. For example, if the scope attribute is set to session, this bean object will not be destroyed until the end of the session. The default value of scope is page. You can specify four values for the scope attribute, which are summarized as follows.

Scope Description
page The default value of scope is page. If scope is not specified, page is set. A bean whose scope attribute is page is valid only on the page. A bean whose scope attribute is page is created each time a page is requested and destroyed when the page finishes execution. A bean whose scope attribute is page can not be referenced in the target page of a jsp:include or jsp:forward action. If there is a jsp:useBean action with the same id and scope bean on the target page, this action creates a new bean. (It does not refer to the bean created on the page that handed over control.) Also, a bean created on the target page of the jsp:include action can not be referenced on a page that handed over control. The page scope beans are appropriate when the state of the beans does not need to be maintained.
request The bean whose scope attribute is request is stored in the HttpServletRequest object. Therefore, A bean whose scope attribute is request can also be referenced from the target page of the jsp:forward and jsp:include actions.
session The bean whose scope attribute value is session is stored in the session object (HttpSession type object). Therefore, the bean whose scope attribute value is session will not be destroyed on all pages that are called during session maintenance. On the other hand, a bean whose scope attribute value is page or request is destroyed after it responds to the browser. The session object created for each user maintains a value that can be referenced by all server-side components until the session ends. Note that JSP whose session attribute of the page directive is set to false can not use the beans stored in the session object.
application The bean whose scope attribute value is application is stored in the ServletContext object. Therefore, the bean whose scope attribute value is application is not destroyed until the web application is unloaded. All JSPs and servlets in the same web application that can access the ServletContext can access this bean. Beans in the ServletContext are common resources for a web application. (we have learned that the ServletContext serves as the common repository) For that reason, you should decide carefully about setting scope to application.

7. JSP Examples

7.1 JSP error handling in the early Servlet/JSP spec

JSP spec provides a way to deal with errors by providing a JSP page that can handle only errors. If there is an unhandled exception in the JSP, the servlet container passes the request to the JSP error page. The exception object that occurred at this time is also passed. Creating a JSP error page is simple. To make jsp error page, set the value of the page directive's isErrorPage attribute to true. Create the following errorPage.jsp in the ROOT application's documentbase.

/errorPage.jsp
<%@ page isErrorPage="true" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<html>
<body>
<p>
The following error has occurred.<br />
<%=exception.getMessage() %>
</p>
</body>
</html>

IsErrorPage="true" tells the container that this page deals with the error professionally.

<%=exception.getMessage() %> prints the error message of the exception sent to the error page. Here exception is an implicit object. The exception implicit object can only be referenced from a JSP page with the value of the page directive's isErrorPage attribute set to true. To see how the error page works, write the following JSP page into the ROOT application's documentbase.

/errorMaker.jsp
<%@ page errorPage="errorPage.jsp" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%
if (true) {
	throw new Exception("Intentionally occurred Exception.");
}
%>

Handling errors using error pages was in the initial specification of Servlet/JSP.

7.2 JSP error handling in the current Servlet/JSP spec

You can specify an error page in the web.xml file, by HTTP status code3 and the type of exception that occurs. This spec was added in Servlet 2.3.

WEB-INF/web.xml
<error-page>
	<error-code>404</error-code>
	<location>/error.jsp</location>
</error-page>
<error-page>
	<error-code>403</error-code>
	<location>/error.jsp</location>
</error-page>
<error-page>
	<error-code>500</error-code>
	<location>/error.jsp</location>
</error-page>

With this approach, you can not use implicit object exception in error.jsp. Instead, you can get the exception object with the newly added property value as follows: 4

Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception");

Here is a list of the attributes of the request related to the error. All of them can be accessed in the same way as above.

javax.servlet.error.status_code
Error status code. java.lang.Integer type
javax.servlet.error.exception_type
Exception type. java.lang.Class type
javax.servlet.error.message
Error message. String type
javax.servlet.error.exception
Exceptions occurred. java.lang.Throwable type
javax.servlet.error.request_uri
The URI of the resource that caused the problem. String type
javax.servlet.error.servlet_name
The name of the servlet that caused the problem. String type
/error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Error</title>
</head>
<body>
<%
//Analyze the servlet exception
Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception");
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
String servletName = (String) request.getAttribute("javax.servlet.error.servlet_name");

if (servletName == null) {
    servletName = "Unknown";
}

String requestUri = (String) request.getAttribute("javax.servlet.error.request_uri");

if (requestUri == null) {
    requestUri = "Unknown";
}
 
if(statusCode != 500){
    out.write("<h3>Error Details</h3>");
    out.write("<strong>Status Code</strong>:" + statusCode + "<br>");
    out.write("<strong>Requested URI</strong>:"+requestUri);
}else{
    out.write("<h3>Exception Details</h3>");
    out.write("<ul><li>Servlet Name:" + servletName + "</li>");
    out.write("<li>Exception Name:" + throwable.getClass().getName() + "</li>");
    out.write("<li>Requested URI:" + requestUri + "</li>");
    out.write("<li>Exception Message:" + throwable.getMessage() + "</li>");
    out.write("</ul>");
}
%>
</body>
</html>

Visit http://localhost:8080/alison.jsp. Because you did not create the alison.jsp file in the ROOT application's document base, a 404 error will occur and the error.jsp file will respond. In IE, if the content of the error page is less than a certain byte, the error page does not work.3

It is better not to set the error page at the development stage.

Cookies are simple data stored in a web browser and sent together when sending a request. If the cookie's lifetime is specified using the setMaxAge() method, the web browser stores the cookie as a file in its own cookie store. Cookies without setMaxAge() will disappear when the web browser exits.

Cookie operation process
  1. The web browser requests a server resource with code to burn cookies.
  2. The server resource adds the cookie value to the HTTP response header.
  3. The web browser stores the cookie data in the response header.
  4. The web browser also sends cookie data whenever it requests a resource on the website that provided the cookie.

In step 2, the cookie value included in the response header is the following string.

Set-Cookie: name=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure

The string highlighted above is required data, Italics are the parts that need to be changed to actual values.

In the fourth step, the cookie information included in the request header is the following string.

Cookie: name1=VALUE1; name2=VALUE2;...
One cookie consists of the following information:
  • name
  • value
  • expires
  • domain
  • path
  • secure(https)

The following is a cookie class.

javax.servlet.http.Cookie
Cookie(String name, String value)
getName()
setValue(String)
getValue()
setDomain(String)
getDomain()
setPath(String)
getPath()
setMaxAge(int)
getMaxAge()
setSecure(boolean)
getSecure()

The following code snippet shows how to use the Cookie class.

/*
* Creates a cookie.
*/
Cookie cookie = new Cookie("user", "alison");

/*
*  If it starts with a dot, the cookie is sent to the relevant domain.
* www.java-school.net, user.java-school.net, blog.java-school.net, etc.
*/
cookie.setDomain(".java-school.net");

/*
* To create a cookie that applies to the full path of your website, set the path to '/'. 
* If you set a specific path, such as '/ user', cookies are sent only to requests containing '/user'.
*/
cookie.setPath("/");

/*
* Set cookie expire time in seconds.
* If a negative value is set here, the cookie is deleted when the web browser exits. 
*/
cookie.setMaxAge(60*60*24*30); //Cookies valid for 30 days

Let's create a simple example of cookies. Create a cookie subdirectory under the document base and create the following files in it.

/cookie/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Cookie Test</title>
</head>
<body>
<h1>Cookie Test</h1>
<ul>
	<li><a href="setCookie.jsp">Burn Cookies</a></li>
	<li><a href="viewCookie.jsp">Confirm Cookies</a></li>
	<li><a href="editCookie.jsp">Modify Cookies</a></li>
	<li><a href="delCookie.jsp">Delete Cookies</a></li>
</ul>
</body>
</html>
/cookie/setCookie.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.net.*"  %>
<%
Cookie cookie = new Cookie("name", URLEncoder.encode("Alison", "UTF-8"));

/*
* If setPath() is not used, the path is set to the directory where setCookie.jsp is located. (path=/cookie)
*/ 
response.addCookie(cookie);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Burn Cookies</title>
</head>
<body>
Set-Cookie: <%=cookie.getName() %>=<%=cookie.getValue() %><br />
<a href="viewCookie.jsp">Confirm Cookies</a> 
</body>
</html>
/cookie/viewCookie.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.net.*" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Confirm Cookies</title>
</head>
<body>
<%
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 1) {
	int length = cookies.length;
	for (int i = 0; i < length; i++) {
%>
	<%=cookies[i].getName() %>=<%=URLDecoder.decode(cookies[i].getValue(), "UTF-8") %><br />
<%			
	}
}
%>
<a href="./">index.html</a>
</body>
</html>
/cookie/editCookie.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.net.*" %>
<%
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 1) {
	int length = cookies.length;
	for (int i = 0; i < length; i++) {
		if (cookies[i].getName().equals("name")) {
			Cookie cookie = new Cookie("name", URLEncoder.encode("Bill" ,"UTF-8"));
			response.addCookie(cookie);
		}
	}
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Modify Cookies</title>
</head>
<body>
Cookie value changed.<br />
<a href="viewCookie.jsp">Confirm Cookies</a>
</body>
</html>
/cookie/delCookie.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 1) {
	int length = cookies.length;
	for (int i = 0; i < length; i++) {
		if (cookies[i].getName().equals("name")) {
			Cookie cookie = new Cookie("name", "");
			cookie.setMaxAge(0);
			response.addCookie(cookie);
			break;
		}
	}
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Delete Cookies</title>
</head>
<body>
name cookie deleted.<br />
<a href="viewCookie.jsp">Confirm Cookies</a>
</body>
</html>

7.4 Separate pages using include directive

Download example.zip and unzip it to the root directory of your ROOT application. Visit http://localhost:8080/example/ex1/index.jsp. Open the index.jsp file and confirm the following:

<%@ include file="sub.jsp" %>

The index.jsp includes sub.jsp. By separating the parts of the page into separate files and integrating them using the include directive, maintenance becomes easier. In the sub.jsp code, the path for files, images, style sheets, and so on should be relative to index.jsp. This is because JSP files are combined based on index.jsp. However, the paths in style sheet code, should be relative to the style sheet file not index.jsp.

7.5 Login using JavaBeans (using session)

The location of this example is /example/ex2/. Visit http://localhost:8080/example/ex2/index.jsp. There is work to do to test the login. The login_proc.jsp page is the page that processes the login. The login_proc.jsp uses net.java_school.user.User.java JavaBeans. To run the example, write net.java_school.user.User.java as below and compile to generate bytecode in WEB-INF/classes.

User.java
package net.java_school.user;

public class User {

  private String id;
  private String passwd;
	
  public String getId() {
      return id;
  }
	
  public void setId(String id) {
      this.id = id;
  }
	
  public String getPasswd() {
      return passwd;
  }	
	
  public void setPasswd(String passwd) {
      this.passwd = passwd;
  }

}

If you have finished creating and compiling User.java, Go back to http://localhost:8080/example/ex2/index.jsp and test your login. Open the file /example/ex2/index.jsp and confirm the followings.

<input type="text" name="id" />

The id parameter is sent to login_proc.jsp. Open the file /example/ex2/login_proc.jsp and check the code below.

String id = request.getParameter("id");

The value of the id parameter in login_proc.jsp can be obtained using the getParameter() method of the request implicit object. Login_proc.jsp creates a User object and sets the member variables of the User object using the passed id and passwd parameters. The login process is completed by putting this User object in the session. In order to simplify the example, I omitted the code related to the database query. Therefore, login is successful for any ID and password.

login_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="net.java_school.user.User" %>

<%
String id = request.getParameter("id");
String passwd = request.getParameter("passwd");

/* 
* Here you need the logic to query the database for members with id and passwd.
*/
User user = new User();
user.setId(id);

// After creating the session, save the User object as "user" in the session.
session.setAttribute("user", user);
%>

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

7.6 Modify the 'Login using JavaBeans (using session)' to be an example using Action

The location of the example is /example/ex3/. This example has the same functionality as the previous example. I just changed login_proc.jsp to use the action. If you open the login_proc.jsp file, you can see that the code has been simplified as shown below.

/login_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="net.java_school.user.User" %>
<jsp:useBean id="user" scope="session" class="net.java_school.user.User" />
<jsp:setProperty name="user" property="*"/>
<jsp:forward page="index.jsp" />

The jsp:useBean action finds an object whose key value is "user" in the session. If there is no such object, this action creates a User object from the net.java_school.user.User class and store it in the session with the id attribute value of the jsp:useBean action as the key value. The jsp:setProperty action passes the values of the parameters in the HTTP request as arguments to the setter method of the JSP bean. The jsp:setProperty action sets the member variables by calling the setter methods of the JSP bean with the values of the parameters in the HTTP request.

<jsp:setProperty name="user" property="*"/>

The above action calls the setId() and setPasswd() methods of the User bean. The value of the HTTP request parameter matching the setter method name is passed as the parameter value of the setter method.

JSP or JSP bean Code
index.jsp
<input type="text" name="id" />
login_proc.jsp
<jsp:setProperty name="login" property="id" />
User.java
setId(String id)

In the "setId()" method name, the "I" in Id is an uppercase letter. (We already studied Java naming convention in Java chapter) When using the jsp:setProperty action, it will not work unless the JSP bean follows the Java naming convention. That is, when using actions, the Java naming convention is not a recommendation, but a grammar.

7.7 JSP that shows uploaded files

We already covered the file upload example in the servlet chapter. The following JSP shows a list of uploaded files in the upload folder.

/fileList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.io.*" %>
<%@ page import="java.net.*" %>
<%
String upload = application.getRealPath("/upload");

File dir = new File(upload);
File[] files = dir.listFiles();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>List of saved files</title>
<script type="text/javascript">
function goDownload(filename) {
	var form = document.getElementById("downForm");
	form.filename.value = filename;
	form.submit();
}
</script>
</head>
<body>
<%
int len = files.length;
for (int i = 0; i < len; i++) {
	File file = files[i];
	String filename = file.getName();
%>
	<a href="javascript:goDownload('<%=filename %>')"><%=file.getName() %></a><br />
<%
}
%>
<form id="downForm" action="download.jsp" method="post">
	<input type="hidden" name="filename" />
</form>
</body>
</html>

7.8 JSP which downloads files

The following is the JSP that works when you click the file name on the file list page above.

/download.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page import="java.io.File" %>
<%@ page import="java.net.URLEncoder" %>
<%@ page import="java.io.OutputStream" %>
<%@ page import="java.io.FileInputStream" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.commons.io.FileUtils" %>
<%
request.setCharacterEncoding("UTF-8");
String filename = request.getParameter("filename");

String path = application.getRealPath("/upload");
File file = new File(path + "/" + filename);

response.setContentLength((int) file.length());

String filetype = filename.substring(filename.indexOf(".") + 1, filename.length());
if (filetype.trim().equalsIgnoreCase("txt")) {
	response.setContentType("text/plain");
} else {
	response.setContentType("application/octet-stream");
}

String userAgent = request.getHeader("user-agent");
boolean ie = userAgent.indexOf("MSIE") != -1;
if (ie) {
	filename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", " ");
} else {
	filename = new String(filename.getBytes("UTF-8"), "8859_1");
}

response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\";");
/* response.setHeader("Content-Transfer-Encoding", "binary"); */

OutputStream outputStream = response.getOutputStream();

try {
	FileUtils.copyFile(file, outputStream);
} finally {
	outputStream.flush();
}
%>

7.9 JSP that uploads files

The following is a JSP replacement of the file upload servlet we covered in the Servlet chapter.

fileupload_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="
java.util.Iterator,
java.io.File,java.util.List,
javax.servlet.http.HttpServletRequest,
org.apache.commons.fileupload.FileItem,
org.apache.commons.fileupload.FileItemFactory,
org.apache.commons.fileupload.FileUploadException,
org.apache.commons.fileupload.disk.DiskFileItemFactory,
org.apache.commons.fileupload.servlet.ServletFileUpload" %>
<%
//Check that we have a file upload request
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
//Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();

//Configure a repository (to ensure a secure temp location is used)
File repository = (File) application.getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);

//Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");
//Parse the request
List<FileItem> items = upload.parseRequest(request);
//Process a file upload
Iterator<FileItem> iter = items.iterator();
while (iter.hasNext()) {
	FileItem item = iter.next();
	String fileName = null;
	if (!item.isFormField()) {
		String fieldName = item.getFieldName();
		out.println("fieldName : " + fieldName);out.println(",");
		fileName = item.getName();
		out.println("fileName : " + fileName);out.println(",");
		String contentType = item.getContentType();
		out.println("contentType : " + contentType);out.println(",");
		boolean isInMemory = item.isInMemory();
		out.println("isInMemory : " + isInMemory);out.println(",");
		long sizeInBytes = item.getSize();
		out.println("sizeInBytes : " + sizeInBytes);
	}
	// Process a file upload
	String dir = application.getRealPath("/upload");
	File uploadedFile = new File(dir + "/" + fileName);
    item.write(uploadedFile);
}
response.sendRedirect("upload.html");
%>
Comments
  1. Servlets made from JSPs are similar to servlets we learned in previous chapters, but they are not the same.
  2. Using JSTL to write JSP can further reduce the difficulty of writing HTML and Java code together.
  3. HTTP status code 404 means not found, 403 means prohibited, and 500 means an internal server error.
  4. With JSTL you can access:
    <c:out value="${requestScope['javax.servlet.error.message']}" />