Wednesday, September 07, 2011

JSF + JPA without EJB or Spring

I've had success using JSF 2.0 with JPA on Glassfish 3.0.1, without using Spring or EJB for managing middle-tier services or DAOs. (I actually do like Spring - the goal in this case was to minimize dependencies, moving parts and learning curve, rather than to avoid any particular technology.)

A similar approach was detailed here:
http://www.swview.org/blog/best-way-use-jpa-web-tier

 Using only the JSF @ManagedBean and @ManagedProperty annotations, along with the JPA @PersistenceContext, you can refactor business services or DAOs into other JSF managed beans that are injected into the one exposed directly to the UI. What this looks like in practice:

 orders.xhtml:
 

OrderBean.java:
@ManagedBean
public class OrderBean {
  @ManagedProperty(value="#{orderDao}")
  private OrderDao orderDao;
  private List orders;
   
  @PostConstruct
  public void init() { 
    this.orders = orderDao.getOrders();
  } 
  public List getOrders() { 
    return orders;
  }
}

OrderDao.java:
@ManagedBean
@ApplicationScoped
public class OrderDao {
   @PersistenceContext(...)
   private EntityManager em;
   
   public List<Order> getOrders() { 
     return em.findAll(Order.class);
   }
}
In this example, the DAO (OrderDao) is just another JSF managed bean, but not actually referenced directly from a page, only from another managed bean. This approach lets you isolate the logic tied to EntityManagers from the rest of your "normal" JSF managed beans, and makes it (marginally) easier to unit-test your managed beans because you can mock the DAO at a higher level instead of mocking the entity manager.

 This does NOT buy you declarative transactions or any of the other good stuff you get with Spring or EJB. (You can inject a UserTransaction with @Resource, and call it explicitly, though.) So it works best for simple apps with mostly read operations and basic single-object CRUD transactions.

 Also, with Java EE 6 CDI, all this may become moot because @Named and @Inject annotations effectively blur the line between all the different managed bean flavors (EJB, JSF, Spring/POJO), although I haven't found a good way to replace JSF @ViewScoped without buying into Seam.
Post a Comment