NeelZone

What's in the Zone?

The Dependency Injection Meta-Container

Posted by indroneel on April 29, 2007

Of late, the dependency injection pattern has gained prominence as a common feature provided by many object-oriented frameworks. Included in this list are new entrants like JBoss Seam and Google Guice as alternatives to the more popular Spring framework. Existing platform, such as Struts and EJB, are also making a move towards this paradigm.

The prevalence of dependency injection has resulted in certain interesting possibilities that are mostly to do with interoperability, transparency and integration across frameworks and containers. In this article we shall take a closer look at these possibilities and propose solutions for the same.

Pushing the Bounds

Dependency injection is a bounded phenomenon. Components that participate in dependency injection form a closed group. Within the group, the features of auto-wiring (and at times, declarative-wiring1) make the necessary components implicitly available to each other.

To access these components from outside the group, one must fall back to the service locator pattern. A good example is that of service beans deployed in a Spring container (the closed group) and invoked from within Struts actions2 (contextual lookup and access).

We can say that the bounds of dependency injection are always defined by the presence of service locator (anti) pattern. From an application developer’s perspective, the impact of the latter is diminished and localized to integration points between frameworks, but not completely removed.

Given the benefits, it is only natural to envisage a common dependency injection scope for components across multiple application tiers in a seamless fashion. Service lookup operations, if any, are encapsulated as part of the framework’s static structure. Application developers are exempted from writing the glue-code between frameworks in different tiers.

The Single Container Approach

In this approach, a single dependency injection container is used to manage components across multiple application tiers. A good example would be the Spring framework that provide a common environment for elements in the presentation and the business layers. Others like Apache Tapestry makes use of HiveMind as the dependency injection container for both view and domain entities.

Different tiers in a well-designed application usually have distinctly different sets of requirements with some overlap. Under this approach, the dependency injection container used must cater to the requirements for each and every tier. This results in a non-trivial container implementation (such as Spring).

Unfortunately for simpler applications, a heavy-weight framework/platform usually represent extra baggage. A good example would be a JSP/servlet-based application, deployed on top of a full-fledged J2EE application server, that makes little use of the enterprise features provided (e.g. EJB, messaging and load-balancing) other than the servlet container.

The Multi-Container Approach

In this approach, frameworks at each application tier make use of their own dependency injection container. For each such framework, integration with other containers are provided in the form of supporting modules, either as part of the standard distribution or from third-party sources. Note that these integration pieces usually encapsulate the service locator pattern and are reusable across multiple application scenarios.

Systems that make use of multiple containers include Tapestry with HiveMind (for view entities) integrated with Spring bean container (for domain entities) or a Struts 2.03 based presentation layer integrated with Spring at the business layer.

The advantages of a multi-container approach are as follows:

  1. Better separation of concerns between different layers within an application without losing out on an overall dependency injection scope.
  2. Inclusion of frameworks that are specialized for the requirements of specific application layers.
  3. The option of having lightweight frameworks in application scenarios that warrant the same.

Even with these attractive features, there are still some limitations with a multi-container approach that deserve consideration:

  1. Most frameworks make use of a third-party container to incorporate the features of dependency injection. The effectiveness of the framework under different scenarios has a dependency on the features provided by the corresponding container.
  2. The ability to mix-and-match solutions to define an enterprise technology stack is constrained by the availability and effectiveness of integration pieces between different dependency injection containers.
  3. Lightweight containers tend to become heavy over a period of time. This may become an issue with frameworks and platforms, that make use of these containers, in catering to simpler application scenarios.

Introducing Meta-Container

The concept of a meta-container derives from the advantages and limitations of a multi-container approach. Simply stated, the meta-container is an object creation factory that also populates the object-graph paths for each instance it creates. In populating this graph and from an application perspective, the meta-container makes exclusive use of the dependency injection pattern.

The meta-container is a transient entity that is created and destroyed for each transaction/operation performed and request handled. A singleton factory is used to create these container instances. Only a basic set of objects are created by the meta-container, the rest are retrieved from ancillary dependency injection containers registered with the meta-container factory.

Usage and Scope

Frameworks that wish to incorporate the features of dependency injection may consider embedding a meta-container as part of their static structure. Application-specific objects, that are deployed on top of the framework, can be instantiated using this meta-container.

It is assumed that these application-specific objects are lightweight in nature with little overheads during their creation and finalization. Features that require advanced capabilities (such as transaction management and AOP) can be implemented as components deployed on external frameworks that provide support for those capabilities. These frameworks are plugged into the meta-container factory via. the external object provider interface. The deployed components are injected, as needed, into lightweight objects created by the meta-container.

From the discussions so far, it follows that there are alternate ways of visualizing the concept of a meta-container. These include,

  • semi-finished container: absence of features to do with life-cycle maintenance of the objects created.
  • gateway/facade for multiple dependency injection containers.
  • glue-code implementation between frameworks and multiple dependency injection containers.

Advantages

Common infrastructure: Because of its extreme simplicity, the same meta-container implementation can be used to provide the features of dependency injection in multiple frameworks and platforms.

Interoperability: One of the USP of a meta-container is out-of-the-box support for multiple external containers at different application tiers. Framework developers are assured of a high degree of integration with the most popular platforms available.

Separation of concerns: The meta-container presents a common interface to multiple dependency injection containers. Integration with external platforms being taken care of, framework developers can focus on the core capabilities offered by their respective solutions.

Cross-container injection: Instances created by the meta-container can be injected with objects from multiple external containers. This also means that the same framework instance (encapsulating a meta-container) can be integrated with multiple external containers simultaneously.

Limitations

Transience: Instances created by a meta-container have an extremely short life-span. Even the meta-container is created on a per request/transaction/operation basis. In addition, features like life-cycle management and aspects are not directly available to meta-container generated instances.

Bidirectional injection: Wiring between instances created by the meta-container and external objects is unidirectional. External objects cannot have references to instances created by the meta-container. Also note that the meta-container does not provide support to directly wire components that are deployed on different external containers.

Support for existing frameworks: It is not possible to provide a pluggable integration to replace existing dependency injection engines in frameworks (such as Tapestry and Struts). Any such integration will require a significant change in the corresponding framework implementation.

Footnotes

[1] Declarations can be provided either as XML-based metadata information or as annotations (requires Java 5).

[2] Note that this is Struts 1.x, the classic version.

[3] Struts 2 internally uses Guice as the dependency injection container.

Advertisements

9 Responses to “The Dependency Injection Meta-Container”

  1. Nanik said

    Hi,

    Can you tell me what tools do you use to draw the diagram ? it looks clean and nice đŸ™‚

    Cheers

  2. indroneel said

    Microsoft Powerpoint

  3. […] The Dependency Injection Meta-Container « NeelZone Ideia legal um container genĂ©rico para DI […]

  4. manoj said

    Neel,
    Good post. But if I may ask, why would I need a meta container. in an era where POJO based programming is the paradigm of programming and the lack of good developers, do we really see a need to write a framework on top of frameworks so that multiple frameworks can be brought together.
    I wonder how a single application can try to do this with conflicting versions of jar files (framework 1 will work on JDK 1.4 but not on java 5, while framework 2 will work only on java5). I appreciate the idea, but is it of great consequence in todays “spring and POJO” world?

    Any thoughts on how easy / hard it is to maintain the meta framework across frameowrk version upgrades?

    Manoj

  5. indroneel said

    Manoj,

    Working with meta containers is not for your average programmers. Meta containers are more for people who wish to engage in framework development and would like to have a flexible integration layer with the Business tier. I would say that a meta container would find big use in developing a presentation layer that provides an extensible glue layer for multiple business layer containers.

    One of the major tenets of open-source development is freedom of choice. I am a big fan of the Spring framework. At the same time I cannot ignore the fact that there are still a lot of applications that run on top of EJB 2 and even EJB 3.

    As regards extensibility and maintainability, I have implemented one version of the meta container that integrates with Spring, HiveMind, EJB 2 and EJB 3, the only restriction is that you need Java 5 as the minimum platform.

    Neel

  6. A good post about meta containers, helps me much – thanks!

  7. Hi Neel,
    Why cant you provide a printable version?
    Regards
    PH

  8. indroneel said

    You mean like a PDF version? I can if you are interested.

  9. PDF or HTML (only the article) anything will do.
    Regards,
    PH

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: