vrijdag 20 februari 2009

fast & simple jsf mockups with hibernate

I'm working on a prototype for several administration pages and needed a quick mockup for testing. So I quickly set up a HSQLDB in memory and used hibernate annotations to map my model to it. Here are some code snippets to check how to configure hibernate to work in the jsf context:

you'll need a filter to instantiate hibernate:
package fi.tavutaito.filter;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
*
* SessionFilter initializes EntityManagerFactory and serves each request
* with an EntityManager.
*
* @author markus
*
*/
public class EntityManagerFilter implements Filter {
/** Logger */
protected Logger log = Logger.getLogger(EntityManagerFilter.class.getName());

private EntityManagerFactory entityManagerFactory;

/* (non-Javadoc)
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
public void init(FilterConfig config) throws ServletException {
Map configOverrides = new HashMap();
// this enables to see hibernate generated SQL in the server log
configOverrides.put("hibernate.show_sql","true");
entityManagerFactory = Persistence.createEntityManagerFactory("database", configOverrides);
}

/* (non-Javadoc)
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws ServletException, IOException {

EntityManager em = entityManagerFactory.createEntityManager();
request.setAttribute("entitymanager", em);
EntityTransaction tx = null;
try {
// begin the transaction
tx = em.getTransaction();
tx.begin();

// continue processing to JSF
chain.doFilter(request, response);

// after returning from JSF commit the transaction
tx.commit();

} catch (RuntimeException e) {
// if something fails, log the error and rollback
log.log(Level.SEVERE, "",e);
tx.rollback();
} finally {
// always close the entitymanager
em.close();
}
}

/* (non-Javadoc)
* @see javax.servlet.Filter#destroy()
*/
public void destroy() {
entityManagerFactory = null;
}

} 

and this filter needs to be configured in the web.xml like this:
<!-- Entity Manager Filter declaration -->
<filter>
<filter-name>EntityManagerFilter</filter-name>
<filter-class>fi.tavutaito.filter.EntityManagerFilter</filter-class>
</filter>

<!-- Filter is setup on all requests than end with jsf suffix -->
<filter-mapping>
<filter-name>EntityManagerFilter</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>

Now don't forget to configure you're persistence.xml. I'm used to putting it into the META-INF folder but it wasn't found so I got exceptions like:
Caused by: javax.persistence.PersistenceException: No Persistence provider for EntityManager named database
Not sure yet why but I think it has something to do with the way I run it using jetyy. Will get back to this post when I have a solution.

If all goes well you can access the EntityManager through the FacesContext like this:
(EntityManager)
((HttpServletRequest)FacesContext
.getCurrentInstance()
.getExternalContext()
.getRequest()
)
.getAttribute("entitymanager");
Also check the resources of this post for some utilities.

I'm managing dependencies using maven and running all this code using the maven jetty plugin ;-).

external links:
* a tutorial on jsf + hibernate + facelets
* an example of HSQLDB hibernate config properties

Geen opmerkingen:

Een reactie plaatsen