I believe I have a solution that currently works for me with respect to
having the filter close the Session prematurely in the session-per-view
impl as defined above. This will ensure that the Session will stay open
for the entire thread request which may contain multiple ServletRequests.
This came about because I was including <jsp:include .../> files in
other JSP's which resulted in additional filter requests consequently
closed the session before it should have been and produced undesirable
results.
The following is the filter code rewritten:
<code>
public class HibernateFilter implements Filter {
private static Log log = LogFactory.getLog(HibernateFilter.class);
public void init(FilterConfig filterConfig) throws ServletException {
log.info("Servlet filter init, now opening/closing a Session for
each re
quest.");
}
private static String INIT_REQ_ATTR_NAME = "__INIT_REQ__";
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
// There is actually no explicit "opening" of a Session, the
// first call to HibernateUtil.beginTransaction() in control
// logic (e.g. use case controller/event handler, or even a
// DAO factory) will get a fresh Session.
boolean initialRequest = false;
try {
HttpServletRequest httpRequest = (HttpServletRequest)request;
Object val = httpRequest.getAttribute( INIT_REQ_ATTR_NAME );
initialRequest = ( val == null );
httpRequest.setAttribute( INIT_REQ_ATTR_NAME,
INIT_REQ_ATTR_NAME );
chain.doFilter(request, response);
HibernateUtil.commitTransaction();
}
catch (RuntimeException ex) {
log.debug("Rolling back the database transaction.");
HibernateUtil.rollbackTransaction(); // Also closes the session
// Just rollback and let others handle the exception, e.g.
for display
throw ex;
}
finally {
// No matter what happens, close the Session.
if ( initialRequest ) {
HibernateUtil.closeSession();
}
}
}
public void destroy() {}
}
</code>
Each <jsp:include > forwards all request attributes. The initial
request flag is then set in all subsequent requests within the thread.
Therefore the initial filter call will then only close the session which
is the desired effect.
This allowed me to assign a filter for both "*.do" and "*.jsp" and not
have to worry about where the initial request started.
For those using struts, you can filter on the action servlet and also
jsp files at the same time and ensure that you will have only one Session.
Hope this helps (and makes sense)
- Doug |