Circular Dependency Puzzle
ColdFusionThis entry is the equivalent of me talking this problem out publicly. Perhaps by the end of it I will have my solution!
Aaron and I are working fast and furiously on InstantSpot behind the scenes so that we can put out a rather large 2.0-ish release in the next couple of months. In the scope of this version we came to the conclusion that it was time to remove Reactor and move to concrete classes. As I mentioned a couple blog posts ago, I am using Brian Rinaldi's Illudium PU-36 Code Generator for creating the CFC templates I modified the XSL a bit to fit my needs, and am using ColdSpring to wire them together so that and object's Service not only has its own DAO and Gateway injected into it, but whatever other Services that are necessary for managing relationships to other objects.
For instance, take our Site bean and its helpers: Site.cfc, SiteService.cfc, SiteDAO.cfc, and SiteGateway.cfc.
Now, let's add in our Page bean and its helpers: Page.cfc, PageService.cfc, PageDAO.cfc, PageGateway.cfc.
In our InstantSpot model, Site hasMany Page objects. Fairly straight forward right?
So in my SiteService I have the methods getPageQuery(), which returns a query recordset from the PageService, and getPageArray() which builds an array of the getPageQuery() recordset.
So, if my application were no bigger than this, my ColdSpring configuration would look like this:
Taking that approach, all works well. When I instantiate a Site bean I can successfully call Site.getPageQuery(), Site.getPageArray(), Site.getPageIterator() and everything is just cruising along fine.
whooops! a snag....
Well as we see, Site objects "hasMany" Page objects, but doesn't a Page "hasOne" Site? In our model it does. Well no problem! I will just inject an instance of the SiteService into the PageService so that the PageService can do a call to PageService.getSite(). So, let's add the SiteService argument to the PageService init() and modfiy the ColdSpring config like so:
Now I reinit my application and I see...
java.lang.StackOverflowError
Of course my initial reaction was "Man, ColdSpring can't do that? Come on!" so I decided to manually instantiate the DAOs and Gateways, passing the arguments by hand.
So I typed the following:
Sweet... so now I will just instantiate that SiteService, and pass it an instance of the PageService... hmmm... but I guess I need to instantiate the PageService first, so I will do that and pass it an instance of the SiteService.... wait... ummm....
So yeah... that is my current puzzle. I know it has been solved countless times by others but for some reason I am currently hung up on it. What is it that I am missing in this pattern?
I really like the idea that a Bean can only talk to its own Service and that the Services then talk to each other. I know that feels right. I also know I don't want to have to instantiate these things at runtime in the Services themselves because that would circumvent the benefits of dependency injection.
For the record, this exercise of typing my problem out loud has certainly made it even more painfully clear, but I still don't have an answer that feels right. What am I missing?





Loading....