| Sign In/My Account | View Cart |
|
Six Cool New JSP and Servlet Featuresby Bruce W. Perry, author of Java Servlet & JSP Cookbook02/11/2004 |
If you use a web container such as Tomcat 5.x, which supports Servlet API 2.4 and JSP 2.0, then you can use a number of useful new features. These include:
RequestDispatchers.ServletRequestListener and
ServletRequestAttributeListener interfaces.In this article, we'll delve into how you can use each of these features in your projects, using working code examples. Let's take a look at the first one on the list.
Welcome files are automatic web server responses to requests that specify only
directories, not specific web components or files. When a visitor wants to request
a home page, for example, they normally will just type in the name of the protocol
(HTTP) and the host name, as in: http://www.google.com. Using Java web
components, you can configure the response that is automatically sent to
requests of this type by using a welcome-file element in WEB-INF/web.xml.
The element looks like this, with index.html as the welcome file, followed by its
alternative, default.jsp (if index.html does not exist in the web application, which
would be admittedly odd, considering that it is configured as a welcome file).
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
With Servlet 2.4, now you can have a servlet as a welcome file, which is useful for applications that use servlets as "Front Controllers." This is a design pattern representing the web components that grab the request and figure out the best place to which it should be routed among several alternatives. Here's how to configure a servlet as a welcome file.
First, register the servlet in web.xml.
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=
"http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
<servlet>
<servlet-name>MyServlet</servlet-name.
<servlet-class>com.jspservletcookbook.MyServlet</servlet-class>
</servlet>
<!-- optionally map the 'MyServlet' servlet to a URL pattern -->
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/myservlet</url-pattern>
</servlet-mapping>
<!-- rest of web.xml ... -->
Then create a welcome-file element in web.xml that specifies the registered
servlet name.
<welcome-file-list>
<welcome-file>MyServlet</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
Make sure to use the servlet name in the welcome-file element without a
forward slash (/) preceding it. With the prior configuration, the servlet is the
primary welcome file; however, default.jsp will be the welcome file, if a servlet of
that registered name does not exist in the web application.
RequestDispatchersFilters are great servlet API features that can intercept specified requests and
initiate logging, security measures, data compression, form-parameter validation,
or whatever task you need them to accomplish before the filter sends the request
back on its way. Servlet 2.4 now allows filters to intervene with
javax.servlet.RequestDispatcher objects that are including the
output of a web component or forwarding a request to another web component.
This feature is once again configured in WEB-INF/web.xml.
<?xml version="1.0"encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation=
"http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"version="2.4">
<filter>
<filter-name>LogFilter</filter-name>
<filter-class>com.jspservletcookbook.LogFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LogFilter</filter-name>
<url-pattern>/requestheaders</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
The dispatcher elements in the example configuration specify that the
LogFilter applies to requests for the servlet path /requestheaders, as well as
to any RequestDispatchers that include the output of the servlet path
/requestheaders.
Similarly, if you want to initiate a filter when you are using a
RequestDispatcher to forward a request to another component, use the
FORWARD value with the dispatcher element:
<filter-mapping>
<filter-name>LogFilter</filter-name>
<url-pattern>/requestheaders</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Servlet 2.4 provides two interfaces that you can use as application event
listeners for HTTP requests: javax.servlet.ServletRequestListener and
javax.servlet.ServletRequestAttributeListener. An
application event listener is an object that is notified when certain events occur,
so you can include objects that initiate tasks when a new request comes into
your application. For example, this code counts the number of web application
requests by incrementing a static variable inside of a
ServletRequestListener.
/* package and import statements */
public class ReqListener implements ServletRequestListener {
private static long reqCount;
//no args constructor made explicit here
public ReqListener(){}
public void requestInitialized(ServletRequestEvent sre){
//used for logging purposes
ServletContext context =sre.getServletContext();
//Used to get information about a new request
ServletRequest request =sre.getServletRequest();
//The static class variable reqCount is incremented in this block;
synchronized (context){
context.log(
"Request for "+
(request instanceof HttpServletRequest ?
((HttpServletRequest)request).getRequestURI():
"Unknown")+";Count="+ ++reqCount);
}//synchronized
}
public void requestDestroyed(ServletRequestEvent sre){
//Called when the servlet request is going out of scope.
}//requestDestroyed
}// ReqListener
Each time the web application receives a new request, the listener is notified and
its requestInitialized() method is called. This method's parameter is a
javax.servlet.ServletRequestEvent type. Calling this object's
getServletRequest() method gives the developer access to the new
request, a javax.servlet.ServletRequest type (to do whatever they
want with the new request).
The listener must have a constructor with no arguments. You have to register the
ServletRequestListener in web.xml:
<listener>
<listener-class>com.jspservletcookbook.ReqListener</listener-class>
</listener>
The web container then creates an instance of the listener when it deploys your web application.
Note: Servlet 2.4 also includes a
ServletRequestAttributeListener interface. An
object that implements this interface can receive notifications
of when object attributes are added to or removed from a
ServletRequest. You also have to register these listener
types in web.xml.
The Expression Language (EL) is a powerful tool that you can use with JSPs.
What's different with JSP 2.0 is that the JSP container is now responsible for the
EL, and you can use EL code embedded inside of template text. For example,
imagine that you had an object attribute named user stored in a session. The
user object has a getName() method that returns the user's name. With a
JSP 2.0 container, you can display the user's name in a JSP in the following
manner:
<html>
<head><title>The User's Name</title></head>
<body>
<%-- you could also use the syntax ${sessionScope.user.name} --%>
<strong>User name:</strong> ${user.name}
</body>
</html>
Notice that the code did not use the former JSTL-related syntax of:
<c:out value="${user.name}"/>
|
Related Reading
Java Servlet & JSP Cookbook |
One caveat is that if your web application is still using the Servlet 2.3 format of web.xml, then the JSP container will automatically deactivate the evaluation of EL expressions in template text, and usages such as in the example will not work as expected. Therefore, in most cases, you should upgrade your application to the Servlet 2.4 format of web.xml.
JSP 2.0 has added the tag file feature, which is designed to make it much easier for developers that are not Java specialists to create a custom tag. Tag files can be written in either JSP syntax or XML. Therefore, you can skip the stage of writing the Java source file and compiling it.
The required extensions for a tag file are .tag if you write the file in JSP syntax, and .tagx if the file is only composed of XML elements. The JSP 2.0 specification requires you to place the tag file in the WEB-INF/tags directory, or a subdirectory thereof. If you want to package the tag file in a Java Archive .jar file as part of a custom tag library, then you can store it in META-INF/tags (or a subdirectory of META-INF/tags), and then describe the tag file in a Tag Library Descriptor (TLD), a type of configuration file. You do not have to describe the tag files that are placed beneath WEB-INF/tags in a TLD, but you can, if you want to consolidate a library of traditional custom tags and tag files in one TLD.
The following tag file generates the HTML text for inserting a logo image inside of the page.
<%@ tag body-content="scriptless" description="Writes
the HTML code for inserting a logo." %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ attribute name="heading" required="true" rtexprvalue=
"true" description="The heading level for the logo."%>
<%@ attribute name="image" required="true" rtexprvalue=
"true" description="The image name for the logo."%>
<%@ attribute name="width" required="true" rtexprvalue=
"true" description="The image width for the logo."%>
<%@ attribute name="height" required="true" rtexprvalue=
"true" description="The image height for the logo."%>
<img src="${imgDir}${image}" width=
"${width}" height="${height}" align="left">
<H${heading}>
<jsp:doBody/></H${heading}>
In the example above, imgDir is a servlet context attribute representing the image
directory, so the Expression Language may access the attribute value with the
syntax ${imgDir}.
Inside of the JSPs that use the custom tag, you specify the location of the tag file
for the JSP container by using the taglib directive's tagDir attribute. In
other words, the tagDir attribute provides the path to the web application
directory where you stored the tag file. Here's an example:
<%@ taglib prefix="cbck" tagdir="/WEB-INF/tags" %>
As long as you place the tag file, which has a .tag extension (or .tagx extension if the tag file is in XML syntax), in /WEB-INF/tags, then JSPs will be able to use the tag associated with the example tag file. Here is an example of how the tag would be used inside of a JSP:
<cbck:logo heading="1" image="stamp.gif" width="42" height="54">Thanks for
visiting</cbck:logo>
The text returned to the user agent that requests the JSP looks like this:
<img src="/home/images/stamp.gif" width="42" height="54"
align="left"><H1> Thanks for visiting</H1>
You can embed your own Java functions within Expression Language (EL) code with JSP 2.0. This allows developers to expand the capabilities of the EL's built-in functions and objects. Java Servlet & JSP Cookbook uses the example of an EL function inside of a JSP that calls an Oracle stored procedure (Recipe 21.8). The JSP 2.0 specification calls them "qualified" functions because the function call is qualified by a particular namespace, the namespace represented by your custom tag library.
First, you write the Java source file and include a public static method. Here's an
example:
//...import statements, class declaration, and constructor
public static void addRaceEvent(String name,String location,String date) {
Connection conn = null;
try{
conn = pool.getConnection();
if (conn == null )
throw new SQLException(
"Invalid Connection in addRaceEvent method");
CallableStatement cs = null;
//Create an instance of the CallableStatement
cs = conn.prepareCall( "{call addEvent (?,?,?)}" );
cs.setString(1,name);
cs.setString(2,location);
cs.setString(3,date);
//Call the inherited PreparedStatement.executeUpdate() method
cs.executeUpdate();
// return the connection to the pool
conn.close();
} catch (SQLException sqle) { }
}//addRaceEvent
In JSP 2.0, you then describe the function in a Tag Library Descriptor:
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=
"http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/
web-jsptaglibrary_2_0.xsd"
version="2.0"
>
<!-- other taglib nested elements... -->
<function>
<name>addRaceEvent</name>
<function-class>
com.jspservletcookbook.StoredProcUtil
</function-class>
<function-signature>
void addRaceEvent(java.lang.String,
java.lang.String,java.lang.String)
</function-signature>
</function>
<tag>
<!-- define a custom tag here if you have to -->
</tag>
</taglib>
Use the taglib directive in the JSP to declare the tag library that includes the
defined function, then call the function.
<%@ taglib uri="jspservletcookbook.com.tags" prefix="cbck" %>
<html>
<head><title>Calling a Stored procedure</title></head>
<body>
<h2>This JSP calls a stored procedure with a JSP 2.0 function</h2>
${cbck:addRaceEvent("Falmouth Triathlon","Falmouth MA","26-Jul-2003")}
</body>
</html>
This is a pretty good way to use JSPs as the presentation component for an application that is based on stored procedures. In general, creating your own functions is a great way to extend the features of the EL for the benefit of your project.
Bruce W. Perry is an independent software developer and writer, and the author of Java Servlet & JSP Cookbook and just-published Ajax Hacks.
O'Reilly & Associates published Java Servlet & JSP Cookbook in January 2004.
Chapter 17, "Embedding Multimedia in JSPs," is available free online.
You can also look at the Table of Contents, the Index, and the full description of the book.
For more information, or to order the book, click here.
Return to ONJava.com.
Showing messages 1 through 6 of 6.
img src="${imgDir}${image}" width=
"${width}" height="${height}" align="left"<c:out../> will escape XML characters by default (this can be turned off with escapeXml='false'), whereas ${foo} will leave the contents of foo untouched.<c:out/> with ${...}. This could have serious side-effects if the content of the variables presented is not considered carefully with respect to escaping.<c:set var="myValue" value="a tag </tag>" />
<c:out value="${myValue}" /></ br>
${myValue}a tag </tag></ br>
a tag </tag>
I didn't see this used anywhere in the tag file. Is it necessary?
Also I believe this:
img src="${imgDir}$"should really be this
img src="${imgDir}$/${image}"-Jerome