![]() |
May 2001 Issue |
![]() |
Headlines:
Java Technical Insight of the
Month
Filters in the Servlet 2.3 API
Visit The Java News Brief
Archive for past issues of the JNB.
OCI Educational Services
Java Technical Insight of the
Month
Filters in the Servlet
2.3 API
by Dan Troesser, Senior
Software Engineer, Object Computing, Inc. (OCI)
Java Servlets have been around for several years now and have
proven themselves in delivering robust and portable web applications. Since their introduction, the Java web
development front hasn't slowed down. Along came JSPs
introducing an easier way to generate HTML. XML and XSLT
entered the picture making it easier to separate presentation
from data, among many other benefits. The Servlet API hasn't
stood still either. The Servlet 2.3 API, now a proposed final
draft, will be released soon and will bring with it another
powerful feature called filters.
Filters allow declarative pre-processing and post-processing
of requests and responses handled by web resources. Web
resources in this case are considered servlets, JSPs, static
content (HTML files), and even other filters in the web
application. Declarative means the Filter can be applied in the
deployment descriptor of the web application rather than
programmatically in a Servlet or JSP.
Filters are very similar to the concept of Servlet chaining
introduced and implemented by some Servlet containers years
ago. They could also be applied declaratively usually in a web
administration tool. However, declarative Servlet chaining was
not in the specification and thus was not implemented widely or
in any standard way by the containers. In the interest of
portability, their use somewhat disappeared.


import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
public class ImageRemovalFilter implements Filter {
// Could also use an initialization parameter for this.
private static final String STYLESHEET = "removeImages.xslt";
private FilterConfig filterConfig;
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
boolean doRemove = req.getParameter("removeImages") != null;
HttpServletResponse httpRes;
if (res instanceof HttpServletResponse) {
httpRes = (HttpServletResponse) res;
} else {
throw new ServletException("ImageRemovalFilter only accepts"
+ " HTTP requests");
}
OutputCaptureResponseWrapper resWrapper
= new OutputCaptureResponseWrapper(httpRes);
chain.doFilter(req, resWrapper);
resWrapper.flushBuffer();
String contentType = resWrapper.getContentType();
if (doRemove && contentType != null
&& contentType.indexOf("html") != -1) {
String initialXHTML = resWrapper.getOutputAsString();
String finalXHTML = removeImages(initialXHTML);
res.setContentLength(finalXHTML.length());
res.getWriter().print(finalXHTML);
} else {
// Let all other content types pass through.
res.getOutputStream().write(resWrapper.getOutputAsByteArray());
}
}
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
// Required by Filter interface. Just providing empty implementation.
public void destroy() { }
/**
* Performs an XSLT transformation using JAXP 1.1 to replace img elements
* in the input XHTML document with links (<a href="...).
*/
private String removeImages(String initialXHTML)
throws ServletException {
StringWriter finalXHTMLWriter = new StringWriter();
TransformerFactory factory = TransformerFactory.newInstance();
ServletContext context = filterConfig.getServletContext();
try {
InputStream xsltStream = context.getResourceAsStream(STYLESHEET);
StreamSource xsltSource = new StreamSource(xsltStream);
StringReader xmlSourceReader
= new StringReader(initialXHTML);
StreamSource xmlSource = new StreamSource(xmlSourceReader);
StreamResult xmlResult = new StreamResult(finalXHTMLWriter);
Transformer transformer = factory.newTransformer(xsltSource);
transformer.transform(xmlSource, xmlResult);
} catch (Exception ex) {
throw new ServletException("Error performing transformation to remove"
+ " images", ex);
}
return finalXHTMLWriter.toString();
}
}
When the Filter is loaded, the init() method is called. We use
the opportunity to save a reference to the FilterConfig object.
We will need this later to retrieve an instance of the
ServletContext object so we can gain access to the XSLT
stylesheet, which will perform the content transformation.
Click here to view or download
the stylesheet. The stylesheet filename is defined as a static
final String. It could also have been specified as a Filter
initialization parameter in the web application's deployment
descriptor (web.xml). If that were the case, the init() method
would have been a good place to retrieve the value using
getInitParameter() on the FilterConfig object. Once loaded and
the init() method is called, the Filter can handle requests.
Each request that should be filtered calls the doFilter()
method.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
<web-app>
<filter>
<filter-name>Image Removal Filter</filter-name>
<filter-class>ImageRemovalFilter</filter-class>
</filter>
<!-- Will cause the Filter to be applied to Viewer Servlet because it
has a matching url-pattern. One could have instead specified the
Servlet directly using a servlet-name element.-->
<filter-mapping>
<filter-name>Image Removal Filter</filter-name>
<url-pattern>/view/*</url-pattern>
</filter-mapping>
<!-- Will cause the Filter to be applied to all resources in the web
application, including static content and JSPs. This makes the
previous filter-mapping a bit redundant.-->
<filter-mapping>
<filter-name>Image Removal Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Viewer Servlet</servlet-name>
<servlet-class>ViewerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Viewer Servlet</servlet-name>
<url-pattern>/view/*</url-pattern>
</servlet-mapping>
</web-app>
The <filter> element declares a Filter in the web
application. It expects <filter-name> and
<filter-class> child elements that define the logical
name and class of the Filter, respectively, similar to the
definitions for servlets shown farther down in the file.
Initialization parameters can be defined in the same way for
filters as far servlets using <init-params> elements. We
also have <filter-mapping> elements that look similar to
<servlet-mapping> elements. They can contain
<url-pattern> elements that define when a Filter should
be called. Filters have critical differences, however, when it
comes to mapping. For one, the <filter-mapping> element
can take a <servlet-name> element instead of a
<url-pattern> element. This allows the Filter to be
mapped to an individual Servlet using its logical name defined
elsewhere in the deployment descriptor. Another critical
difference in mapping is realized when filters are chained
together. When chaining multiple filters, the order the
mappings appear in the deployment descriptor is significant.
First, the filters will be called in the order the
<filter-mapping> elements appear for <url-pattern>
elements that match. Then filters will be called in the order
the <filter-mapping> elements appear for matching
<servlet-name> elements.
OCI Educational Services
OCI has one of the most
comprehensive OO training curricula in the country.
Clients contract group training that is either taught at the
client site or at the OCI Education Center in St. Louis,
MO.
(click on course titles for online
descriptions)
| Java Curriculum |
CORBA/C++ Curriculum |
Enterprise
Web Development Curriculum |
Linux Courses |
|
![]() |
||||
![]() |
||||
Object Computing, Inc. is a Sun Authorized Java Center in St. Louis and a Member of the Object Management Group, OMG. OCI specializes in distributed computing using object-oriented and web-enabled technologies and provides Consulting, Education, and Product Development services to clients nation-wide. For more information contact us at 314-579-0066 (St. Louis), 480-752-0042 (Tempe) or email info@ociweb.com.
Click here for OCI CAREER
OPPORTUNITIES.
The Java News Brief is a monthly
newsletter. The purpose and intent of this publication is
to advance Java, provide technical value, and to announce
available OCI Java services. If you would prefer to not
receive this newsletter or would like to subscribe please click
here.
Copyright © 2001. Object Computing, Inc.
All rights reserved.
Java and all Java-based marks are trademarks or registered
trademarks of Sun Microsystems, Inc. in the United States and
other countries.
Object Computing, Inc. is independent of Sun Microsystems,
Inc.