User Documentation

One minute description
Two minute tutorial
Five minute introduction
Advanced Topics
FAQ
Container
Components
Terminology
Mock Objects
Inversion of Control Types

Patterns

Inversion of Control 
Dependency Injection 
Constructor Injection 
Setter Injection 
Interface Implementation Separation 
Lifecycle 
Antipatterns

Developer Documentation

 Current build status
How To Contribute
Relative Volunteering
Release Process

Project Information

Slogan
Mailing lists
Source Repositories
Open Issues
Blog entries 
Statistics
Team
Sister Projects
TShirts

Miscellaneous

Differentiators
Nirvana

Full Sitemap

Feeds


Site
News
Container Dependency

Symptoms

Classes that depend on the container.

Consider the following example. We have a class BImpl that requires an A instance. It declares the dependency on the container so it can look up that A:

public interface A {
}

public class AImpl implements A {
}

public class BImpl implements B {
    private final A a;

    BImpl(PicoContainer pico) {
        a = (A) pico.getComponentInstanceOfType(A.class);
        
        /*
        alternatively:
        a = (A) pico.getComponentInstance("a");
        */
    }
}

It can be used in the following way:

MutablePicoContainer pico = new DefaultPicoContainer();
pico.registerComponentImplementation("a", AImpl.class);
pico.registerComponentImplementation("b", BImpl.class);

...
B b = (B) pico.getComponentInstance("b");

This will work, but it's an antipattern.

(The PicoContainer instance is implicitly available as a "hidden" component adapter. However, it is highly


discouraged to have regular components depend on PicoContainer. The only reason why it is available implicitly


is to be able to register containers inside other containers - as this is how child containers will get the reference to their parent).

The reasons why the above implementation of BImpl is an antipattern are:

  • It introduces an unneeded dependency from BImpl to the container.
  • This makes BImpl hard to test without a container.
  • B assumes that the container has a registered an A. As a result, B won't FailFast if it hasn't. Instead, a will reference null, and BImpl will FailLate.

Causes

Not sure. Poor understanding of how PicoContainer works? Not being able to think "simple"?

What to do

The simple and elegant solution to this antipattern is not to complicate the world more than it is.


Here is how it should be:

public class BImpl implements B {
    private final A a;

    BImpl(A a) {
        this.a = a;
    }
}

PicoContainer will figure out that BImpl needs an A instance, and will pass in the AImpl, as this is an implementation of A.