Welcome

Lookup Tables with Hibernate and JSF

Every project has several tables which contains data mainly in a form of code,name pair. Those tables define state, type or other similar values as codes, which will be referenced from other tables in database. Further, their name values are used in GUI to make users know what those code values really mean in real business, as descriptive values in other words. Such tables are called “lookup tables”, “reference tables”, or “decode tables” in general.

Number of code,name pairs may increase or decrease, and their content may change from time to time.Hence, developed systems should take this point into account, and behave accordingly. Systems never should define such code and name values in source code directly, but fetch them from database.

We have many of such lookup tables in our current project, too. As a result, we need to develop a generic way to fetch those tables’ values, use them in model and GUI layers. Some domain classes have dependencies to those lookup values, and we need to create whole database schema from hibernate mapping files automatically. So, we decided to model those lookup values as first class objects. Otherwise, they would be primitive numeric types in domain model and we had to maintain relationships among domain tables and lookup tables manually.

/**
 * @hibernate.class
 */
    public class Personel {
        ...
        private Country country;
        ...
/**
         *@hibernate.many-to-one not-null=”true”
          */
        public Country getCountry() {
            return country;
        }
    }

    /**
     * @hibernate.class
     */
    public class Country {
        private Long id;
        private String name;
        
        /**
         * @hibernate.id
         */
        public Long getId() {
            return id;
        }



        /**
         * @hibernate.property
         */
        public String getName() {
            return name;
        }
    }

Country is here mapped as lookup table. We need a gereric lookup mechanism to provide available countries to be used in the system. Our LookupDAO class provides this;

    public class LookupDAO extends HibernateDaoSupport {
        public List getLookupObjectList(Class type) {
            return getHibernateTemplate().loadAll(type);
        }
        public Object getLookupObject(Class type, Long id) {
            return getHibernateTemplate().load(type,id);
        }
    }

We also declared a ILookupObject interface to utilize in JSF value binding and Converter, and each lookup class implements that interface, too.

public ILookupObject {
    public Object getThis();
    public Long getId();
    public String getName();
}

Business and presentation layers utilize above methods to retrieve country list or any specific country if they know its id. We employ Java Server Faces to implement presentation layer and need another generic way to bind those lookup values to JSF components, like comboxes, lists, checkboxes.Below, you can see how we do this with selectOneMenu JSF component.

<h:selectOneMenu id="cmbCountries" value="#{personelPageCode.personel.country }" styleClass="selectOneMenu" converter="lookupObjectConverter">
    <f:selectItems value="#{selectitems.personelPageCode.countries.name.this.toArray}" />
</h:selectOneMenu>

Combobox lists all available countries getting them evaluating value binding #{selectitems.personelPageCode.countries.name.this.toArray} EL. personelPageCode.getCountries() returns available country object using LookupDAO.getLookupObjectList().

A careful eye should immediately catch oddness in this EL. Combobox component requries a distinct identifier value, which usually becomes integer value. Instead, we gave whole lookup object instance as identifier value using “this” keyword. JSF uses “lookupObjectConverter”, we defined above, to produce that identifier value.
While rendering selectable items, each country lookup object -fetched calling getThis(), in which lookup objects return themselves- is given into Converter.getAsString(…)  method. This method returns getClass().getName() + “:” + getId() as identifier value.

    public String getAsString(FacesContext facesContext, UIComponent component, Object lookupObject) {
        try {

            String type = lookupObject.getClass().getName();

            return type + ":" + ((ILookupObject) lookupObject).getId();

        } catch (Exception e) {
            throw new ConverterException("Error during LookupObject conversion", e);
        }
    }

    public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {

            try {

            String[] parts = value.split(":");

            String type = parts[0];

            Long id = Long.valueOf(parts[1]);

            Class type = Class.forName(type);

            Object lookupObject = getLookupDAO().getLookupObject(type, id);

            return lookupObject;

            } catch (Exception e) {
                    throw new ConverterException("Error during LookupObject conversion", e);
            }

    }

When a country object is selected, JSF sets personel.country model property, getting lookup current object using Converter.getAsObject(…) method.

As a result we have come up with a really useful “JSF-Hibernate” java idiom to map and bind lookup tables in model and GUI.