Hibernate Transaction Handling in DWR

I am currently building a web-application using OSGI (HTTP Service) and Hibernate. I also use DWR for all the AJAX stuff in the application. DWR uses a special DWRServlet which handles the interaction of the browser with the server side. The other part of my application uses a global dispatcher servlet for all other servlet requests.  This global dispatcher servlet also does the Hibernate  transaction handling using a OpenSessionInView – Pattern. This means the dispatcher servlet begins, commits and rollback the transaction in case of an exception. This works well.

My problem until today was, that this kind of transaction handling was not working in my DWRServlet, because this is a servlet not under my control. My first approach was to create a new servlet which extens DWRServlet so that I could modify the behaviour , but that didn’t work completely, because DWR does not pass Exceptions to my servlet. DWR handles all exceptions, marshals them so that the Exception can be passed back to the browser to be displayed in your calling Javascript code.  That means I cannot catch the exception in my custom servlet  because it is already caught and handled. Damn!

So I debugged and digged through a complete DWR call and found the @GlobalFilter annotation. That seems to be exactly what I need. This annotation can be applied to a class and this class also needs to implement the AjaxFilter interface. DWR then applies all filters to each method call made through the DWRServlet. This class needs to be registered the same way as you register your other DWR annotated classes (e.g. the classes annotated with the @RemoteProxy or @RemoteMethod annotation)

So I came up with the following class which borrowed some code of the existing org.directwebremoting.hibernate.H3SessionAjaxFilter which does almost exactly what I need, except the rollback() of my transaction in case of an error.

@GlobalFilter
public class DWRFilter implements AjaxFilter {
 
	private static final Logger LOGGER = LoggerFactory.getLogger(DWRFilter.class.getName());
 
	public Object doFilter(Object obj, Method method, Object[] params,
			AjaxFilterChain chain) throws Exception {
 
        SessionFactory sessionFactory = Activator.getSessionFactory();
 
        Transaction transaction = null;
        if (sessionFactory != null)
        {
            Session session = sessionFactory.getCurrentSession();
            transaction = session.beginTransaction();
        }
        else
        {
            LOGGER.error("SessionFactory not initialized for this web application.");
        }
 
        Object reply = null;
		try {
			reply = chain.doFilter(obj, method, params);
 
			if (transaction != null)
			{
			    transaction.commit();
			}
		} catch (Exception e) {
			LOGGER.error("Error while committing transaction in DWRFilter. Transaction will be rolled back now...",e);
                        if(transaction != null){
			    transaction.rollback();
                        }
			throw new InvocationTargetException(e);

		}

        return reply;
	}

}

This basically does exactly what I want and is basically something like the Open Session In View pattern for DWR and Hibernate. For each DWR call it is the following flow:

  • begin transaction
  • do work
  • commit transaction
  • or rollback transaction in case of an exception

This way I have a central place for my DWR-Transaction handling.

This is my first solution to this problem and maybe it doesn’t catch every scenario, e.g. especially when you are using special features of DWR like batch calls etc. I haven’t used those features and for my current features using simple calls it works very well.

Dieser Beitrag wurde unter Software-Development abgelegt und mit , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

1.064 Antworten auf Hibernate Transaction Handling in DWR

  1. Pingback: 2,000+ Free iPhone Wallpapers!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

CAPTCHA-Bild

*