View/Hide Sitemap Inline ...

FAQs

Why PicoContainer 2.0?

First EJB 3.0 then Google’s Guice seemed to copy the ideas from PicoContainer. EJB 3.0 invented the annotated types of injection, but crazily omitted the Constructor Injection support, and Guice too the annotation idea and went far to further with it. Soon after Guice, even the Spring Framework team decided to do things the direct way with their ‘JavaConfig’ capability.

So PicoContainer 1.x was refactored (not rewritten) into PicoContainer 2.0. All the unit tests were kept, and exercise took hundreds of commits, but the team is pleased with the result. PicoContainer has moved into the JDK 5 era and introduced some more innovations.

Can my component use multiple constructors?

Yes.

You can code multiple constructors for a component:

class MyComp {
  private ThreadPool theThreadPool;
  public MyComp(ThreadPool threadpool) {
    theThreadPool = threadpool;
  }
  public MyComp() {
    theThreadPool = new DefaultThreadPool(); 
  } 
  // other methods. 
}

How does PicoContainer decide what constructor to use?

PicoContainer will instantiate a given component using the"greediest"satisfiable constructor. By greedy, we mean the constructor that takes the most parameters. By satisfiable, we mean constructors where all arguments can be satisfied by other registered components.

If you register a component with no satisfiable constructors, or two or more ambiguous"largest"constructors, a RuntimeException will be thrown when you ask for the component instance.

We recommend for most components, you use only one constructor, although this is by no means a requirement.

How does PicoContainer compare to EJB containers?

PicoContainer is rather different. EJB traditionally has loads of things you must extend, implement, provide and throw. EJB itself is also not an Inversion of Control (IoC) design. It is close in that components are managed by a container, but the cumbersome and static nature of the JNDI lookups ensure that it is not actually IoC. PicoContainer is not a superset of EJB though, as it provides no remoting capability out of the box.

How does PicoContainer decide what constructor to use?

PicoContainer will instantiate a given component using the"greediest"satisfiable constructor. By greedy, we mean the constructor that takes the most parameters. By satisfiable, we mean constructors where all arguments can be satisfied by other registered components.

If you register a component with no satisfiable constructors, or two or more ambiguous"largest"constructors, a RuntimeException will be thrown when you ask for the component instance.

We recommend, for the sake of predictability, that PicoContainer compatible components use only one constructor, although this is by no means a requirement.

How to use primitive types in constructors?

PicoContainer will look for the greediest constructor of your component. But if your component’s constructor depends on primitive types you may set the values explicitly.

public interface ThreadPool { 
  void setSize(int);
}
public class MyComp {
  private ThreadPool threadPool;
  public MyComp(ThreadPool pool, int size) {
    threadPool = pool; 
    threadPool.setSize(size); 
  } 
}

In this case you can set the parameters at registration time:

DefaultPicoContainer pico = new DefaultPicoContainer();
pico.addComponent(ThreadPool.class, DefaultThreadPool.class);
pico.addComponent(MyComp.class, MyComp.class, new Parameters[] { 
    new ComponentParameter(), 
    new ConstantParameter(new Integer(5)); 
}) 
MyComp myComp = pico.getInstance(MyComp.class);

Use ConstantParameter to set constant values and the ComponentParameter to let Pico resolve the dependency.

When should I use PicoContainer?

We recommend using PicoContainer when your application consists of many different components that are related to each other. Instantiating a lot of objects and lacing/connecting them in the right order can be difficult task.

Why Another IoC Framework?

After a long period of watching or participating in the development of Apache’s Avalon framework, we formed a team to start what we believed to be a far simpler IoC design. One that considered the component contract more important that the container.

When we set out to do this in 2003, there was nothing equivalent to PicoContainer (xContainer originally). XWork, that underpinned WebWork2 was a general/embeddable Setter Dependency Injection framework, but not well known. The Spring Framework started in the same timescale, and we were talking to its authors before Martin Fowlers Dependency Injection article. Later we discovered that Apache’s HiveMind also was in the same space.

Why Constructor Injection?

Constructor Injection is hard to swallow for developers who have been living with Interface Lookup (the Avalon or OSGi way) or Setter Injection for long. We think it’s like TDD. Once you get the grasp of it, you don’t go back. Here are some benefits of Constructor Injection:

Will we support Guice’s @Inject annotation transparently?

We could compile PicoContainer against Guice.jar and leverage the @Inject method with a new InjectionFactory (and probably will). The problem is that there is no easy way to use an annotation without having its class in the classpath. There’s no easy ‘transparent’ solution for this.

Things fail silently if the jar is missing, unless the annotation is used – then it fails noisily. Meaning, the mere declaration of an annotation on a component is not enough to cause a ClassNotFoundException on load, if its not used:

@Retention(RetentionPolicy.RUNTIME) 
@Target(value={ElementType.METHOD}) 
public static @interface Bar { } 
... 
import com.google.inject.Inject;
public class Foo { 
  @Inject @Bar 
  public void setFoo(String str) { 
    System.out.println("setFoo:" + str);
  }
  public static void main(String[] args) throws NoSuchMethodException { 
    Foo foo = new Foo();
    foo.setFoo("hello"); 
    Method m = Foo.class.getMethod("setFoo", String.class);
    Annotation[] anns = m.getDeclaredAnnotations(); 
    System.out.println("Num annotations: " + anns.length);
    for (int i = 0; i<anns.length; i++) { 
	  Annotation ann = anns[i]; System.out.println("Annotation: " + ann.toString()); 
	} 
	Annotation ann = m.getAnnotation(Inject.class); 
	System.out.println("InjectAnnotation: " + ann); 
  } 
}

Leaving Guice out of the classpath, and trying to launch Foo like so:

commandline: java -cp classes Foo  
setFoo:>hello  
Num annotations: 1  
Annotation: @Foo$Bar()  
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/inject/Inject  
        at Foo.main(Foo.java:32)

The class loads, but the @Inject annotation is not present in the set of declared annotations, but another in the classpath is. Lastly when accessed explicitly, there is an exception thrown. Contrast to, the same run with Guice in the classpath:

setFoo:hello  
Num annotations: 2  
Annotation: @org.picocontainer.annotations.Inject()  
Annotation: @Foo$Bar()  
InjectAnnotation: @org.picocontainer.annotations.Inject()