Adding Inversion of Control to our application
We a lready took the first step in reducing maintenance costs by eliminating our
dependency on MySQL by using a test stub. However the mechanism we used
incurred a great risk due to violation of the DRY (Don’t Repeat Yourself) principle.
For our current problem, we want Spring Python to manage the creation of
WikiService in a way that allows us to make changes in one place, so we don’t
have to edit every test method. To do this, we will define an IoC container and
let it handle creating the objects for us. The following code shows a simple
container definition.
- First of all, let’s create an IoC container using Spring Python and have it
create our instance of WikiService. - Now we want to change our startup code so that it uses the container instead
of creating WikiService object directly.
if __name__ == “__main__”:
from springpython.context import ApplicationContext
container = ApplicationContext(WikiProductionAppConfig())
service = container.get_object(“wiki_service”)
WikiWebApp(service).run()
In this version of our wikiweb application, the service object was obtained
by asking the container for wiki_service. Spring Python dispatches this
request to WikiProductionAppConfig where it invokes the wiki_service()
method. It is now up to the container to create an instance of WikiService
and return it back to us.
The dependencies are shown in the following diagram:

At this intermediate stage, please note that WikiService is still dependent on
MySqlDataAccess. We have only modified how our application gets a copy
of WikiService. In later steps, we will completely remove this dependency
to MySqlDataAccess.
- Let’s see what our test case looks like when we use the IoC container to
retrieve WikiService.
from springpython.config import PythonConfig
from springpython.config import Object
class WikiProductionAppConfig(PythonConfig):
def __init__(self):
super(WikiProductionAppConfig, self).__init__()
@Object
def wiki_service(self):
return WikiService()
You can spot the objects defined in the container by noting Spring Python’s
@Object decorator.
from springpython.context import ApplicationContext
class WikiServiceTestCase(unittest.TestCase):
def testHittingWikiService(self):
container = ApplicationContext(WikiProductionAppConfig())
service = container.get_object(“wiki_service”)
service.data_access = StubDataAccess()
results = service.statistics(“stub page”)
self.assertEquals(10.0, results[0])
self.assertEquals(5.0, results[1])
With this change, we are now getting WikiService from the container, and then
overriding it with the StubDataAccess. You may wonder “what was the point
of that?” The key point is that we shifted creation of our testable wiki_service object
to the container. To complete the transition, we need to remove all dependency
of MySqlDataAccess from WikiService. Before we do that, let’s discuss
Dependency Injection.
Dependency Injection a.k.a. the Hollywood principle
So fa r, we have managed to delegate creation of our WikiService object to
Spring Python’s Inversion of Control container. However, WikiService still
has a hard-coded dependency to MySqlDataAccess.
The nature of IoC is to push object creation into a 3rd party location. Up to this
point, we have been using the term Inversion of Control. The way that Spring Python
implements IoC, is through the mechanism of Dependency Injection. Dependency
Injection, or DI, is where dependencies are pushed into objects through either
initialization code or by letting the container directly assign attributes. This is
sometimes described by the Hollywood cliché of Don’t call us, we’ll call you. It
means that the object which needs a certain dependency shouldn’t make it
directly, but instead wait on the external container to provide it when needed.
Because Spring Python only using Dependency Injection, the terms,
Inversion of Control, IoC, Dependency Injection, and DI may be used
interchangeably throughout this book to communicate the same idea.
The following version of WikiService shows a complete removal of dependence on
MySqlDataAccess.
class WikiService(object):
def __init__(self, data_access):
self.data_access = data_access
def statistics(self, page_name):
“”"Return tuple containing (num hits, hits per edit)”"”
hits = self.data_access.hits(page_name)
return (hits, hits / len(self.data_access.edits(page_name)))
With this altered version of WikiService, it is now up to WikiService’s creator to
provide the concrete instance of data_access. The corresponding change to make
to our IoC container looks like this.
from springpython.config import PythonConfig
from springpython.config import Object
class WikiProductionAppConfig(PythonConfig):
def __init__(self):
super(WikiProductionAppConfig, self).__init__()
@Object
def data_access(self):
return MySqlDataAccess()
@Object
def wiki_service(self):
return WikiService(self.data_access())
We have added a definition for MySqlDataAccess so that we can inject this into the
instance of WikiService when it’s created. Our dependency diagram now shows a
complete break of dependency between WikiService and MySqlDataAccess.

As described earlier, this is akin to the Hollywood mantra Don’t call us, we’ll call you.
It opens up our code to the possibility of having any variation injected, giving us
greater fl exibility, without having to rewrite other parts of the system.
Adding Inversion of Control to our test
With t his adjustment to WikiService and WikiProductionAppConfig, we can now
code an alternative way of setting up our test case.
- First, we subclass the production container configuration to create a test
version. Then we override the data_access object so that it returns our
stub alternative. - Now, we can alter our test suite to fetch WikiService just like the production
main code, except using our alternative container.
class WikiTestAppConfig(WikiProductionAppConfig):
def __init__(self):
super(WikiTestAppConfig, self).__init__()
@Object
def data_access(self):
return StubDataAccess()
Using this technique, we inherit all the production definitions. Then
we simply override the parts needed for our test situation. In this case, we
return a slightly modified version of WikiService that is suitable for our
testing needs.
from springpython.context import ApplicationContext
class WikiServiceTestCase(unittest.TestCase):
def testHittingWikiService(self):
container = ApplicationContext(WikiTestAppConfig())
service = container.get_object(“wiki_service”)
results = service.statistics(“stub page”)
self.assertEquals(10.0, results[0])
self.assertEquals(5.0, results[1])
The dependencies (or lack of!) between WikiService and StubDataAccess are
shown in following diagram:

This makes it easy to plug in our alternative StubDataAccess. An important thing
to note is how our test code is no longer overriding the data_access attribute, or
doing any other special steps when creating WikiService. Instead, this creation logic
has been totally turned over to the IoC container. We can now easily write as many
tests as we want with no risk of changes to WikiService or data_access, provided
we continue to rely on the IoC container to handle object creation. We just visit the
blueprints of WikiTestAppConfig to make any future alterations.
In conc lusion of this example, the following diagram shows our current objects as
well as potential enhancement to our system. In this possible situation, we have
defined multiple data access components. To find out which one is being injected
into WikiService, we simply look at the relevant container’s definition, whether its
production or a particular test scenario. Our current system may use MySQL, but if a
new customer wanted to use PostGreSQL, we simply create another variation of our
container, and inject the alternate data access object. The same can be said for Sqlite.
And all of this can be done with no impact to WikiService.

Spring Framework Articles
- Spring Framework Articles
- Introduction to Spring MVC Web Framework – Web Tier
- Integrating Spring Framework with Hibernate ORM Framework
- Introduction to Spring Web Framework
- Introduction to Spring’s Aspect Oriented Programming(AOP)
- Introduction to Spring Web Services






September 8, 2010
Spring Framework