July 30, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Spring into JavaServer Faces

  • April 27, 2006
  • By Michael Klaene
  • Send Email »
  • More Articles »

In the context of Java development, the Spring framework and JavaServer Faces are two names that frequently come up in conversation. Spring is a powerful application framework that rivals Enterprise JavaBeans in the breadth of its features. JavaServer Faces, commonly known as JSF, is a component-oriented, event-driven framework for building Web applications. Given the popularity of both Spring and JSF, it is natural that there will be some interest in integrating Spring and JSF. As it turns out, this is quite possible. In fact, they compliment each other very nicely. This article demonstrates how to utilize JSF and Spring to build an application.

A detailed discussion of either Spring or JSF is beyond the scope of this article. There are numerous resources on the Web where you can learn about these two topics. Having said that, I will attempt to provide a very brief overview of both of them.

Spring is a framework that consists of several modules. Its core module provides Inversion of Control services. Inversion of Control is often referred to as IOC; I will use this term for the remainder of the article. With IOC, the container injects an object's dependencies at runtime. This is in contrast to the common approach of writing code to look up dependent objects using the Java Naming and Directory Interface (JNDI) interface or an object implementing the Service Locator design pattern. When you allow an IOC container to inject dependencies for you, you simplify your application code. Spring specifies object dependencies in a configuration file; this is more flexible than putting this information in source code. Spring's other modules provide an array of other services. These services include transaction support and support classes for working with O-R mapping tools. Spring also provides its own Web framework as an alternative to Struts or even JSF.

JavaServer Faces represents a new approach to Web development. Previously, developers using Servlet-based technologies such as JavaServer Pages manipulated an object model that reflected the stateless nature of the HTTP protocol. This model includes objects such as Request and Response. Developers had to write code to explicitly preserve a Web form's values between requests (although frameworks helped in this regard). although these objects are still important to JSF developers, JSF user interface components are designed to automatically preserve their state between requests. Code to handle state management is greatly reduced. In addition to user interface components, JSF provides 'managed-beans' that can be used to hold data and respond to user events. JSF also provides numerous non-visual components that handle validation and data conversion tasks. Using a JSF development tool, building an interface is as simple as dragging components and dropping them onto a page where you can modify their behavior and appearance through a property palette. In short, JSF is designed to make the Web development experience similar to building applications with a technology such as Visual Basic.

JSF and Spring do share some of the same features, most noticeably in the area of IOC services. By declaring JSF managed-beans in the faces-config.xml configuration file, you allow the FacesServlet to instantiate that bean at startup. Your JSF pages have access to these beans and all of their properties. This is a powerful feature and is similar to how Spring's applicationContext works. JSF's managed-beans facility may be all that you need for developing small applications but Spring's applicationContext is a more powerful option. In addition, by using Spring IOC developers have at their disposal all of Spring's other capabilities.

In the remainder of this article, you will step through a simple application that utilizes both Spring and JSF. The sample application is a hotel reservation system. Here is the full schema for this application. You will focus on a single table, room, for the purposes of this article. The room table contains information about different hotel rooms.

You will build this application from the bottom up, so your first task is to create a domain object to represent your room table. Room.java contains the source code for the Room class. The attributes of this class match the columns in the table. You will add this class to the package called 'domain'. In this application, you will use the Hibernate object-relational mapping framework. Hibernate can significantly reduce the amount of data access code necessary in Java applications. The mapping between tables and Java objects is specified in an XML configuration file. Room.hbm.xml maps the room table to domain.Room:

<hibernate-mapping>
   <class name="hotelReservations.domain.Room" table="room">
   <id name="roomId" column="room_id" unsaved-value="0">
      <generator class="increment" />
   </id>
   <property name="floor" column="floor" not-null="true"/>
   <property name="roomNumber" column="room_number" not-null="true"/>
   <property name="reserveStatus" column="reserve_status"
             not-null="true"/>
   <property name="roomType" column="room_type" not-null="true"/>
   <property name="canSmoke" column="can_smoke" not-null="true"/>
   lt;/class>
</hibernate-mapping>

This file should be in the same 'domain' directory as the Room class. Next, a class is needed that handles the data access requirements for working with room data. This designated class follows the Data Access Object, or DAO, design pattern. To add greater flexibility to switch data access implementations later on, your DAO should implement an interface. By doing so, the rest of the application can remain unaware of the data access specifics. The RoomDao defines the public methods of any DAO class the application implements, whether you use Hibernate or not. RoomDaoHibernate implements RoomDao and will use the Hibernate programmatic interface. Here are the methods in this Hibernate-specific class:

public List getRooms() {
   return getHibernateTemplate().find("from Room");
}

public Room getRoom(Long id) {
   return (Room) getHibernateTemplate().get(Room.class, id);
}

public void saveRoom(Room room) {
   getHibernateTemplate().saveOrUpdate(room);
}

public void removeRoom(Long id) {
   Object room = getHibernateTemplate().load(Room.class, id);
   getHibernateTemplate().delete(room); 
}

Now that you have established your domain layer and implemented a data access layer, it would be acceptable to begin developing the view layer of the application with JSF. However, a common practice is to add one final layer to the application. This final layer sits between the view and the data access objects and defines the interface through which all clients access the application. This layer contains the core business logic for the application and invokes DAO methods. JSF managed beans will communicate only with this layer, not the DAOs. The HotelManager class does nothing more than invoke the DAO methods. In a more complex application, additional business logic would be found here.

HotelManager contains an instance of the application's DAO object:

private RoomDao dao;

   public void setRoomDAO(RoomDao dao) {
      this.dao = dao;
   }

You did not write this code. Rather, you let Spring inject this dependency at runtime. This dependency is specified in Spring's applicationContext.xml file.

<!--Dao (Data Access Object) for application. -->
<bean id="roomDAO" class="hotelReservations.dao.RoomDaoHibernate">
   <property name="sessionFactory">
      <ref local="sessionFactory"/>
   </property>
</bean>

<!--Manager for Hotel rooms application.-->
<bean id="hotelManager" class="hotelReservations.HotelManager">
   <property name="roomDAO">
      <ref local="roomDAO"/>
   </property>
</bean>

There can be many different settings in a Spring configuration file, such as database connection properties. The Spring framework also allows developers to specify transactions at the business layer of an application. This is accomplished by specifying a transaction proxy bean that wraps the business layer object, in this case HotelManager.

<!--Wraps manager in order to support transactions.-->
<bean id="manager"
      class="org.springframework.transaction.interceptor.
             TransactionProxyFactoryBean">
   <property name="transactionManager">
      <ref local="transactionManager"/>
   </property>
   <property name="target">
      <ref local="hotelManager"/>
   </property>
   <property name="transactionAttributes">
      <props>
         <prop key="save*">PROPAGATION_REQUIRED</prop>
         <prop key="remove*">PROPAGATION_REQUIRED</prop>
         <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
      </props>
   </property>
</bean>

This has admittedly been a brief introduction on how Spring is used in this application. I would suggest visiting the Spring Web site for a more thorough explanation of Spring's features. As mentioned earlier, JSF provides managed-beans to Web pages once they are specified in the faces-config.xml file. FacesServlet loads the beans listed in this file at application startup. It is possible, though not recommended, to put business logic inside JSF managed-beans. Typically, you will want to keep managed-bean code focused on view-related tasks. I created a managed-bean called ShowRooms that can contain methods and properties that your JSF Web page, ShowRooms.jsp can reference.





Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel