Reputation: 396
I am coming from .NET land and am doing some Java projects recently (converting parts of a .NET codebase to Java). Normally I use .NET along with Castle Windsor as my IoC container of choice and am very familiar with it. I am using the PicoContainer IoC container for a Java project and I am trying to figure out how to inject a scoped dependency into the container. By "scoped dependency", I mean a dependency whereby the result is the exact same object each time the dependency is resolved from the container for as long as the "scope" of the container is open.
In .NET land, using an IoC container such as Castle Windsor, it was trivial to register a component with a certain life cycle (Singleton, Transient, Scoped, etc.). For example, the following C# works perfectly as expected.
// C# CODE //
IWindsorContainer container = new WindsorContainer();
container.Register(Component
.For<Foo>()
.ImplementedBy<FooImpl>()
.LifestyleScoped()
);
using (container.RequireScope())
{
Foo foo1 = container.Resolve<Foo>();
Foo foo2 = container.Resolve<Foo>();
Console.WriteLine(foo1 == foo2); // Will print true
Console.WriteLine(foo1.Equals(foo2)); // Will print true
}
public interface Foo
{
}
public class FooImpl : Foo
{
}
However, in Java land, using an IoC container like PicoContainer, it appears there is not a way to implement such behavior which I find rather odd.
// JAVA CODE //
PicoContainer container = new DefaultPicoContainer();
container.addComponent(FooImpl.class);
// FooImpl implements an interface called "Foo" (for clarity & brevity)
Foo foo1 = container.getComponent(Foo.class);
Foo foo2 = container.getComponent(Foo.class);
// How to "scope" PicoContainer"?
// It appears the default behavior of DefaultPicoContainer is "scoped"...
// I could not find any documentation clarifying one way or another though
System.out.println(foo1 == foo2); // Should print true (most likely), for reference equality, but it does not.
System.out.println(foo1.equals(foo2)); // Should print true, for object equality, but it does not.
public interface Foo
{
}
public class FooImpl extends Foo
{
}
I am sure it must have a feature like this as I cannot imagine someone using an IoC container and wanting every single dependency to be either transient or a singleton only.
Now, before posting this question, I did thoroughly consult the documentation at the following links as well as Google for solutions, but nothing seemed to be helpful:
http://picocontainer.com/lifecycle.html http://picocontainer.com/javadoc/core/org/picocontainer/DefaultPicoContainer.html http://picocontainer.com/javadoc/core/org/picocontainer/lifecycle/DefaultLifecycleState.html
It appears there is no such lifestyle (or associated API) option to allow for scoped dependencies in PicoContainer. Some ideas I can think of to solve the problem are either a temporary container (or child container of a master container) that holds "temporary singletons" that act like scoped dependencies and once the calling code finishes with the child container it will call some kind of "dispose" method on the child container holding the "temporary singletons" and flush them all out. However, this seems inelegant and rather "hacky" as far as I can see.
The other solution may reside in the "start" and "stop" API's of PicoContainer, but these do not make sense to me as I do not understand the idea of an IoC container "starting" and "stopping" but rather just "existing" (or not). Also, the documentation is unclear if the various dependencies would need to implement such methods/API's. That sort of use case seems ... unintuitive? Or rather like we are encouraging coupling and leaking abstractions/NFC's into dependencies. I doubt this is what those API's are intended for, so I may be on the wrong track here.
P.S. I am not "married" to the idea using PicoContainer as the IoC container of choice for this project. I am open to other options if they can achieve IoC container functionality. I did some light initial investigation of "Guice" but it seemed to not be a "Container" in the traditional IoC container sense but rather a library with a limited injector and depends completely on annotations for dependency resolution. I am looking for something closer to what one would expect with a traditional IoC container such as Castle Windsor for example.
Thanks for any insight or assistance!
Upvotes: 0
Views: 380