ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Wiring Your Web Application with Open Source Java
Pages: 1, 2, 3

Wiring Together a Simple Example

Now that we understand the components from a high level, let's put this into practice. Again, for this example, we will combine the Struts, Spring, and Hibernate frameworks. Each one of these frameworks has too much detail to cover in one article. Instead of going into many details about each framework, this article will show how to wire them together with simple example code. The sample application will demonstrate how a request is serviced across each layer. A user of this sample application can save a new order to the database and view an existing order in the database. Further enhancements might allow the user to update or delete an existing order.



You can download the source code of the application.

First, we will create our domain objects since they will interoperate with each layer. These objects will allow us to define what should be persisted, what business logic should be provided, and what type of presentation interface should be designed. Next, we will configure the persistence layer and define object-to-relational mappings with Hibernate for our domain objects. Then we will define and configure our business objects. After we have these components we can discuss wiring these layers using Spring. Finally, we will provide a presentation layer that knows how to communicate with the business service layer and knows how to handle exceptions that arise from other layers.

Domain Object Layer

Since these objects will interoperate across all layers this might be a good place to start coding. This simple domain model will contain an object that represents an order and an object that represents a line item for an order. The order object will have a one-to-many relationship to a collection of line item objects. The example code has two simple objects in the domain layer:

  • com.meagle.bo.Order.java: contains the header-level information for an order.
  • com.meagle.bo.OrderLineItem.java: contains the detail-level information for an order.

Consider choosing package names for your objects that reflect how your application is layered. For example, the domain objects in the sample application can be located in the com.meagle.bo package. More specialized domain objects would be located in subpackages under the com.meagle.bo package. The business logic begins in the com.meagle.service package and DAO objects are located in the com.meagle.service.dao.hibernate package. The presentation classes for forms and actions reside in com.meagle.action and com.meagle.forms, respectively. Accurate package naming provides a clear separation for the functionality that your classes provide, allows for easier maintenance when troubleshooting, and provides consistency when adding new classes or packages to the application.

Persistence Layer Configuration

There are several steps involved in setting up the persistence layer with Hibernate. The first step is to configure our domain business objects to be persisted. Since Hibernate works with POJOs we will use our domain objects for persistence. Therefore the Order and OrderLineItem objects will need to provide getter and setter methods for all fields that they contain. The Order object would contain setter and getter methods such as ID, UserName, Total, and OrderLineItems in a standard JavaBean format. The OrderLineItem would similarly follow the JavaBean format for its fields.

Hibernate maps domain objects-to-relational databases in XML files. For our Order and OrderLineItem objects there will be two mapping files to express this. There are tools such as XDoclet to assist with this mapping. Hibernate will map the domain objects to these files:

  • Order.hbm.xml
  • OrderLineItem.hbm.xml

You will find these generated files in the WebContent/WEB-INF/classes/com/meagle/bo directory. The Hibernate SessionFactory is configured to know which database it is communicating with, the DataSource or connection pool to use, and what persistent objects are available for persistence. Session objects provided by the SessionFactory are the interface used to translate between Java objects and persistence functions such as selecting, saving, updating, and deleting objects. We will discuss configuring the SessionFactory that Hibernate requires to handle Session objects in a later section.

Business Layer Configuration

Now that we have our domain objects we need to have business service objects that perform application logic, make calls to the persistence layer, take requests from the UI layer, deal with transactions, and handle exceptions. To wire all of this together and make this easy to manage we will use the bean management aspect of the Spring framework. Spring uses inversion of control (IoC), or setter dependency injection, to wire up objects that are referenced in an external XML file. Inversion of control is a simple concept that allows objects to accept other objects that are created at a higher level. This way your object is free from having to create objects and reduces object coupling.

Here is an example of an object creating its dependencies without IoC, which leads to tight object coupling:

Figure 2
Figure 2. Objects arranged without IoC. Object A creates objects B and C.

And here is an example with IoC that allows objects to be created at higher levels and passed into objects so that they can use the implementations directly:

Figure 3
Figure 3. Objects arranged with IoC. Object A contains setter methods that accept interfaces to objects B and C. This could have also been achieved with constructors in object A that accepts objects B and C.

Building Our Business Service Objects

The setters we will use in our business objects accept interfaces that allow loosely defined implementations of the objects that will be set, or injected. In our case we will allow our business service object to accept a DAO to handle the persistence of our domain objects. While the examples in this article use Hibernate, we can easily switch implementations to a different persistence framework and inform Spring of the new implementation DAO object to use. You can see how programming to interfaces and using the dependency injection pattern loosely couples your business logic from your persistence mechanism.

Here is the interface for the business service object that is stubbed for a DAO object dependency:

public interface IOrderService {
  public abstract Order saveNewOrder(Order order)
    throws OrderException,
           OrderMinimumAmountException;

  public abstract List findOrderByUser(
                                     String user)
                           throws OrderException;

  public abstract Order findOrderById(int id)
                           throws OrderException;

  public abstract void setOrderDAO(
                             IOrderDAO orderDAO);
}

Notice that the code above has a setter for a DAO object. There is not a getOrderDAO method because it is not necessary since there is often no need to access the wired OrderDAO object from the outside. The DAO object will be used to communicate with our persistence layer. We will wire the business service object and the DAO object together with Spring. Because we are coding to interfaces, we do not tightly couple the implementation.

The next step is to code our DAO implementation object. Since Spring has built-in support for Hibernate this example DAO will extend the HibernateDaoSupport class, which allows us to easily get a reference to a HibernateTemplate, which is a helper class that simplifies coding with a Hibernate Session and handles HibernateExceptions. Here is the interface for the DAO:

public interface IOrderDAO {

  public abstract Order findOrderById(
                                    final int id);

  public abstract List findOrdersPlaceByUser(
                           final String placedBy);

  public abstract Order saveOrder(
                               final Order order);
}

We still have a couple more objects to wire together for our business layer. This includes the HibernateSessionFactory and a TransactionManager object. This is done directly in the Spring configuration file. Spring provides a HibernateTransactionManager, which will bind a Hibernate Session from the factory to a thread to support transactions (see ThreadLocal for more information). Here is the Spring configuration of the HibernateSessionFactory and the HibernateTransactionManager:

<bean id="mySessionFactory"
       class="org.springframework.orm.hibernate.
              LocalSessionFactoryBean">
  <property name="mappingResources">
    <list>
      <value>
        com/meagle/bo/Order.hbm.xml
      </value>
      <value>
        com/meagle/bo/OrderLineItem.hbm.xml
      </value>
    </list>
  </property>

  <property name="hibernateProperties">
    <props>
      <prop key="hibernate.dialect">
        net.sf.hibernate.dialect.MySQLDialect
      </prop>
      <prop key="hibernate.show_sql">
        false
      </prop>
      <prop key="hibernate.proxool.xml">
        C:/MyWebApps/.../WEB-INF/proxool.xml
      </prop>
      <prop key="hibernate.proxool.pool_alias">
          spring
      </prop>
    </props>
  </property>
</bean>

<!-- Transaction manager for a single Hibernate
SessionFactory (alternative to JTA) -->
<bean id="myTransactionManager"
         class="org.
                springframework.
                orm.
                hibernate.
                HibernateTransactionManager">
  <property name="sessionFactory">
    <ref local="mySessionFactory"/>
  </property>
  </bean>

Each object can be referenced in the Spring configuration within a <bean> tag. In this case the bean mySessionFactory represents a HibernateSessionFactory and the bean myTransactionManager represents a Hibernate transaction manager. Notice that the transactionManger bean has a property element called sessionFactory. The HibernateTransactionManager class has a setter and getter for sessionFactory, which is used for dependency injection when the Spring container starts. The sessionFactory property references the mySessionFactory bean. These two objects will now be wired together when the Spring container initializes. This wiring relieves you from creating singleton objects and factories for referencing and creating these objects, which reduces code maintenance in your application. The mySessionFactory bean has two property elements, which translate to setters for mappingResources and hibernatePropertes. Normally, this configuration would be stored in the hibernate.cfg.xml file if you were using Hibernate outside of Spring. However, Spring provides an easy way to incorporate the Hibernate configuration within the Spring configuration file. For more information see the Spring API.

Pages: 1, 2, 3

Next Pagearrow