A couple of suggestions when using this pattern with a Struts application.
1) Only filter on the Struts ActionServlet - This ensures that you
don't accidentally close the session.
I found that if my filter-mapping picked up the *.jsp files,
<jsp:include>'s would get a separate path through the Filter and could
close the session before you wanted it to. Filtering only on the
Struts
ActionServlet ensures that every request is filtered exactly once.
(Of course this assumes that the entire app is going through Struts)
<code>
<filter>
<filter-name>HibernateFilter</filter-name>
<filter-class>example.hibernate.HibernateFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HibernateFilter</filter-name>
<servlet-name>action</servlet-name>
</filter-mapping>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
...
</servlet>
</code>
2) Don't commit the Transaction in the Filter if you're using
Optimistic Locking.
The reason I suggest this is because any Optimistic Locking
exceptions you receive
won't be thrown until the commit takes place. And in most
instances, you've already
returned an ActionForward object that will take you to another page.
If you're on an edit page and hit the save button, you'd like the
Concurrent Modification
message to appear on the edit page, not on the maintain or view
page that you'd forward to
if the update were successful. At the very least, I like my action
to be able to determine
which ActionForward to navigate to when this exception is thrown.
<code>
...
public void doFilter(ServletRequest request, ServletResponse
response, FilterChain chain)
throws IOException, ServletException {
try {
// We don't start the database transaction here, but when
first needed
chain.doFilter(request, response);
// Commit any pending database transaction.
// HibernateUtil.commitTransaction(); <-- Do this in a
data-management layer.
} finally {
// No matter what happens, close the Session.
HibernateUtil.closeSession();
}
}
...
</code> |