Fighting circular dependencies in Bootstrap

Fighting circular dependencies in Bootstrap

Have you ever encountered this error message?

Fatal error: Uncaught exception ‘Zend_Application_Bootstrap_Exception’ with message ‘Circular resource dependency detected’ in…

Damn. Two of my resources are trying to bootstrap each other!

Depending on the complexity of your Bootstrap you might be in for a rather long investigation of your resources and their dependencies. If you are initializing only a few resources you will probably identify the culprits straight away but if your Bootstrap is a bit longer the offending resources might be difficult to find and untangle. Let’s build a simple tool for Zend Framework 1 applications which will make the troubleshooting easier.

What is circular dependency in Bootstrap?

Imagine situation when resource A needs to bootstrap resource B and resource B needs to bootstrap A. Like this:

The resources may also depend on each other via an intermediary (or more):

The bootstrapping mechanism of Zend Framework detects these dependencies and halts the execution with the forementioned fatal error (otherwise we would end up in an infinite loop). Unfortunately the error itself is of little help when troubleshooting as we only get the names of two resources taking part in the loop and they are in a pretty messy format on top of that. Try to decipher the names of the two resources from the complete error message:

Fatal error: Uncaught exception ‘Zend_Application_Bootstrap_Exception’ with message ‘Circular resource dependency detected’ in C:\WebDev\Libraries\ZF\v1.11.11\library\Zend\Application\Bootstrap\BootstrapAbstract.php:662 Stack trace: #0 C:\WebDev\Libraries\ZF\v1.11.11\library\Zend\Application\Bootstrap\BootstrapAbstract.php(629): Zend_Application_Bootstrap_BootstrapAbstract->_executeResource(‘resourceC’) #1 C:\WebDev\PhpStorm\SandBoxMVC-ZF1\application\Bootstrap.php(46): Zend_Application_Bootstrap_BootstrapAbstract->_bootstrap(‘resourceC’) #2 C:\WebDev\Libraries\ZF\v1.11.11\library\Zend\Application\Bootstrap\BootstrapAbstract.php(669): Bootstrap->_initResourceD() #3 C:\WebDev\Libraries\ZF\v1.11.11\library\Zend\Application\Bootstrap\BootstrapAbstract.php(629): Zend_Application_Bootstrap_BootstrapAbstract->_executeResource(‘resourceD’) #4 C:\WebDev\PhpStorm\SandBoxMVC-ZF1\application\Bootstrap.php(53): Zend_Application_Bootstrap_BootstrapAbstract->_bootstrap(‘resourceD’) #5 C:\WebDev\Libraries\ZF\v1.11.11\library\Zend\Applic in C:\WebDev\Libraries\ZF\v1.11.11\library\Zend\Application\Bootstrap\BootstrapAbstract.php on line 662

You are right, it’s resourceC and resourceD, but have you had fun extracting these out? And more importantly, can you be sure that it is only these two resources which form the dependency circle? (Hint: you cannot.) What we need is a clearer view of resource dependencies.

Extend the original ZF Bootstrap

We will tap into the bootstrap process to display resource names as they are being initialized. To do this we need to extend the Zend_Application_Bootstrap_Bootstrap class and override the _executeResource() method. We will then save our new bootstrap class in a library and use it as a base class for the actual Bootstrap class of our application.

class Dlu_Wal_Bootstrap extends Zend_Application_Bootstrap_Bootstrap {

    /**
     * Turns Bootstrap Debug logging on/off
     * Redefine in descendant
     * @var boolean
     */
    protected $_logging		= false;

    /**
     * Current indentation level
     * @var integer
     * @see _executeResource()
     */
    protected $_indent		= 0;

    /**
     * Resource counter
     * Counts resources as they are being bootstrapped
     * @var int
     */
    protected $_rscCounter  = 0;

    /* ****************************** METHODS ************************** */

    /**
     * Execute a resource with optional logging
     * Echoes the resource name and proxies to the overloaded method
     * @param  string $resource
     */
    protected function _executeResource($resource) {
        $resource   = strtolower($resource);
        if($this->_logging && !in_array($resource, $this->_run)) {
            $this->_rscCounter++;
            $line   = sprintf('#%03d %s %s', $this->_rscCounter,
                              str_repeat(' ', $this->_indent * 3),
                              $resource);
            //NOTE! Wrap the $line variable in html pre tag!
            echo "$line";
            $startLogged	= true;
            $this->_indent++;
        } else {
            $startLogged	= false;
        }
        parent::_executeResource($resource);
        if($startLogged) {
            $this->_indent--;
        }
    }
}

Please note the line 39 and the preceding comment if you are going to copy and paste this piece of code. (It is safer to download the code instead.)

Use the modified Bootstrap

Base your application’s Bootstrap class on Dlu_Wal_Bootstrap, turn on logging (line 7) and you are done:

class Bootstrap extends Dlu_Wal_Bootstrap
{
    /**
     * Turns Bootstrap Debug logging on/off
     * @var boolean
     */
    protected $_logging		= true;

    //Define your resource methods
    //...
}

Now it is much easier to see the dependencies between the resources:

#001  resourcea
#002     resourceb
#003  resourcec
#004     resourcee
#005        resourced
#006           resourcec

Fatal error: Uncaught exception 'Zend_Application_Bootstrap_Exception' with message 'Circular resource dependency detected' in

The notation is pretty much self explanatory. If a resource initializes other resources, they are indented. As we can see the resource C needs the resource E which needs resource D which needs resource C again:

Now you know that your problem of circular dependency is limited to resources C, E and D and you have to untangle these somehow.

Breaking the vicious circle

Well, putting the resources and their dependencies straight is a different story and actually a bit off-topic. Anyway here are two hints:

Split the resource

There is very likely a ‘hidden’ resource in one (or more) of your resources. In other words some of your resources are trying to do too much and their responsibilities are not clearly focused. Split the resource into two and extract the hidden responsibility and you will eliminate the circular dependency. By doing this you will also improve the overall design. This is the clear and propper solution as you are tackling the root cause of your circular dependency problem. If your ‘circle’ is formed by more than two resources though, it might be quite difficult to extract the hidden resource(s).

The Bootstrap is as close to the dependency injection container as you can get in Zend Framework 1. Initializing another resource from a resource method is akin to the constructor injection. Spliting the resource is thus similar to the solution Miško Hevery suggests for circular dependency between objects in his blog post Circular Dependency in constructors and Dependency Injection. Although it is based on Java you will find more details about this approach there and it is definitely worth reading.

Use ‘setter injection’

Do not initialize one of your resources completely in the relevant resource method, leaving out the dependency forming the circle. You will get a partialy initialized resource but you will be able to use it as a dependency in another resource. You will finish the initialization of the partialy initialized resource later (e.g. in a new resource method), when all of the resources in the circle have been (at least partialy) initialized.

But that’s cheating! We have left the circular dependency intact! You are right. We have not eliminated the circle at all but we have built some resources in two phases instead. This is similar to setter injection. You might think this approach has a slightly fishy odour. It has. The devil is in the word ‘partialy’. Your resource method produced an incomplete or not functioning resource. The resource will be ok only after the second phase of its initialization. What if anyone uses the resource in the critical time space after it has been created but before it has been completely initialized? It is up to you to secure this hole and not enable usage of the partialy initialized resource. As we are talking Zend Framework 1 Bootstrap, it should not be too difficult.

Back to the tool

The resource logging tool is very simple. It just keeps track of the number of initialized resources and indentation level corresponding to the hierarchy structure of the resource dependencies and prints the correctly indented resource name together with its number to the screen. There is only one thing you should be aware of: The log contains only resources being actually initialized (not merely used). If resource A calls bootstrap('b') but the resource B has already been initialized, it will not be logged.

The good and the bad

This resource logging tool is very simple to implement and use. Just base your Bootstrap class on our modified base class and keep the logging switched off. If you ever get the 'Circular resource dependency detected' error, flip the switch (the $_logging property) and you instantly see the troublemakers.

You might not like the crude screen logging. Of course there are better ways to output diagnostic information (Zend_Log and namely Zend_Log_Writer_Firebug), but remember, we are dealing with Bootstrap and we likely do not have any more sophisticated resources available yet. You might also ask about the performance impact with the logging switched off. I consider this negligible (there are certainly other way more significant bottlenecks in the app) and do not bother to change the Bootstrap base class for production.

Summary

We have built a quick and dirty logging tool which helps in discovering dependencies between Bootstrap resources. We have also suggested possible solutions to the circular dependencies in Bootstrap.

The code mentioned in this article forms a part of my Web App Library, which can be downloaded complete with a Bootstrap example here: https://bitbucket.org/dlu/web-app-library/downloads