Discussion:
Child Container Strategy Help
Daniel Hinojosa
2008-04-24 23:32:18 UTC
Permalink
I wish to setup a previously developed Swing app using an IoC
container and I like PicoContainer more because of the ability to use
child containers.
In most of the examples on the website though, they are simple (which
is nice). The child container is always created right after the parent
container is created. The example doesn't cover what to do in case
you wish to create a child container based off of a root container
that has been configured in another class all while keeping everything
decoupled.

I wanted my solution to be simple, so I came up with the following
code, and it works GREAT! My question is, given my code, is anything
I did here an anti-pattern or can you foresee and issues?

public class MyApplication {

public MyApplication() {
}

public static void main(String[] args) {
MutablePicoContainer pico = new DefaultPicoContainer();
pico.addComponent("rootContainer", pico);
pico.addComponent(MyChildApp.class);
pico.addComponent(MyApplication.class);

MyChildApp app = pico.getComponent(MyChildApp.class);
app.doIt();
}
}

public class MyChildApp {
private MutablePicoContainer rootContainer;

@Inject
public void setRootContainer(MutablePicoContainer rootContainer) {
this.rootContainer = rootContainer;
}

public void doIt() {
System.out.println(rootContainer);
MutablePicoContainer childContainer =
rootContainer.makeChildContainer();
childContainer.addComponent("value", 14);
childContainer.addComponent(MyGrandchildApp.class);
MyGrandchildApp myGrandchildApp =
childContainer.getComponent(MyGrandchildApp.class);
myGrandchildApp.doIt();
}
}

public class MyGrandchildApp {
private MutablePicoContainer rootContainer;
private int value;

@Inject
public void setRootContainer(MutablePicoContainer rootContainer) {
this.rootContainer = rootContainer;
}

@Inject
public void setValue(int value) {
this.value = value;
}

public void doIt() {
System.out.println("rootContainer: " + rootContainer);
System.out.println("value: " + value);
}
}



Thanks for your help,
Danno
--
Daniel Hinojosa
Programmer, Instructor, and Consultant

2529 Wisconsin St. NE
Albuquerque, NM 87110
dhinojosa-sRlC7LJHFRkitjMjQMKR8gC/***@public.gmane.org

http://www.evolutionnext.com
http://www.abqjug.org

(505) 363-5832

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Paul Hammant
2008-04-25 00:15:21 UTC
Permalink
Daniel,

The container being aware of itself is not the IoC way.
And components (other than the conceptual main() method or boot logic)
should not be aware that they are being managed by container(s).
Thus yes, its an anti pattern :-(

MutablePicoContainer has makeChildContainer() and also
addChildContainer(..) and removeChildContainer(..)

makeChildContainer() is going to create a child, the components for
which, will be able to depend on the components in the parent.

addChildContainer(..) is going to add a container as a child. if you
start() the parent, the child with be start()ed too. But by default
the childs will NOT be able to depend on the components in the
parent. UNLESS that child container was instantiated wiith the parent
passed into its constructor - meaning it would be kinda indentical to
the makeChildContainer() scenario. Well if not identical, similar as
you could have different benaviors, component-monitors etc.

Tell me more about MyChildApp and MyApplication. Do either of them
use 'rootContainer' - like call methods on it ? Are they adding more
components? Or getting some out ? Or calling start/stop ?
Is stuff happening on pico instances from the AWT thread ?

You're not unique, Jetbrains have three tiers of PicoContainer in
their IDEA product (though I do not have the details).

- Paul
Post by Daniel Hinojosa
I wish to setup a previously developed Swing app using an IoC
container and I like PicoContainer more because of the ability to use
child containers.
In most of the examples on the website though, they are simple (which
is nice). The child container is always created right after the parent
container is created. The example doesn't cover what to do in case
you wish to create a child container based off of a root container
that has been configured in another class all while keeping everything
decoupled.
I wanted my solution to be simple, so I came up with the following
code, and it works GREAT! My question is, given my code, is anything
I did here an anti-pattern or can you foresee and issues?
public class MyApplication {
public MyApplication() {
}
public static void main(String[] args) {
MutablePicoContainer pico = new DefaultPicoContainer();
pico.addComponent("rootContainer", pico);
pico.addComponent(MyChildApp.class);
pico.addComponent(MyApplication.class);
MyChildApp app = pico.getComponent(MyChildApp.class);
app.doIt();
}
}
public class MyChildApp {
private MutablePicoContainer rootContainer;
@Inject
public void setRootContainer(MutablePicoContainer rootContainer) {
this.rootContainer = rootContainer;
}
public void doIt() {
System.out.println(rootContainer);
MutablePicoContainer childContainer =
rootContainer.makeChildContainer();
childContainer.addComponent("value", 14);
childContainer.addComponent(MyGrandchildApp.class);
MyGrandchildApp myGrandchildApp =
childContainer.getComponent(MyGrandchildApp.class);
myGrandchildApp.doIt();
}
}
public class MyGrandchildApp {
private MutablePicoContainer rootContainer;
private int value;
@Inject
public void setRootContainer(MutablePicoContainer rootContainer) {
this.rootContainer = rootContainer;
}
@Inject
public void setValue(int value) {
this.value = value;
}
public void doIt() {
System.out.println("rootContainer: " + rootContainer);
System.out.println("value: " + value);
}
}
Thanks for your help,
Danno
--
Daniel Hinojosa
Programmer, Instructor, and Consultant
2529 Wisconsin St. NE
Albuquerque, NM 87110
http://www.evolutionnext.com
http://www.abqjug.org
(505) 363-5832
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Daniel Hinojosa
2008-04-25 15:54:28 UTC
Permalink
Paul Thanks for your response.
Post by Paul Hammant
Daniel,
The container being aware of itself is not the IoC way.
And components (other than the conceptual main() method or boot logic)
should not be aware that they are being managed by container(s).
Thus yes, its an anti pattern :-(
MutablePicoContainer has makeChildContainer() and also
addChildContainer(..) and removeChildContainer(..)
makeChildContainer() is going to create a child, the components for which,
will be able to depend on the components in the parent.
addChildContainer(..) is going to add a container as a child. if you
start() the parent, the child with be start()ed too. But by default the
childs will NOT be able to depend on the components in the parent. UNLESS
that child container was instantiated wiith the parent passed into its
constructor - meaning it would be kinda indentical to the
makeChildContainer() scenario. Well if not identical, similar as you could
have different benaviors, component-monitors etc.
Tell me more about MyChildApp and MyApplication. Do either of them use
'rootContainer' - like call methods on it ?
Yes. Essentially what I am looking for is many JInternalFrames that
will encompass a "document" model and allow the user to enter data to
that document model. The same model as an IDE or a word processor.
So, in detail, I have two custom scopes for my Swing application, an
application scope and an internal frame scope. Each document will
have injected into it about 50 internal frame scoped services that
handle calculations and about 5 application scoped services used for
application wide notifications. The internal frame scoped services are
unique to the document, in other words they are not shared across
documents. Therefore, one application -> many internal frames, one
internal frame -> one document, one document -> many internal frame
scoped services per document.
Post by Paul Hammant
Are they adding more components?
Yes, as you can see above.
Post by Paul Hammant
Or getting some out ?
Or calling start/stop ?
No, I have not seen the need, but could be wrong.
Post by Paul Hammant
Is stuff happening on pico instances from the AWT thread ?
I do have code that uses Swing threading utilities.
Post by Paul Hammant
You're not unique, Jetbrains have three tiers of PicoContainer in their
IDEA product (though I do not have the details)
Very interesting. Now I can provide a simple greenfield app like
multisession calculator that shows what I am looking for, and this
list can provide suggestions or ideas. If that's of interest let me
know.

Danno
Post by Paul Hammant
Post by Daniel Hinojosa
I wish to setup a previously developed Swing app using an IoC
container and I like PicoContainer more because of the ability to use
child containers.
In most of the examples on the website though, they are simple (which
is nice). The child container is always created right after the parent
container is created. The example doesn't cover what to do in case
you wish to create a child container based off of a root container
that has been configured in another class all while keeping everything
decoupled.
I wanted my solution to be simple, so I came up with the following
code, and it works GREAT! My question is, given my code, is anything
I did here an anti-pattern or can you foresee and issues?
public class MyApplication {
public MyApplication() {
}
public static void main(String[] args) {
MutablePicoContainer pico = new DefaultPicoContainer();
pico.addComponent("rootContainer", pico);
pico.addComponent(MyChildApp.class);
pico.addComponent(MyApplication.class);
MyChildApp app = pico.getComponent(MyChildApp.class);
app.doIt();
}
}
public class MyChildApp {
private MutablePicoContainer rootContainer;
@Inject
public void setRootContainer(MutablePicoContainer rootContainer) {
this.rootContainer = rootContainer;
}
public void doIt() {
System.out.println(rootContainer);
MutablePicoContainer childContainer =
rootContainer.makeChildContainer();
childContainer.addComponent("value", 14);
childContainer.addComponent(MyGrandchildApp.class);
MyGrandchildApp myGrandchildApp =
childContainer.getComponent(MyGrandchildApp.class);
myGrandchildApp.doIt();
}
}
public class MyGrandchildApp {
private MutablePicoContainer rootContainer;
private int value;
@Inject
public void setRootContainer(MutablePicoContainer rootContainer) {
this.rootContainer = rootContainer;
}
@Inject
public void setValue(int value) {
this.value = value;
}
public void doIt() {
System.out.println("rootContainer: " + rootContainer);
System.out.println("value: " + value);
}
}
Thanks for your help,
Danno
--
Daniel Hinojosa
Programmer, Instructor, and Consultant
2529 Wisconsin St. NE
Albuquerque, NM 87110
http://www.evolutionnext.com
http://www.abqjug.org
(505) 363-5832
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
--
Daniel Hinojosa
Programmer, Instructor, and Consultant

2529 Wisconsin St. NE
Albuquerque, NM 87110
dhinojosa-sRlC7LJHFRkitjMjQMKR8gC/***@public.gmane.org

http://www.evolutionnext.com
http://www.abqjug.org

(505) 363-5832

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Peter Karich
2008-04-25 20:07:26 UTC
Permalink
Hi Daniel!
Post by Daniel Hinojosa
Post by Paul Hammant
You're not unique, Jetbrains have three tiers of PicoContainer in their
IDEA product (though I do not have the details)
Very interesting. Now I can provide a simple greenfield app like
multisession calculator that shows what I am looking for, and this
list can provide suggestions or ideas. If that's of interest let me
know.
Oh, I am really interested in this code. Because I want build a swing
app with picocontainer, too. But I am a newbie on picocontainer. So it
could be possible that I couldn't provide you any helpful suggestions :-)

Regards,
Peter.


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Jörg Schaible
2008-04-25 07:02:47 UTC
Permalink
Hi Danno,

in addition what Paul said, I use normally a pattern by defining a ServiceLocator interface that allows me to access all kind of services. The class that implements the main method will implement this interface and use internally a PicoContainer hierarchy in combination with the Lifecycle more along to:

public class MyApplication {

MutablePicoContainer rootPico = new DefaultPicoContainer();
Map childPicos = new HashMap();

public MyApplication() {
rootPico.addComponent(this);
rootPico.addComponent(MyChildApp.class);
}

/** @see ServiceLocator.startGrandChild(String) */
public void startGrandChild(String value) {
MutablePicoContainer child = childPico.get(value);
if (child == null) {
child = rootPico.makeChildContainer();
child.addComponent(value);
child.addComponent(MyGrandChildApp.class);
childPicos.put(value, child);
}
if (!child.isStarted()) {
child.start();
}
/* alternative to child.start(), depends on your needs
return child.getComponent(MyGrandChildApp.class);
*/
}

// needs a corresponding stop method

void doIt() {
pico.start(); // supposes that at least one of your components uses the lifecycle
}

public static void main(String[] args) {
MyApplication app = new MyApplication();
app.doIt();
}
}


Basically this keeps any Pico-specific stuff in this single class (except the Lifecycle, but even that can be redefined for your own interfaces) and all other classes don't even know about Pico. Any component that neesd to start a new GrandChildApp will simply express the dependency to the ServiceLocator. The map with the Picos in the example above simply separates distinct "operation modes". In my real world application the "value" is a Principal (=customer) and all services that are based directly or indirectly on this specific customer and the Pico ensures to get separate instances of the services.

Note, that you can also take a different approach here. Normally the instances are cached and the pico acts like a collection of singletons. However, you can influence the cache's strategy. By default it uses an ObjectReference too keep the reference, but Pico provides also a ThreadLocalReference (see ThreadLocalized/ThreadLocalizin in pico-gems) to ensure an own instance per thread and in web applications you can keep instances in the session. You can do the same by defining an own "session" (whatever your different domains are) and ensure that way separate instances for services that are bound to such a domain.

Just to give you some options :)

- Jörg

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Daniel Hinojosa
2008-04-25 17:30:51 UTC
Permalink
On Fri, Apr 25, 2008 at 1:02 AM, Jörg Schaible
Post by Jörg Schaible
Hi Danno,
public class MyApplication {
MutablePicoContainer rootPico = new DefaultPicoContainer();
Map childPicos = new HashMap();
public MyApplication() {
rootPico.addComponent(this);
rootPico.addComponent(MyChildApp.class);
}
public void startGrandChild(String value) {
MutablePicoContainer child = childPico.get(value);
if (child == null) {
child = rootPico.makeChildContainer();
child.addComponent(value);
child.addComponent(MyGrandChildApp.class);
childPicos.put(value, child);
}
if (!child.isStarted()) {
child.start();
}
/* alternative to child.start(), depends on your needs
return child.getComponent(MyGrandChildApp.class);
*/
}
// needs a corresponding stop method
void doIt() {
pico.start(); // supposes that at least one of your components uses the lifecycle
}
public static void main(String[] args) {
MyApplication app = new MyApplication();
app.doIt();
}
}
Basically this keeps any Pico-specific stuff in this single class (except the Lifecycle, but even that can be redefined for your own interfaces) and all other classes don't even know about Pico. Any component that neesd to start a new GrandChildApp will simply express the dependency to the ServiceLocator. The map with the Picos in the example above simply separates distinct "operation modes". In my real world application the "value" is a Principal (=customer) and all services that are based directly or indirectly on this specific customer and the Pico ensures to get separate instances of the services.
Note, that you can also take a different approach here. Normally the instances are cached and the pico acts like a collection of singletons. However, you can influence the cache's strategy. By default it uses an ObjectReference too keep the reference, but Pico provides also a ThreadLocalReference (see ThreadLocalized/ThreadLocalizin in pico-gems) to ensure an own instance per thread and in web applications you can keep instances in the session. You can do the same by defining an own "session" (whatever your different domains are) and ensure that way separate instances for services that are bound to such a domain.
Just to give you some options :)
- Jörg
Wow, that's pretty nice stuff Jörg. So as long as the children are
created in one area whereas not to affect the rest of the codebase is
really what the anti-pattern is all about. I like it. Can this be
posted on website so that others can learn from this?
--
Daniel Hinojosa
Programmer, Instructor, and Consultant

2529 Wisconsin St. NE
Albuquerque, NM 87110
dhinojosa-sRlC7LJHFRkitjMjQMKR8gC/***@public.gmane.org

http://www.evolutionnext.com
http://www.abqjug.org

(505) 363-5832

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Michael Rimov
2008-04-25 23:02:16 UTC
Permalink
Jörg,

Can we abstract this code and put it into Gems? I know that it defeats the
purpose of wrapping Pico, but I think it would give people a good idea of how to
handle this problem.

-Mike (R)
-----Original Message-----
Sent: Friday, April 25, 2008 12:03 AM
Subject: RE: [picocontainer-user] Child Container Strategy Help
Hi Danno,
in addition what Paul said, I use normally a pattern by defining a
ServiceLocator interface that allows me to access all kind of services. The
class that implements the main method will implement this interface and use
internally a PicoContainer hierarchy in combination with the Lifecycle more
public class MyApplication {
MutablePicoContainer rootPico = new DefaultPicoContainer();
Map childPicos = new HashMap();
public MyApplication() {
rootPico.addComponent(this);
rootPico.addComponent(MyChildApp.class);
}
public void startGrandChild(String value) {
MutablePicoContainer child = childPico.get(value);
if (child == null) {
child = rootPico.makeChildContainer();
child.addComponent(value);
child.addComponent(MyGrandChildApp.class);
childPicos.put(value, child);
}
if (!child.isStarted()) {
child.start();
}
/* alternative to child.start(), depends on your needs
return child.getComponent(MyGrandChildApp.class);
*/
}
// needs a corresponding stop method
void doIt() {
pico.start(); // supposes that at least one of your components uses the lifecycle
}
public static void main(String[] args) {
MyApplication app = new MyApplication();
app.doIt();
}
}
Basically this keeps any Pico-specific stuff in this single class (except
the Lifecycle, but even that can be redefined for your own interfaces) and
all other classes don't even know about Pico. Any component that neesd to
start a new GrandChildApp will simply express the dependency to the
ServiceLocator. The map with the Picos in the example above simply
separates distinct "operation modes". In my real world application the
"value" is a Principal (=customer) and all services that are based directly
or indirectly on this specific customer and the Pico ensures to get
separate instances of the services.
Note, that you can also take a different approach here. Normally the
instances are cached and the pico acts like a collection of singletons.
However, you can influence the cache's strategy. By default it uses an
ObjectReference too keep the reference, but Pico provides also a
ThreadLocalReference (see ThreadLocalized/ThreadLocalizin in pico-gems) to
ensure an own instance per thread and in web applications you can keep
instances in the session. You can do the same by defining an own "session"
(whatever your different domains are) and ensure that way separate
instances for services that are bound to such a domain.
Just to give you some options :)
- Jörg
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Jörg Schaible
2008-04-28 07:35:23 UTC
Permalink
Hi Mike,
Post by Michael Rimov
Jörg,
Can we abstract this code and put it into Gems? I know that it
defeats the purpose of wrapping Pico, but I think it would give
people a good idea of how to handle this problem.
I think Paul selected the right way to code an example/demo. Every addition in this regard to gems would create an "official" API and be invasive for customer code. Therefore such an example with best practices how to use our classes in different scenarios is IMHO the better way to go.

- Jörg

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

Loading...