View/Hide Sitemap Inline ...

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;
  public BImpl(PicoContainer pico) { 
    a = (A) pico.getComponentOfType(A.class); 
    /* alternatively: a = (A) pico.getComponent("a"); */ 
  } 
}

The usage would probably look similar to:

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

It will work, but it is an anti-pattern.

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

Causes

What to do

The simple and elegant solution to this anti-pattern 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.

The One Major Exception

When you go to integrate all your components into a single application, SOMETHING is going to have to wire all these components together. In Pico-land, we call that the”bootstrap”script. (Script, is a loose term, it could easily be a reference to PicoContainer inside a class’ main() function.) The pattern of this code will often look like this:

public class Bootstrap {
  private PicoContainer pico = new PicoBuilder().withLifecycle().withCaching().build();
  public static void main(String[] args) { 
    Bootstrap bootstrap = new BootStap(); 
    bootstrap.start();
  }
  public void start() { 
    /* pico.addComponent(A.class), pico.addComponent(B.class) */ 
    /* etc. */ 
    pico.start(); 
    //enter some sort of event loop. 
    //Event loop broken. 
    pico.stop();
  }
  public void stop() {
    pico.stop();
    pico.dispose(); 
  } 
}

PicoContainer has a sample project called”bootstrap”that does just this sort of thing. For web applications, Pico uses a WebappContextListener to bootstrap an application-level container, and a Servlet filter to bootstrap a request-level container.