May 5, 2006

Simply Spring

So you've heard of The Spring Framework, just one of another list of meaningless addons for your development pleasure. Or is this one really worth the hype? Well, honestly, I'm not here to advocate or obliterate the use of Spring in your Java apps, but I am going to give you an example of how I've been using it. I approach this article from a problem/solution angle, and I leave a lot to be desired in setup and configuration. If you really want to get into Spring you will need more than this article, but maybe this will show you a simple usage of Spring as an example of the framework's implementation.

Problem:
Our Java app like many others has a Data Access Layer. In this layer of our app we use Data Access Objects (DAOs - pronounced dow) to access/manipulate our backend data. One issue that is always prevalent when accessing backend data is this:

Will we always be using the same backend?

This is an important question. If we change backends (i.e. switch database clients such as going from MySQL to Oracle) how much of our code is going to need to change? This is the purpose of a DAO, a single point of exit/entry for our data connections. We need to make sure and implement an architecture (pattern if you will) that will make this switch as easy as possible.

Many people are probably thinking one step ahead of me here. An easy solution to this problem would be to create a common DAO Interface that we will implement in all of our concrete DAO classes. Then in our client code (the code that needs to call on our DAO) we simply pass around the interface. But a small problem is still there. We have to instantiate our concrete DAO in our code:

InterfaceDAO dao = new ConcreteMysqlDAO();

So now every time we change our concrete DAO we have to find the code that creates an instance of ConcreteMysqlDAO and change it, keeping with switching from MySQL to Oracle now our dao instantiation looks like this;

InterfaceDAO dao = new ConcreteOracleDAO();

So now we have to update our code and recompile and redeploy, all because we changed our concrete implementation.

Ah, but many will break out their Gang of 4 Patterns book and call me a dunce. You see there is a little pattern called the Factory Pattern that can help us take care of this. We simply create a Factory object that will pass us an instance of our concrete class and now all we have to do is call to the factory to recieve our implementation:

InterfaceDAO dao = DaoFactory.getDaoInstance("concreteDao");

So now, as long as we us the same String key (concreteDao) in our Factory we won't have to change our instantiation code, but now we have to update the code in our factory. I admit this is cleaner, but it still involves updating code that shouldn't really need to be touched. The more code that has to be modified the more likely it is that you will introduce bugs into your system. That is overhead, and really un-needed overhead.

What if there is a way we can use a configuration file that references our concrete DAO? All we would have to do is update the config file any time we needed to change our concrete class. This means less code editing and fewer chances to have deployment issues. Afterall, we already deployed working code, why should we have to redeploy just because we introduce a new DAO?

Solution:
So if we use Spring's handy XML configuration capabilities we can define a Spring Bean that will be an instance of our concrete DAO. A Spring Bean can be accessed via Spring's Bean Factory, which is very much an implemention of the Factory Pattern we've already talked about, the only difference is that if we use the XML configuration file to define our concrete DAO then when we need to change our DAO we don't have to make changes to any Java code that we know already works, we just change the XML reference to our DAO.

So we first define our DAO bean in the Spring XML configuration file:

<bean name="concreteDao" class="com.yourapp.dataacceess.dao.ConcreteMysqlDAO"/>

So now our Spring container will hold a reference to our MySQL DAO. We can reference it like so:

InterfaceDAO dao = (InterfaceDAO)beanFactory.getBean("concreteDao");

So now when we want our concrete DAO we just fetch if from Spring, if our concrete changes then we change the XML bean like so:

<bean name="concreteDao" class="com.yourapp.dataacceess.dao.ConcreteOracleDAO"/>

This means that we don't have to modify Java code that we know is already working, so we don't take the chance of introducing new bugs into our working code.

Until next time
Les

No comments: