Community   SpringSource   Projects    Downloads    Documentation    Forums    Training   Exchange   Blogs

Go Back   Spring Community Forums > Core Spring Projects > Core Container

Reply
 
Thread Tools Display Modes
  #1  
Old Dec 22nd, 2004, 11:59 AM
cyboc cyboc is offline
Senior Member
 
Join Date: Sep 2004
Location: Vancouver, BC, Canada
Posts: 135
Default Refactoring from Singleton Anti-Pattern to Dep Injection

Hi,

I'm currently refactoring a large Swing application to use the Spring Framework. Unfortunately, the application currently makes heavy use of the Singleton "anti-pattern" to access the business service layer.

So far, it has been easy to make the IOC container instantiate the service layer objects as beans and to inject them into objects at the "top layer" of the application, that is objects directly involved with the main frame. However, what about objects farther down the food chain? For example (somewhat contrived), what about a model object for a panel that is part of another panel on a dialog that is accessed from a child frame of the main frame? The dependency chain could look like this, for example:

Code:
MainFrame
->ChildFrame
->DialogLaunchedFromChildFrame
->BigPanelOnDialog
->LittlePanelInsideBigPanel
->LittlePanelModel
->MyServiceLayerObject
Currently LittlePanelModel accesses MyServiceLayerObject in singleton fashion. For example:
Code:
MyServiceLayerObject.getInstance.doSomeService()
The question is, how should I refactor this code so that LittlePanelModel does not have to access MyServiceLayerObject in singleton fashion. The way I see it, there are several refactoring options here:
1) Instantiate ALL of the objects in the IOC container and use dependency injection to inject the service layer dependency into LittlePanelModel. This may seem like the logical choice except when you look at the big picture. This sort of long dependency chain is seen all over the application because there are many, many screens, dialogs and panels in the app. I would have to configure several hundred objects in the application context configuration files. Some of you say "what's wrong with that"? In the long run, I think it might be workable but in the short run, I can only refactor this app in stages. I can't make all of the beans IOC-managed all at once; I have to move towards this goal slowly.
2) Get the container to Inject the dependency into MainFrame and then pass the dependency along as each object instantiates its helper object in the next link of the dependency chain. I don't particularly like this because objects in the middle of the chain are not directly dependent on the service layer objects; to keep coupling low, I don't want to introduce unnecessary dependencies.
3) Use "one singleton to rule them all" (this hiliarious Lord of the Rings-ish quote is from the javadocs for Spring's BeanFactoryBootstrap class). In other words, allow singleton access to the bean factory or application context that holds all of the service layer objects. This is still a singleton but at least there's only ONE singleton in the entire app instead of one for each service object.

Comments or advice?
__________________
Cheers,
Joe
"All your bean are belong to us" - Spring Framework's IOC Container
Reply With Quote
  #2  
Old Dec 22nd, 2004, 02:04 PM
steve_smith steve_smith is offline
Member
 
Join Date: Oct 2004
Posts: 69
Default

I think maybe option 3 okay for Swing application. I looking at Spring Rich Client and they have this sort of "one singleton to rule all". It is Application class. If you looking at some Spring Rich Client code, you see lots of classes access this singleton to look up images, icons, rules source, messages, etc. Example:
- Application.services().getIconSource() in OverlayValidationInterceptorFactory class
- Application.services() in ApplicationServicesAccessor class, which many class derives from and using it to get images, icons, etc.

So I think is not big deal if Keith already doing this in Spring Rich Client (if Keith using it, it must be okay for you to use it too :wink: ). Maybe just make sure you have only this one singleton though. Make everything else non-singleton.

What you other guys say about this one?
__________________
Stefano Rossi

"If I want your opinion, I'll give it to you."
Reply With Quote
  #3  
Old Dec 22nd, 2004, 02:14 PM
cyboc cyboc is offline
Senior Member
 
Join Date: Sep 2004
Location: Vancouver, BC, Canada
Posts: 135
Default

Quote:
Originally Posted by steve_smith
I think maybe option 3 okay for Swing application. I looking at Spring Rich Client and they have this sort of "one singleton to rule all". It is Application class.
Thanks Stefano. My gut was telling me this too. If Spring Rich uses this one-singleton idea, it can't be that bad can it? I mean, as long as I use DI where convenient and also make sure that this is the only singleton, it should be okay, right? This will allow me to convert my existing singletons to beans.

Does anyone else have a differing opinion?
__________________
Cheers,
Joe
"All your bean are belong to us" - Spring Framework's IOC Container
Reply With Quote
  #4  
Old Dec 23rd, 2004, 06:16 AM
jbetancourt jbetancourt is offline
Senior Member
 
Join Date: Aug 2004
Location: u.s.a
Posts: 399
Default

Not that I'm criticizing this idea, but how is this not replacing the "singleton" antipattern with the the ServiceLocater "anti-pattern"?

A matter of degree or misuse? Or is a ServiceLocator object that is created via DI better then an old style ServiceLocator.

I guess if you dig deep into any code base (or even cosmology) there is one singleton somewhere.
Reply With Quote
  #5  
Old Dec 23rd, 2004, 11:30 AM
cyboc cyboc is offline
Senior Member
 
Join Date: Sep 2004
Location: Vancouver, BC, Canada
Posts: 135
Default

jbetancourt, thanks for your response.

Quote:
Originally Posted by jbetancourt
how is this not replacing the "singleton" antipattern with the the ServiceLocater "anti-pattern"?
IMHO, using one standard singleton provided by either Spring (e.g. BeanFactoryBootstrap, SingletonBeanFactoryLocator, ContextSingletonBeanFactoryLocator) or Spring Rich Client (e.g. Application) has got to be at least a little bit better than using several custom singletons. Using this one singleton instead of several custom singletons has several benefits:
1) The custom singletons can be converted to "service" beans and we can remove the getInstance() method from each bean. This means that classes that depend on them can now depend on their interfaces instead of their implementations (e.g. you can call myService.someMethod() instead of myServiceImpl.getInstance().someMethod()). This makes it easier to change the implementation or to mock it up for testing.
2) The properties of these service beans can all be configured in a standard way in the IOC container instead of using ad hoc techniques.
3) These service beans can be injected with their dependencies (for example, dependencies on a transaction manager) by the IOC container.

Quote:
Originally Posted by jbetancourt
Or is a ServiceLocator object that is created via DI better then an old style ServiceLocator.
Yes, I think so -- see the benefits, above. And note that these "service locators" are beans not singletons; there would be only one singleton left in the app after the singleton services are refactored to service beans.

Quote:
Originally Posted by jbetancourt
I guess if you dig deep into any code base (or even cosmology) there is one singleton somewhere.
This is precisely my point. In Spring Rich Client, that singleton is the Application class. If you use almost any part of Spring Rich Client, you are using this singleton. For example, as Stefano points out, a lot of Spring Rich Client's classes use this singleton to load messages, icons, rules, etc. So that singleton is always there, under the covers. If Spring Rich Client didn't have this singleton, many of Spring Rich Client's classes would need setters for message sources, icon sources, rules sources, etc. Yes, having these extra setters would be flexible, but it could also lead to a lot of extra configuration and also a lot of passing around of dependencies through a long chain of objects (see my first post in this forum topic), where objects in the middle of the chain might not even use the dependency. I'm not sure if this flexibility would be worth the extra hassle.

In a web app, I guess you don't really need a singleton like Spring Rich Client's Application singleton. But then again, web apps have the servlet context where you can shove your app context, making it pretty much globally accessible. With Swing apps, you don't have the benefit of a servlet context. So, the way I see it, the Application singleton is sort of like the servlet context.

If our existing app used only Spring Rich Client's Form, View and Dialog related classes, we would probably never see references to the Application singleton in our app's code. Unfortunately, we currently have our own "form", "view" and "dialog" framework in our existing app. At the moment, we don't have time to convert the entire app over to using Spring Rich Client's Form, View and Dialog framework. Therefore, in the short term, I think we must use the Application singleton in our framework to look up messages, icons, rules, etc in a similar fashion to how Spring Rich Client's Form, View and Dialog framework does these lookups. I don't really see the difference between what we are doing and what Spring Rich Client does.

In theory, I think pure DI would be great but how do I get from here (lots of custom singletons) to there (pure DI) with the least amount of disruption to the existing app? Surely some DI is better than no DI. I think a lot Spring users are in this same situation of having to convert an existing app instead of starting from scratch. All I'm looking for is a little advice on how to do this conversion sanely without having to turn the existing app upside down all at once.
__________________
Cheers,
Joe
"All your bean are belong to us" - Spring Framework's IOC Container
Reply With Quote
  #6  
Old Dec 24th, 2004, 12:54 PM
rstearns01 rstearns01 is offline
Senior Member
 
Join Date: Aug 2004
Location: Atlanta, GA
Posts: 129
Default

cyboc,

I had to do something very similar (albeit a web app). Everything was looked up via a static factory/registry. My refactoring strategy was to start at the bottom layer by converting the factory to acquire beans from the Spring container. That let the codebase remain stable while I built up the bean configurations. In other words, the first set of beans provided by the factory came from the IoC container, but they themselves still did DL of their collaborators.

At that point I began modifying those classes to replace the DL with DI. Once that was complete, I continued by moving up layer by layer. Going from the top down, you have to watch that everyone gets the same instance of your singleton since the one used by Spring is only one by virtue of the IoC registry. I may have been wrong, but I thought it would be more problemmatic during a long, complicated refactor.

This is probably a good discussion for the architecture forum. We need an "Introduce Spring" refactoring with a one button Eclipse plugin.

Cheers.
__________________
Randy
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Problem with stylesheet in acegilogin.jsp page wolf Spring Security 11 Jun 1st, 2006 04:30 PM
after login redirects incorrectly ryan.tyer Spring Security 1 Oct 10th, 2005 05:16 PM
EHCaching Hibernate dencamel Data Access 3 Sep 6th, 2005 09:03 PM
Loosing my SecureContext sklakken Spring Security 3 Jul 21st, 2005 01:44 PM
DefaultAdvisorAutoProxyCreator skipping beans youngm Core Container 6 Apr 12th, 2005 04:29 PM


All times are GMT -5. The time now is 08:06 AM.


Contegix provides first-class managed hosting and partial sponsorship of these forums.

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.