0

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!

G.T.D.
  • 386
  • 1
  • 5
  • 21
  • Have you checked http://picocontainer.com/caching.html ? It looks like `Basic Caching` is what you want. – user158037 Aug 16 '19 at 15:55
  • @user158037 Thanks! I have tried tinkering around with getting the cacheing to work, but it seems that it functions more like a "Singleton" lifestyle and less like a "Scope" lifestyle which is deal breaking. At any rate, PicoContainer does not seem to work as a professional level IoC container and their "documentation" is cumbersome at best. I have since transitioned to HK2 as it has much better documentation and a clearer API for features. Thanks for the idea and help though! I will leave the question up as someone else might know more or it might help future searchers. – G.T.D. Aug 19 '19 at 01:00
  • HK2 is probably not the best choice, it's actually based on Guice interfaces with very old codebase inside. But feature-wise pico can do all the same stuff. Yeah, with caching behavior you can get "singleton scope", I don't quite understand, what entity should control the other scopes you need. Anyway you're right about using child containers, it's very powerful and convenient thing, allowing to control visibility scopes, bootstrap code units with lifecycles, automatically care about object disposal etc – xeye Aug 19 '19 at 07:04
  • @xeye Just curious, why are old codebases bad? I cannot imagine there is anything inherently wrong with a good codebase that is not new (interpretable) other than it maybe does not leverage new syntax sugar. Isn't Java still using 1990's code? The JVM does most of the optimization work AFAIK. HK2 looked pretty well kept too AFAIK. Also, for Pico's child containers: I could not get them to understand that dependencies may exist in either the parents and/or children. It seems only children are aware of parents. Which seems to be a feature for isolating sub-containers from the master container. – G.T.D. Aug 19 '19 at 08:47
  • HK2 is just the particular case, its core was built to support OSGi container for glassfish and later it was augmented to provide modern DI interfaces. If you dive into its source code you would see a small hell. As for pico: If you don't need hierarchical scopes with parent-child isolation, just don't use children. Instead you can add components to the container with your own impl of ComponentAdapter that would take care of custom scopes. Also you may want to check Spring that has a more detailed custom scope API: https://www.baeldung.com/spring-custom-scope – xeye Aug 19 '19 at 09:40
  • I will have to look into that more at some point. I, generally, am not overly concerned with the source code of a library (personal pref.), but more so that it indeed works well and is easy-to-use. Though, like I said, I tinkered with Pico for quite a while and just found it frustrating with how cumbersomely documented it was and unclear how things worked. Though, I am not married to any particular library. I could easily switch to another one if something else better comes along. I did look into Spring, but it is far beyond what I need for an IoC container. Thanks for the heads-up though! :) – G.T.D. Aug 19 '19 at 12:22

0 Answers0