Friday, March 6, 2009

Spring Framework Redux

This is my second attempt at this article. The version of this post I originally wrote wasn’t one of my finer works. I decided that I needed to clean it up to try and explain myself a bit more clearly but by the time I had finished, the article was so much different than before that I decided it best to simply submit this one as a new post (and remove the prior post). I’ll soon write a new post where I concentrate more on AOP but for now I’m focused on trying to provide a bit of clarity around Dependency Injection. Hopefully, this version is a bit easier to read.

Spring is based on the idea that loosely coupled systems can adapt and change more quickly while at the same time allowing the developer to focus their concerns on the business problem. The framework utilizes two very powerful architectural concepts, Aspect Oriented Programming (AOP), and an implementation of the Inversion of Control (IOC) design pattern also known as Dependency Injection (DI). If you’re not already familiar with this particular design pattern I’d recommend that you start here: Martin Fowler's Site

Aspect Oriented Programming

First, let’s discuss Aspect Oriented Programming (AOP). When building complex software applications, each business component (say a controller in a typical MVC framework) in addition to solving the business problem at hand typically needs to handle various concerns which cut horizontally across the application (examples include transaction management, logging, performance profiling, and security logic.). The idea behind AOP is to pull these cross-cutting concerns out of the business layer and to ‘weave’ the code to handle these into your classes either at compile time through byte code manipulation or at run time using some form of interceptor logic (think servlet filters). Spring provides a robust implementation of AOP which provides great flexibility in allowing developers to pull code related to these cross cutting concerns from their business logic. If you’re not familiar with AOP, I’d encourage you to read the following: up in more detail on the topic: AOP explained or take a look at AspectJ for an alternative implementation.

Dependency Injection(DI)

As simply as I can describe it, Dependency Injection is a strategy used to reduce the compile time dependency between two objects (in favor instead of injecting the dependency at run-time). Probably the simplest way to wrap your brain around the value that DI can bring to your software solution is to begin with the type of problem it typically helps to solve and work through a few iterative improvements to the design (of course since this is a post about the benefits of using the Spring framework, I’m sure you can guess where we’ll end up).

Let’s begin with our sample domain model. In our business domain we have multiple performers: Some of these performers sing, some dance, and some have some specialized skill like juggling. To model this relationship I’d typically have a Performer interface with a generic perform method. I’d then have a few implementation classes for each specialization.

   1: public interface Performer {
   2:     public void perform();
   3: }
   4:  
   5:  
   6: public class Dancer implements Performer {
   7:     public void perform() {
   8:         System.out.println("I love to dance");
   9:     }
  10: }
  11:  
  12:  
  13: public class Singer implements Performer {
  14:     public void perform() {
  15:         System.out.println("I love to sing");
  16:     }
  17: }
  18:  
  19:  
  20: public class Juggler implements Performer {
  21:     public void perform() {
  22:         System.out.println("I love to juggle");
  23:     }
  24: }

In the sample above we have a Dancer, Singer, and a Juggler. Each of these classes implement the Performer interface. In the perform method for each class we’ll just have them print out what they like to do. The Dancer’s perform method would just say ‘I love to dance’ for example.

Now let’s create a sample program to consume one of these implementations as follows:

   1: Performer perf1 = new Dancer(); 
   2: perf1.perform(); 

This is a pretty common pattern that we would likely encounter in many applications. This first example simply prints out: I love to Dance.

The primary issue with this simplistic snippet of code is the compile time dependency on the Dancer class. If this type of domain were used in a real application you would probably have dozens of these compile time dependencies spread throughout the application. This is fine if requirements never change but when dealing with real world systems requirements always change. What happens if the requirements for the application change and now we need the ability to support a Singer and a Juggler in addition to the Dancer. You have hard coded calls to the Dancer constructor littered throughout the codebase which will need to be changed to support this new requirement.

Time to re-factor our solution. For the next pass let’s drop in an implementation of the factory pattern to see if it helps.

   1: public interface PerformerFactory {
   2:     public Performer createPerformer();
   3: }
   4:  
   5: public class DancerFactory implements PerformerFactory {
   6:     public Performer createPerformer() {
   7:         return new Dancer();
   8:     }
   9: }
  10:  
  11: public class JugglerFactory implements PerformerFactory {
  12:     public Performer createPerformer() {
  13:         return new Juggler();
  14:     }
  15: }
  16:  
  17: public class SingerFactory implements PerformerFactory {
  18:     public Performer createPerformer() {
  19:         return new Singer();
  20:     }
  21: }

So what have we accomplished. Not much as it turns out. We’ve succeeded in centralizing the code which creates each of the concrete performer classes to a single place (e.g. the DancerFactory should be used to create Dancers). The problem is that now we would have hard coded references to the DancerFactory all over our codebase. What else can we do here? Well I can think of two sub-optimal options and one much better one. Let’s start with the two sub-optimal choices:

First, I guess we could tweak our Factory model a bit and have a static method in a single PerformerFactory class which takes a string as an input parameter and returns an instance of the appropriate type of performer based on it’s value (the string could be read from a properties file). Here’s what that code might look like (remember this is a SUB-OPTIMAL solution).

   1: public class BasePerformer {
   2:     public static final String DANCER = "Dancer";
   3:     private static final String JUGGLER = "Juggler";
   4:     private static final String SINGER = "Singer";
   5:     
   6:     public static Performer getPerformer(String performerType){
   7:         if(DANCER.equalsIgnoreCase(performerType))
   8:             return new Dancer();
   9:         if(JUGGLER.equalsIgnoreCase(performerType))
  10:             return new Juggler();
  11:         if(SINGER.equalsIgnoreCase(performerType))
  12:             return new Singer();
  13:  
  14:         return null;
  15:     }
  16:  
  17: }

So what’s wrong with this solution? For one thing as your domain grows this method would just continue to grow. Also, you must make a source code change to swap out one of the types.

The next possible solution I could think of would be to provide a parameter in a properties file using a fully qualified class name. We could then write a bit of generic code to instantiate an instance of this class. This would work but the heavy use of reflection is typically frowned upon. Also it just seems a bit clunky.

   1: /**
   2:  * This method reads in a Performer property from the myFile.properties file 
   3:  * and instantiates an instance of the class specified.
   4:  * @return an implementer of the Performer interface
   5:  */
   6: public Performer createAPerformer() {
   7:     String PERFORMER = "Performer";
   8:     
   9:     Properties properties = new Properties();
  10:  
  11:     try {
  12:         properties.load(new FileInputStream("myFile.properties"));
  13:         String value = properties.getProperty(PERFORMER);
  14:         ClassLoader cl = this.getClass().getClassLoader();
  15:         Class ourClass = cl.loadClass(value);
  16:         return (Performer)ourClass.newInstance();
  17:     } catch (IOException ex) {
  18:         Logger.getLogger(BasePerformer.class.getName()).log(Level.SEVERE, null, ex);
  19:     } catch (InstantiationException ex) {
  20:         Logger.getLogger(BasePerformer.class.getName()).log(Level.SEVERE, null, ex);
  21:     } catch (IllegalAccessException ex) {
  22:         Logger.getLogger(BasePerformer.class.getName()).log(Level.SEVERE, null, ex);
  23:     } catch (ClassNotFoundException ex) {
  24:         Logger.getLogger(BasePerformer.class.getName()).log(Level.SEVERE, null, ex);
  25:     }
  26:  
  27:     return null;
  28: }

The above example assumes you have a property defined in a file named ‘myFile.properties’. The property in question should look something like this:

   1: Performer = Dancer

Now that we’ve looked at a couple of sub-optimal solutions, let’s look at how a DI container provides a more robust solution to this problem.

Spring takes our previous solution another step forward and wires the factory details via xml configuration files rather than by using random property files in your code. Additionally, the objects are created when the application context is initialized which provides an added benefit of letting you know if you have any class mapping issues when the application starts as opposed to when the application uses the classes you’ve referenced (if you mistype the fully qualified class name for example).

Let’s continue our example and see how spring might help to improve upon our design. Using spring, I would now create an xml context file that looks basically like this:

   1: <bean>
   2:     <id="performer"> </id>
   3:     <class="org.demo.perform.Dancer"></class> 
   4: </bean>

In order to effectively use this in my application, I must do the following:

1. Create an instance of the Spring application context passing my xml configuration file name to the constructor. This would typically be done as part of your application startup (perhaps in your main method in the case of a console application).

   1: ApplicationContext ctx = new FileSystemXmlApplicationContext("spring.xml");

2. To use the bean defined in the application code I can ask Spring to serve up an instance of the bean I need by using the id I provided in the xml configuration file. In my example the id we are looking for is “Performer”.

   1: Performer perf1 = ctx.getBean(“Performer”); 
   2: perf1.perform(); 

With our example as it is currently configured, Spring would serve up a Dancer instance any time you ask for a Performer. If we wanted to change this to serve up a Singer instead, we could accomplish this by changing the performer bean in our Spring.xml file.

   1: <bean>    
   2:     <id="performer"></id>
   3:     <class="org.demo.Singer"></class >
   4: </bean > 

At this point, you might be thinking, what makes this any better than the reflection example presented earlier? This is a legitimate questions. Ignoring for the time being that writing and maintaining that extra bit of infrastructure code has a cost associated with it (and also the fact that most developers on your team would be totally intimidated by the reflection code used no matter how simple it is). Let’s take a look at what else Spring can do for us.

Let’s go back to our earlier example and assume that our Performer interface has a talent attribute which stores each performer’s specialization. We’ll add the following two methods to our interface:

   1: public Talent getTalent() 
   2: public void setTalent(Talent talent) 

Our new class Talent has a couple of attributes but for the purpose of this example we can assume it has a single field which contains a string to identify a given performer’s talent. So let’s have the constructor in that class take a string and use it to initialize the talent with it:

   1: public talent(String talent){ 
   2:     this.talent = talent; 
   3: } 

Now, if we go back to our reflection or factory examples and tried to support this new requirement, our solution would need some additional work to support the new domain. This makes the code brittle. Spring on the other hand, provides a mechanism for defining the dependency in the configuration file thus pulling these implementation specific details out of the code and into your master configuration file (Spring.xml in my example). The updated configuration file for Spring would now look something like this:

   1: <bean>
   2:     <id="Talent"></id> 
   3:     <class="org.demo.Talent"></class>
   4:     <value="Dances"></value>
   5: </bean> 
   6: <bean>
   7:     <id="Performer"></id> 
   8:     <class="org.demo.Dancer"></class>
   9:     <name="talent" ref="Talent"></name>
  10: </bean>

Summary

If I’ve done a reasonable job of explaining things, you should now be able to see how a DI container such as Spring can help you to build systems which are loosely coupled. Spring is available as a framework for Java as well as .NET. If you would like to learn more about the framework and the value it might add to your next project check out the Spring website

No comments:

Post a Comment