April 16, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Wiring Java Applications with Spring

  • May 12, 2005
  • By Michael Klaene
  • Send Email »
  • More Articles »

The Spring Framework

In 2002, J2EE expert Rod Johnson published an influential book entitled Expert One-on-One J2EE Design and Development. This book encouraged readers to take a more pragmatic approach to developing J2EE applications, rather than just assuming standard technology, such as Enterprise JavaBeans (EJBs), were always the best solution to the problem. Rod suggested that there was a rather wide gap between the promise of technology such as EJBs (simpler development, improved performance, and so forth) and what the technology was actually delivering. To demonstrate solutions to common J2EE programming problems, the book introduced code examples using a framework that Rod Johnson had authored based upon his own experiences. The Spring framework is essentially the product of improvements made to this framework first presented in the book, along with additional features inspired by ideas from existing frameworks. A vibrant developer community and subsequent book releases have followed, resulting in a new way of thinking about J2EE.

This article is intended for those who are new to the Spring framework, but would like to know more about it. The Spring framework addresses a variety of topics. This article will focus on what is perhaps the most important, and useful, aspect of the framework: Inversion of Control.

Spring, the IOC Container

Spring is often called an 'IOC Container.' IOC stands for Inversion of Control. IOC is a design pattern that alleviates application objects from the responsibility of creating, and managing their dependencies. Instead, these application objects are free to concentrate solely on fulfilling their business purpose. Martin Fowler, respected J2EE author, coined the phrase 'Dependency Injection' as a more descriptive title to describe this behavior. 'Inversion of Control' and 'Dependency Injection' are often used interchangeably when talking about Spring. With Spring, classes no longer need to look up, then create, their own dependencies. Instead, the container does it for you. Consider the problems associated with objects assembling themselves, through code like the following:

public interface Drive {
    public void read();
    ...
}
public class HardDrive extends Drive {
    public void read();
    ...
}

public class Computer {
   private Drive drive;

   //Other properties...
   ...

   //Constructor
   Computer() {
        drive = new HardDrive();
        drive.read();
   }
}

This approach is far from ideal because it couples you to a specific implementation. What if you wanted to swap out the current drive for another type? You would have to modify the Computer class. It is therefore always a good idea to mask such implementation details, preferably coding to interfaces. In the past, several methods have emerged to avoid hard coding an implementation. These approaches usually involve using design patterns such as Service Locator and Java Naming and Directory Interface (JNDI) lookups (which you'll learn about in a bit).

In addition to coding to interfaces rather than a specific implementation, it's a good idea to limit the number of object instances as well as who is responsible for creating those instances. Developers often turn to the Singleton design pattern, and custom object factories to address these issues.

As we proceed, I hope to convince you that a Spring 'ApplicationContext' offers a superior approach to all of the aforementioned solutions, making it easy for you to develop applications with less code, less coupling, and, in general, less problems!

Wiring Dependencies with an ApplicationContext

If you work with Spring, you will most surely meet the ApplicationContext. A Spring ApplicationContext is essentially a registry of application objects. The ApplicationContext object actually extends a Spring class called BeanFactory. In reality, BeanFactory provides a good deal of the functionality developers often associate with an ApplicationContext. A BeanFactory reads configuration data from a file typically, but not always, formatted in XML, and creates the types of objects desired. It manages dependencies between objects and provides a mechanism to control their lifecycles. Spring is an 'interface-driven' framework and ApplicationContext (which includes BeanFactory) implements numerous interfaces that define its behavior.

In trivial applications, a BeanFactory may fulfill your needs. However, ApplicationContext adds a rich layer of functionality above and beyond BeanFactory, including support for Aspect Oriented Programming (AOP), internationalization, transaction support, and event handling. The feature set is pretty extensive. Most of the behavior you will explore comes from BeanFactory. However, most applications will use ApplicationContext to take advantage of its extended functionality.

As a means of introduction, what follows are a series of examples designed to highlight the use of Spring's ApplicationContext. The examples will involve a sample program that manages client/sales representative relationships. There will be little in the way of functionality, just enough to get the point across.

First, consider two domain objects: SalesRep and Client. These objects represent a sales person and a client assigned to a specific sales person:

public class SalesRep {
   private Integer id;
   private String name;

   //Clients assigned to SalesRep
   private Set clientSet;

   //getter/setter methods....
}

public class Client {
   private Integer id;
   private Integer id companyId;
   private String contactName;
   ...

   //Which rep is assigned to the client?
   private SalesRep salesRep;

   //getter/setter methods....
}

As you might expect, SalesRep contains a Set of clients, and Client contains a reference to a SalesRep. Typically, these types of objects represent data from a database and are created as needed by the application's users. In other words, there can be numerous instances floating around the system at any time.

Along with these objects, however, there is a need for objects to manage the business functions that operate on the domain instances. Two commonly used objects include the Session Facade and Data Access Object (often simply referred to as DAO). Basically, a Facade consolidates all the business services your application provides to its users. It serves as a gateway to business logic. A Data Access Object conceals the complexities of dealing with a data source. A primary goal of both is to avoid dependencies upon a specific implementation. In a typical scenario, a user invokes a facade method, and the facade in turn will call upon a data access object to perform some of the work that involves the database. As you will see, it is these types of objects that you will most likely want a Spring ApplicationContext to manage. Here are snippets of your Facade and DAO, including interfaces and their implementations.

//Session Facade Interface
public class SalesManagerFacade {
   SalesManagerDAO salesManagerDAO;

   public void assignClientToSalesRep(SalesRep salesRep,
                                      Client newClient);
   ...
}

//Facade Implementation
public class SalesManagerDefaultImpl(SalesManagerDAO) {

   private SalesManagerDAO salesManagerDAO;

   public void SalesManagerDefaultImpl(SalesManagerDAO
                                       salesManagerDAO) {
       this.salesManagerDAO = salesManagerDAO;
   }

   public void assignClientToSalesRep(SalesRep salesRep,
                                      Client newClient) {
       this.salesManagerDAO.addClient(SalesRep salesRep,
                                      Client newClient);
   }
   ...
}

//DAO Interface
public class SalesManagerDAO {
   public String setImplType();
   public void addClient(salesRep, newClient);
   ...
}
//DAO Implementation using JDBC API
public class SalesManagerJdbcDAO {

   private String implType;
   private Map dbProperties;

   public String setImplType(String implType) {
      this.implType = implType;
      return this.implType;
   }

   public String setDbProperties(Map dbProperties) {
      this.dbProperties = dbProperties;
   }

   public void addClient(salesRep, newClient) {
      Connection conn = DbUtils.getConn();
      //perform database work via JDBC...
   }
   ...
}

Note that the Facade implementation contains a reference to the DAO so that it may invoke DAO methods. Also, there is no reason why all application users can't share a single instance of each of these objects. The DAO implementation contains a Java Collection to hold connection properties and a Java String to specify the current implementation type. Keep in mind that this is purely for purposes of the demonstration and not to suggest this is the ideal way to store this information.





Page 1 of 3



Comment and Contribute

 


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

 

 


Sitemap | Contact Us

Rocket Fuel