Wednesday, August 6, 2008

Alternative Ways to Define JSP/Servlet Attribute Scopes

As we know, there are four types of scopes that a JSP/Servlet attribute can use:
Application: The attribute lasts the lifetime of an application instance.
Session: The attribute survives throughout the conversation session.
Request: The attribute will be discarded after the request is serviced.
Page: The attribute is only visible within a particular JSP page.

To keep data integrity, it's important to put attributes into the right scope. Most of the time developers will retrieve attributes from requests and put them into appropriate scopes thereafter. There are alternative ways.

1. Set application scope attributes in a ServletContextListener.
Sometimes "static" information should be loaded once and visible throughout the lifetime of an application. For example,

web.xml
<listener>
<listener-class>
com.denistek.SampleListener
</listener-class>
</listener>

Java
public class SampleListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent event) {
//... get your attributes
event.getServletContext().setAttribute("attributes", attributes);
}

@Override
public void contextDestroyed(ServletContextEvent event) {
}
}

2. Set application scope attributes in a Servlet with <load-on-startup> features.
This is very similar to the above approach. For example,

web.xml
<servlet>
<servlet-name>SampleServlet</servlet-name>
<servlet-class>com.denistek.servlet.SampleServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

Java
@Override
public void init() throws ServletException {
super.init();
//... get your attributes
getServletContext().setAttribute("attributes", attributes);
}


3. Use filters to define session attributes.
Sometimes there are multiple entry points where a session attribute can be updated. In this case we'd better use a filter to watch for this kind of update instead of scattering the logic across various JSP's/Servlets. For example,

web.xml
<filter>
<filter-name>SampleFilter</filter-name>
<filter-class>com.denistek.SampleFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SampleFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Java
public class SampleFilter implements Filter {

private SampleAttribute[] attributes = null;

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException{
HttpServletRequest rq = (HttpServletRequest) request;
//... populate attributes from request here
rq.getSession().setAttribute("sampleAttributes", attributes);
chain.doFilter(request, response);
}

@Override
public void init(FilterConfig config) {
//... populate attributes from context here
attributes = config.getServletContext().getAttribute("sampleAttributes");
}

@Override
public void destroy() {
}
}

1 comment: