View RSS Feed

Servlet

General Event Handling in Servlets Part 2

Rate this Entry
by , 11-28-2011 at 11:26 PM (1395 Views)
In the last article, we started to look into the Application Events Framework for servlets and javaserver pages. We listed eight different kinds of events listeners that are related to web application life-cycle events. If you are interested, go review the post, General Event Handling in Servlets Part 1.

In that article, we looked at the first of the listeners for the initialization and destruction of servlet context and we presented an example of it’s use for a company that is constantly rebranding itself. In this article, we are going to look at the listener connected to notifications in the servlet context attributes by building on our previous application.

The Web application is loaded and you can then set up initial values of resources and store references to them in the servlet context. Next we want to be notified whenever these resources change. So we will design the behavior such that the value of resource B depends on the value of resource A. Therefore if resource A changes, it’s necessary to automatically update the value of resource B. Handling this situation is the job of servlet context attribute listeners. Using them involves the following steps.
  1. Implement the ServletContextAttributeListener interface. This interface is in the javax.servlet package.
  2. Implement attributeAdded, attributeReplaced, and attributeRemoved. The attributeAdded method is triggered when a new attribute is added to the servlet context. When a new value is assigned to an existing servlet context attribute, attribute- Added is triggered with the new value and attributeReplaced is triggered with the old value (i.e., the value being replaced). The attributeRemoved method is triggered when a servlet context attribute is removed altogether.
  3. Obtain references to the attribute name, attribute value, and servlet context. Each of the three ServletContextAttribute- Listener methods takes a ServletContextAttributeEvent as an argument. The ServletContextAttributeEvent class has three useful methods: getName (the name of the attribute that was changed), getValue (the value of the changed attribute—the new value for attributeAdded and the previous value for attribute- Replaced and attributeRemoved), and getServletContext (the servlet context).
  4. Use the objects. You normally compare the attribute name to a stored name to see if it is the one you are monitoring. The attribute value is used in an application-specific manner. The servlet context is usually used to read previously stored attributes (getAttribute), store new or changed attributes (setAttribute), and make entries in the log file (log).
  5. Declare the listener. Use the listener and listener-class elements to simply list the fully qualified name of the listener class, as shown here:


Java Code:
<listener>
<listener-class>somePackage.SomeListener</listener-class>

</listener>
Continuing from our previous example’s we have now provided the means to read the current and former company names when the Web application is loaded and how to make use of those values in JSP pages. Next we want to change the company name during the execution of the Web application. We use the servlet context attribute in order to modify the companyName servlet context attribute. So when we change the company name, we modify the formerCompanyName attribute as well. In order to achieve this, we use the servlet context attribute listeners.
The following steps summarize a listener that automatically updates the former company name whenever the current company name changes.
  1. Implement the ServletContextAttributeListener inter- face. Listing 6.5 shows a class (ChangedCompanyNameListener) that implements this interface.
  2. Implement attributeAdded, attributeReplaced, and attributeRemoved. The attributeReplaced method is used to detect modification to context attributes. Empty bodies are supplied for the attributeAdded and attributeRemoved methods.
  3. Obtain references to the attribute name, attribute value, and servlet context. The attributeReplaced method calls getName and getValue on its ServletContextAttributeEvent argu- ment to obtain the name and value of the modified attribute. The method also calls getServletContext on its argument to get a reference to the servlet context.
  4. Use the objects. The attribute name is compared to "company- Name". If the name matches, the attribute value is used as the new value of the formerCompanyName servlet context attribute.
  5. Declare the listener. The listener is declared in the deployment descriptor with the listener and listener-class elements, as shown here:<listener> <listener-class>com.acme.webexample.listeners.ChangedCompany NameListener </listener-class></listener>


The ChangeCompanyNameListener is shown in Listing 1. It checks to see if the name has changed. If that is the case, it sets the formerCompanyName attribute to the previous name of the company. The web.xml file is shown in Listing 2 for defining the listener, the servlet and the new jsp pages around authentication. Note that it also contains Form-Based Authentication details since we are adding a level of security. The JSP page, In the Listing 4, is shown companydetails.jsp. This javaserver page contains a form that displays the current company name, lets users enter a new name, and submits the new name to the ChangeCompanyName servlet (Listing 5). Because changing the company name is a privileged operation, access to the form and the servlet is restricted.

The form is placed in the admin directory and the servlet and servlet- mapping elements are used to assign the servlet a URL that also starts with /admin. Next, the security-constraint element is used to authorize only authenticated users in the ceo role to access the admin directory. The ceo role is declared using the security-role element. Then, the login-config element is used to specify that form-based authentication be used. This is handled by the login.jsp page. The login.jsp page collects the usernames and passwords. If the login is unsuccessful the login-error.jsp, shown in Listing 7, will display messages to users as to the reason of the failed authentication.

Listing 1 - ChangedCompanyNameListener.java
Java Code:
package com.acme.webexample.listeners;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;

public class ChangedCompanyNameListener implements
		ServletContextAttributeListener {

	@Override
	public void attributeAdded(ServletContextAttributeEvent arg0) {
	}

	@Override
	public void attributeRemoved(ServletContextAttributeEvent arg0) {
	}

	/**
	 * When the companyName attribute changes, put 
	 * the previous value into the formerCompanyName 
	 * attribute.
	 */
	@Override
	public void attributeReplaced(ServletContextAttributeEvent event) {
		if (event.getName().equals("companyName")) {
			String oldName = (String) event.getValue();
			ServletContext context = event.getServletContext();
			context.setAttribute("formerCompanyName", oldName);
		}
	}

}

Listing 2 - web.xml
Java Code:
 <?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

	<display-name></display-name>
	<!-- Because the company name changes so frequently, supply it as a servlet 
		context parameter instead of embedding it into lots of different servlets 
		and JSP pages. The InitialCompanyNameListener will read this value and store 
		it in the servlet context. -->
	<context-param>
		<param-name>companyName</param-name>
		<param-value>acme.com</param-value>
	</context-param>
	<!-- Also store the previous company name. -->
	<context-param>
		<param-name>formerCompanyName</param-name>
		<param-value>nuts-and-bolts.com</param-value>
	</context-param>
	<!-- Register the listener that sets up the initial company name. -->
	<listener>
		<listener-class>com.acme.webexample.InitialCompanyNameListener</listener-class>
	</listener>

	<listener>
		<listener-class>com.acme.webexample.ChangedCompanyNameListener</listener-class>
	</listener>

	<!-- Assign the name ChangeCompanyName to webexample.ChangeCompanyName. -->
	<servlet>
		<servlet-name>ChangeCompanyName</servlet-name>
		<servlet-class>com.acme.webexample.ChangeCompanyName</servlet-class>
	</servlet> <!-- Assign the URL /admin/ChangeCompanyName to the servlet that is named 
		ChangeCompanyName. -->
	<servlet-mapping>
		<servlet-name>ChangeCompanyName</servlet-name>
		<url-pattern>/admin/ChangeCompanyName</url-pattern>
	</servlet-mapping>
	<!-- Protect everything within the "admin" directory. Direct client access 
		to this directory requires authentication. -->
	<security-constraint>
		<web-resource-collection>
			<web-resource-name>Admin</web-resource-name>
			<url-pattern>/admin/*</url-pattern>
		</web-resource-collection>
		<auth-constraint>
			<role-name>ceo</role-name>
		</auth-constraint>
	</security-constraint>
	<!-- Declare security roles. -->
	<security-role>
		<role-name>ceo</role-name>
	</security-role>
	<!-- Tell the server to use form-based authentication. -->
	<login-config>
		<auth-method>FORM</auth-method>
		<form-login-config>
			<form-login-page>/admin/login.jsp</form-login-page>
			<form-error-page>/admin/login-error.jsp</form-error-page>
		</form-login-config>
	</login-config>
</web-app>
Listing 3 - companychangename.jsp
XML Code:
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type"
			content="text/html; charset=ISO-8859-1">
		<title>Changing Company Name</title>
		<link rel="stylesheet" type="text/css" href="../events-styles.css">
	</head>
	<body>
		<table border=5 align="center">
			<tr>
				<th class="title">
					Changing Company Name
		</table>
		<p>
		<form action="ChangeCompanyName">
			New name:
			<input type="text" name="newName" value="${companyName}">
			<p>
			<center>
				<input type="submit" value="Submit Change">
			</center>
		</form>
	</body>
</html>
Listing 4 - companydetails.jsp
XML Code:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
	<head>
	  <title>${applicationScope.companyName}</title>
	  <link rel="stylesheet" type="text/css" href="events-styles.css">
	</head>

	<body>
	  <table border=5 align="center">
		<tr>
			<th class="title">
				${applicationScope.companyName}
				<br>
				(formerly ${applicationScope.formerCompanyName})
	  </table>
	    <p>
		Learn more about
		<b>${applicationScope.companyName}</b> (formerly
		${applicationScope.formerCompanyName})
	    <ul>
		<li><a href="products.jsp">${applicationScope.companyName} products</a>
		<li><a href="services.jsp">${applicationScope.companyName} services</a>
		<li><a href="history.jsp">${applicationScope.companyName} history</a>
		<li><a href="invest.jsp">investing in ${applicationScope.companyName}</a>
		<li><a href="contact.jsp">contacting ${applicationScope.companyName}</a>
	   </ul>
	</body>
</html>
Listing 5 - ChangeCompanyName.java

Java Code:
package com.acme.webexample.servlets;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet that changes the company name. The web.xml file specifies that only
 * authenticated users in the ceo role can access the servlet. A servlet
 * context attribute listener updates the former company name when this
 * servlet (or any other program) changes the current company name.
 */
public class ChangeCompanyName extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		boolean isNameChanged = false;
		String newName = request.getParameter("newName");
		if ((newName != null) && (!newName.equals(""))) {
			isNameChanged = true;
			getServletContext().setAttribute("companyName", newName);
		}
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		String docType = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 "
				+ "Transitional//EN\">\n";
		String title = "Company Name";
		out.println(docType + "<HTML>\n" + "<HEAD><TITLE>" + title
				+ "</TITLE></HEAD>\n" + "<BODY BGCOLOR=\"#FDF5E6\">\n"
				+ "<H2 ALIGN=\"CENTER\">" + title + "</H2>");
		if (isNameChanged) {
			out.println("Company name changed to " + newName + ".");
		} else {
			out.println("Company name not changed.");
		}
		out.println("</BODY></HTML>");
	}
}
Listing 6 - login.jsp

XML Code:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type"
			content="text/html; charset=ISO-8859-1">
		<title>Log In</title>
		<link rel=stylesheet href="../events-styles.css" type="text/css">
	</head>
	<body>
		<table border=5 align="center">
			<tr>
				<th class="title">
					Log In
		</table>
		<p>
		<h3>
			Sorry, you must log in before accessing this resource.
		</h3>
		<form action="j_security_check" method="POST">
			<table>
				<tr>
					<td>
						User name:
						<input type="text" name="j_username">
				<tr>
					<td>
						Password:
						<input type="password" name="j_password">
				<tr>
					<th>
						<input type="submit" value="Log In">
			</table>
		</form>
	</body>
</html>

Listing 7 - login-error.jsp
XML Code:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type"
			content="text/html; charset=ISO-8859-1">
		<title>Begone!</title>
		<link rel=stylesheet href="../events-styles.css" type="text/css">
	</head>
	<body>
		<table border=5 align="center">
			<tr>
				<th class="title">
					Begone!
		</table>
		<h3>
			Begone, ye unauthorized peon.
		</h3>
	</body>
</html>
We have now completed coding the parts necessary to detect changes in the servlet context as well as monitoring the creation and destruction of the servlet context. In the next article we will look at how to use listeners with tag libraries.

Submit "General Event Handling in Servlets Part 2" to Facebook Submit "General Event Handling in Servlets Part 2" to Digg Submit "General Event Handling in Servlets Part 2" to del.icio.us Submit "General Event Handling in Servlets Part 2" to StumbleUpon Submit "General Event Handling in Servlets Part 2" to Google

Updated 12-09-2011 at 04:13 PM by Servlet

Categories
Tutorial , Web , Listener , ServletContextListener

Comments