Integration of Hibernate and MyFaces

Description

A common problem many people have is the usage of ORM mappers in conjunction with MyFaces, or JSF generally. The Howto in this page will describe how to solve the problem in combination with the very popular ORM mapper Hibernate

Basic Problems

MyFaces or JSF is a loosely coupled framework concentrating on the UI Layer and the bindings to the middle tier. As such, it does not have clear ORM and middle tier infrastructure APIs, except for the ones, which are responsible for the middle tier bindings.

The infrastructure for the middle tier and the database layer has to be provided, either by the implementor, or by some other existing frameworks, like EJB, or Spring.

However, some existing components, like the datascroller, have APIs which define interfaces to the middle tier which have to deliver the data. One of the biggest problems of those bindings is that the implementor him/herself has to provide the necessary hooks for those interfaces.

Basic interfaces

Aditionally to work directly with provided data objects through JSF value bindings

 <x:component id="id" value="#{datasetObject.property}"/>  there are two mechanisms for currently existing controls which can bind groups of objects to the component.

These affected components are

These need extended mechanisms for the binding of data objects. Further details on this topic are provided later.

Basic Mechanisms

The first and foremost problem of having to integrate Hibernate with JSF is that a controlled session and transaction handling is needed. There are various ways to accomplish that, it either can be done manually or automatically via some kind of automatic program control.

The manual way can be achieved within the backend beans at the various stages of the control flow and basically uses all the mechanisms described in the Hibernate Documentation.

This strategy is cumbersome and problematic because it has to many points where the implementor can cause a significant error in the session open/closing flow. (for instance a forgotten transaction finalizer can cause a severe interruption and a tangling session which might never be closed)

The same goes for the transaction handling. The transaction handling can be done manually as described in the Hibernate documentation, but this approach is error prone and often causes huge amounts of transactional code duplication. Hence, an automated approach to cover this are is recommended, due to the additional time saving and code reduction which can be gained.

Automated Mechanisms

There are various ways to automate the session opening and closing and also the transaction handling for standard cases.

The most often used case probably is the one session per request appraoch.

The idea is relatively simple. the session generation/recycling cycle can be started at the beginning of a request, and as soon as one request terminates one way or the other (in a normal or error condition) the session has to be closed/pushed back into the recycle me state. There are various ways to achieve this behavior. All which is needed, is a clearly defined, beginning of the cycle ending of the cycle conjunction point. The main problem is, that the JSF API at the first sight does not define such things. But in fact it does, but on a level where you do not expect it. But we will try to cover it from another angle first.

One Session per Request via Servlet Filters

The most basic way is, to start the whole integration on a servlet level. Servlets know the servlet filter mechanisms. Which is a filter chain pattern exactly triggered at the request levels we already need (beginning of request, end of request, one way or the other. Therefore the whole session open/close mechanism can be and often is done via the usage of servlet filters.

So basically, this is a common way, to do it, there must be an implementation of such a thing already existing out there?

Yes indeed there is, and can be found in the Spring Framework

it is called the OpenSessionInViewFilter

The usage is relatively simple, although it enforces introduction of the Spring Framework into your mix of base frameworks. All which is needed is two entries in the web.xml and the pattern is enabled.

<filter>
  <filter-name>sessionFilter</filter-name>
  <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
        
<filter-mapping>
  <filter-name>sessionFilter</filter-name>
  <url-pattern>*.jsf</url-pattern>
</filter-mapping>

If you already have a working spring/hibernate configuration all you need to do is to hadd these lines to your project and every request which goes into a jsf file automatically is under full session scope, without having to add a single line of code.

Problems

There are a handful of problems related to this apprach however, the biggest one is described by Spring itself:

WARNING: Applying this filter to existing logic can cause issues that have not appeared before, through the use of a single Hibernate Session for the processing of an entire request. In particular, the reassociation of persistent objects with a Hibernate Session has to occur at the very beginning of request processing, to avoid clashes will already loaded instances of the same objects.

Alternatively, turn this filter into deferred close mode, by specifying "singleSession"="false": It will not use a single session per request then, but rather let each data access operation or transaction use its own session (like without Open Session in View). Each of those sessions will be registered for deferred close, though, actually processed at request completion.

A single session per request allows for most efficient first-level caching, but can cause side effects, for example on saveOrUpdate or if continuing after a rolled-back transaction. The deferred close strategy is as safe as no Open Session in View in that respect, while still allowing for lazy loading in views (but not providing a first-level cache for the entire request).

Looks up the SessionFactory in Spring's root web application context. Supports a "sessionFactoryBeanName" filter init-param in web.xml; the default bean name is "sessionFactory". Looks up the SessionFactory on each request, to avoid initialization order issues (when using ContextLoaderServlet, the root application context will get initialized after this filter).

NOTE: This filter will by default not flush the Hibernate Session, as it assumes to be used in combination with business layer transactions that care for the flushing, or HibernateAccessors with flushMode FLUSH_EAGER. If you want this filter to flush after completed request processing, override closeSession and invoke flush on the Session before closing it. Note that closeSession will just be invoked in single session mode! 

That means, if this filter is used, either all the code has to be under transactional scope or the filter patterns have to be changed into something different, or disable the filter indirectly by setting singleSession to false. Also have in mind that the objects are stored in a single session, possibly over various codeparts.

An alterated filter could look like following code:

public class OpenSessionInViewFilter extends org.springframework.orm.hibernate3.support.OpenSessionInViewFilter {
        
        /**
         * we do a different flushmode than in the codebase
         * here
         */
        protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
                Session session = SessionFactoryUtils.getSession(sessionFactory, true);
                session.setFlushMode(FlushMode.COMMIT);
                return session;
        }

        /**
         * we do an explicit flush here just in case
         * we do not have an automated flush
         */
        protected void closeSession(Session session, SessionFactory factory) {
                session.flush();
                super.closeSession(session, factory);
        }
}

The filter above sets the flush mode to commit and performs an explicit flush upon the close session stage. It should work with an explicit transaction and transaction less operations, which rely on outside flushes.

The other problem is, that often access to the hibernate facilites is needed, this problem can be solved by combining spring and JSF. To do this, there are currently two APIs one is provided by Spring and very basic, the alternate one is a separate sideproject currently hosted on sourceforge.

At the time of writing this, the JSF-Spring project should be seriously considered over the spring internal JSF bindings, it is much better and much more extensive.

Once both APIs are integrated MyFaces beans can be used from Spring and vice versa. Automated access to the Spring ApplicationContext can be gained, by defining beans which implement the ApplicationContextAware interface (probably they have to be defined as spring beans) and /or you can use the DAO base classes of spring to inherit the dao functionality in the jsf apps DAOs.

Automated transaction handling

Once this state is reached, two options to do transaction handling are available, a manual one or automated one.

The manual approach has different options

The first two approaches are described in the Hibernate manual and in the spring manual in a platform agnostic way. The third approach to work properly with JSF needs some pattern adjustment.

Patterns neededed for the approach:

There has to be a precise split between UI logic and application logic to gain full control over the transactional flow. IE in the backing beans which are directly docket to the forms, no real application logic should be performed. The main problem is, that Spring uses some kind of proxy mechanism to enable the AOP and the transactionaly handling, which intervenes with precompiled logic in the JSF framework to some extent.

Hence the flow of your application should go the following way:

form(JSP) -> backing bean with strict ui logic and jsf related code -> business object under transactional scope with the business logic -> DAO objects with the DAO code for sending and fetching the data.

It does not matter if the BOs and the DAOs are combined or a split approach is targetted, the main key is to keep the transactional scope out of the JSF UI code, otherwise there might be problems wrapping the needed aspect proxies around the code.

The transactional boundary might look like this (picture will follow):

backing bean with strict ui logic and jsf related code |'''transaction boundary'''| business object under transactional scope with the business logic

Depending on the JDK different mechanisms can be used to put your access code under Hibernate/Spring transactional control.

The JDK 5.0 approach can use annotations to put an accessor method of your business object under automated transactional control, to the time of this writing springs transactional annotation support was in beta stage, see this blog for more information. This approach, however only works with Spring 1.2+ and Hibernate 3 in conjunction with JDK 5.0.

For an older approach the Spring based AOP transactional mechanisms can be used:

<bean id="businessObject" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager" ref="txManager" />
        <property name="target" ref="businessObjectTarget" />
        <property name="transactionAttributes">
                <props>
                        <prop key="transactional_*">PROPAGATION_REQUIRED</prop>
                </props>
        </property>
</bean>

puts an automated transactional mechanism over a businessObject object, all methods beginning with transactional_ are automatically put under transactional scope. Spring gives from its core api even a much finer granularization, but this approach can be recommended as replacement for the missing annotation support if there is no ultimate emphasise on calling speed.

Special Controls Data prodviding classes

Some controls need some kind of data providers which feed more than a single dataset. Currently there are two group of controls doing this.

selectXXXX

and

dataTable

Both of them have different mechanisms and binding interfaces for getting the data. The simpler one are the controls of the select Group (selectItem menuList etc...)

SelectItem, MenuList etc...

While in normal controls the fetched datasets directly can be fed, those controls basically rely on lists with key/value pairs. JSF has a basic mechanism to feed that data into the controls, it is a holder class, called SelectItem, which can be used as a data "interface" between the ui element and the control.

The basic programmatic flow of such a datafeed from hibernate can be like following:

uicontrol->backend bean which maps the data into Collection<SelectItem>->DAO which fetches the list from the db and returns it

or even simpler

uicontol->backend bean dao which delivers the selectItems directly from the db

a classical approach of such an object could look like following:

/**
* a simple class which fetches some items from the 
* db and delivers a list of items
*/
public class SelectItemFromDBDAO extends HibernateDaoSupport implements ISelectItemFromDBDAO   {
        
        public List getItems() {
                List elements = getHibernateTemplate().find("from MyDataObjectTable as obj where 1=1 order by obj.id");
                Iterator i = elements.iterator();
                List retVal = new LinkedList();

                while(i.hasNext()) {
                        MyDataObjectTable element = (MyDataObjectTable ) i.next();
                        SelectItem item = new SelectItem(element.getId(),element.getValue());
                        retVal.add(item);
                }
                return retVal;
        }
}

on the frontend it can look like that:

<h:selectOneMenu id="typus" value="#{holder.value}">
        <f:selectItems id="theTypis" value="#{myDataObjectTableBean.items}" />
</h:selectOneMenu>

Note: if you use the HibernateDAO support, make sure that the Backend bean is under Request scope, otherwise you might run into errors with the automated session handling, because the sessions referenced do not resemble the actual ones anymore.

The select items approach with a pure DAO approach

The above example although tight and convenient introduces a heavy depence between the dao layer and the user interface layer, if you can rely on non changing user interface techniques, it is a valid approach. However the classical DAO approach tries to capsule the data access and also does not have any dependency into the user interface or business logic of the application.

Hence a different approach might be more appropriate if it can be expected that the DAO has to deal with different frontend technologies.

The SelectItem transformation has to be done from a controller backend bean.

Data Table

Data Table the easy way

The easy way a data table only needs a collection of elements, hence a dao which delivers a list of elements can be used. [Example will follow] However this approach is heavy on the memory because every dataset on the list has to be loaded into memory. A simpler approach would be to feed lists into the data model, but this approach disables paging. Therefore under normal circumstances, the data model approach has to be followed.

Data model, Data Table the hard way

It is more complicated to implement a data model for a database table. This technique also introduces unwanted dependancies between the UI and the DAO's. JSF defines a DataModel interface and convenience implementations such as ListDataModel for use with the DataTable UI component. DataTable knows the DataModel interface and uses it to access the bound database data.

The main problem of implementing such data model is the unsophisticatedness of the interface. Basically, it is an interface for - retrieving total number of records or, - retrieving data for a record at the current or given position. No services are offered for iterating through records.

So implementing such a class for Hibernate is not easy, unless somebody one day will provide a generic class which then can be used simply by pushing down Hibernate query objects and then let things do their way.

The jsf-comp project currently provides a mechanism for generic mappers which uses prefetch caching instead of automated session handling and direct feeds to accomplish such a thing. Unfortunately it is more complicated than an automated session handler or Hibernate query object approach would be, but it gives a good starting point on how to implement a specialized data model.

Several datamodels can be found in the MyFaces sourcecode also.

Examples for working springConfigs and web.xml s for the integration of MyFaces 1.0.9 and Spring as well as Hibernate 3 with the Spring-JSF Integration library can be found here

Query by Example

If you want to use the query by example feature of Hibernate you will run probably in the pitfall of empty inputText-controls do not return null than empty String for String-properties. For this you can create an NullableStringConverter. An example can be found at http://jroller.com/page/stritti?entry=jsf_stringconverter_for_null_values.

Hibernate_And_MyFaces (last edited 2009-09-20 23:01:10 by localhost)