|
View:
New views
12 Messages
—
Rating Filter:
Alert me
|
|
|
scoped containers...Hello,
i have created a caching container for all my singletons: MutablePicoContainer cachingContainer; cachingContainer = new PicoBuilder().withCaching().build(); cachingContainer.addComponent(singletonIF1.class, singletonIF1Impl.class); ... Now i have certain components which needs "runtime arguments", like a user. At the moment i do something like this: public I getInstance(Class impl, User user) {
Parameter[] params = new Parameter[]{new ConstantParameter(user)};
MutablePicoContainer instanceContainer = new PicoBuilder(cachingContainer).build();
instanceContainer.addComponent(UserProviderIF.class, UserProvider.class, params);
instanceContainer.addComponent(impl);
return instanceContainer.getComponent(impl);
}
This is pretty annoying and costly, that i have to create a new container at each method call, because i can add Class only, when i have the user available. I could have a cache to store the container for each user, but thats overkill as well.
Is there an alternate way of doing this?
I am close to do something like that:
instanceContainer.addComponent(singletonIF1.class, singletonIF1Impl.class); instanceContainer.addComponent(UserProviderIF.class.class, ThreadLocalUserProvider.class); instanceContainer.addComponent(MyIF.class, MyIFImpl.class);On each getInstance() i will write the user into a thread local variable, which will then be read by the ThreadLocalUserProvider, when it is being instantiated. But anyhow this does not seem to be very clean. No one can assure me, that the creationg of the UserProvider instance will happen in the same thread as the caller. Does someone have another idea? Big Thanks in advance! |
|
|
Re: scoped containers...--- On Mon, 5/11/09, Olaf Krische <public@...> wrote: > From: Olaf Krische <public@...> > Subject: [picocontainer-user] scoped containers... > To: user@... > Date: Monday, May 11, 2009, 8:36 PM > Hello, > > > i have created a caching container for all my singletons: .... no objections here ;) > > Now i have certain components which needs "runtime > arguments", like a user. > At the moment i do something like this: > > public I getInstance(Class impl, User user) { > Parameter[] params = new Parameter[]{new > ConstantParameter(user)}; > MutablePicoContainer instanceContainer = new > PicoBuilder(cachingContainer).build(); > instanceContainer.addComponent(UserProviderIF.class, > UserProvider.class, > params); > instanceContainer.addComponent(impl); > return instanceContainer.getComponent(impl); > } > > > This is pretty annoying and costly, that i have to create a > new container at > each method call, because i can add Class only, when i have > the user > available. Basically you can add (register) your components, even if here no dependencies available at the moment. But they have to be present, when component is about to be instantiated / injected > I could have a cache to store the container for > each user, but > thats overkill as well. > > Is there an alternate way of doing this? Maybe hot-swapping is that what you need? http://www.picocontainer.org/hiding.html > I am close to do something like that: > > > instanceContainer.addComponent(singletonIF1.class, > singletonIF1Impl.class); > instanceContainer.addComponent(UserProviderIF.class.class, > ThreadLocalUserProvider.class); > instanceContainer.addComponent(MyIF.class, MyIFImpl.class); > > > On each getInstance() i will write the user into a thread > local variable, > which will then be read by the ThreadLocalUserProvider, > when it is being > instantiated. > > But anyhow this does not seem to be very clean. No one can > assure me, that > the creationg of the UserProvider instance will happen in > the same thread as > the caller. While puprose of pico, is [try] to avoid such clumsy constructions - so having component depending on user provider, is non-picoish way of doing this. There are also a lot of adapters / behaviours storing components in awkward places - in thread locals, JNDI, accessing comonents via JMX... Surelythere is something fo you there. regards, ----[ Konstantin Pribluda http://www.pribluda.de ]---------------- JTec quality components: http://www.pribluda.de/projects/ --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: scoped containers...Hello Konstantin, big thanks for the quick answer.
Why is it clumsy to depend on user provider? I have my reasons, why i do not use the user itself in the constructor as parameter. The "User.class" is already registered to deliver a proper User-Implementation with a completely different set of parameters. Though i get the idea, but i am not so far with rewriting the whole app yet. Ok, let me re-ask my question to a more "best practise" question. How to write this properly and not clumsy with the help of the pico container: User user = users.lookup(id); without executing: container = new Container(parentContainer); container.addComponent(User.class, UserByID.class, new Param[]{id}); container.getComponent(User.class); on each lookup with a different id? |
|
|
|
|
|
Re: scoped containers...Hello Konstantin,
But this is exactly the thing, that i wanted to avoid. I have millions of IDs. I can not add all "IDs" in advance to the child. Nor i wanna create a child, registering an ID and then asking for a component with the ID, since all the dependencies must be resolved then, which i can imagine is a kind of "expensive" operation. Hm. |
|
|
|
|
|
RE: scoped containers...> Ok, let me re-ask my question to a more "best practise" question.
> > How to write this properly and not clumsy with the help of the pico > container: > > User user = users.lookup(id); > > without executing: > > container = new Container(parentContainer); > container.addComponent(User.class, UserByID.class, new Param[]{id}); > container.getComponent(User.class); > on each lookup with a different id? To be honest? I don't think it's a particularly good use case for PicoContainer. (Not that your problem isn't a legitimate one, I just don't think Pico is too much of a help for instantiating Entities... it's better for instantiating Value Objects, Services, and Controllers). Whenever I have something along these lines, I end up creating an interface that Pico provides the instantiation for, but the implementation itself does the actual construction of the object. It's possible that this is exactly what you've been talking about, so if I'm beating a dead horse, please forgive me :) Example: public interface UserFactory { public User createUserWithId (String id); } public class DefaultUserProvider implements UserFactory { public User createUserWithId (String id) { return new DefaultUser(id); } } Then where pico becomes useful is decoupling your controllers/services from DefaultUserProvider: public class MyController { private UserFactory userProvider; public MyController(UserFactory provider) { this.userProvider = provider; } public void doSomething() { User user = userProvider.createUserById("joe"); /* do something to user object here*/ } } And it is wired together like so: MutablePicoContainer container = new PicoBuilder().withCaching().withLifecycle().build(); container.addComponent(UserFactory.class, DefaultUserProvider.class) .addComponent(MyController.class); Now, at least MyController is abstracted away from the UserProvider implementation. The user provider implementation is bound to a particular user implementation, but at least the coupling stops there. This also tends to follow Eric Evan's logic in his book "Domain Driven Designs" Entities are created by "factories", and their state is stored in "repositories". And pico doesn't really try to replace that kind of model. Otherwise, I don't think Pico is really meant to handle dynamic dependencies like what you're asking for. Is this helping? -Mike --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: scoped containers...OK, i think the crux of this rests on the "where is the User needed".
I'm going assume an 'action' for a web framework. class AddressChangeAction extends BaseAction { public void doAction { // right here User user = pico.getComponent(User.class, UserByID.class, new Param[]{id}); user.setAddressLine1(getRequest().getParam("line1"); user.setCity(getRequest().getParam("city"); user.setAZipCode(getRequest().getParam("zipcode"); // etc } } So do you? interoperate with PicoContainer in the doAction of this (admitedly crap) web framework? No. DI gives you the user. Moreover, the container is not holding all users as is, as that would be unfeasable. A Provider is the right solution for this. Your action should look like: class AddressChangeAction extends BaseAction { User user; public AddressChangeAction(User user) { this.user = user; } public void doAction { user.setAddressLine1(getRequest().getParam("line1"); user.setCity(getRequest().getParam("city"); user.setAZipCode(getRequest().getParam("zipcode"); // etc } } And you should have a Provider like so : http://svn.codehaus.org/picocontainer/java/2.x/trunk/web/examples/ajax-email/src/java/org/picocontainer/web/sample/ajaxemail/UserFromCookieProvider.java Note that it itself has dependencies. In this case a UserStore class that is, no doubt, application scoped. The user made by this provider is implicitly scoped for the session, but not actually cached as such. Its lazily made on each request by invisible invocation of this provide(..) method. The big question is then, where are you using this - a web framework ? Regards, > > Why is it clumsy to depend on user provider? I have my reasons, why > i do not > use the user itself in the constructor as parameter. The > "User.class" is > already registered to deliver a proper User-Implementation with a > completely > different set of parameters. Though i get the idea, but i am not so > far with > rewriting the whole app yet. > > Ok, let me re-ask my question to a more "best practise" question. > > How to write this properly and not clumsy with the help of the pico > container: > > User user = users.lookup(id); > > without executing: > > container = new Container(parentContainer); > container.addComponent(User.class, UserByID.class, new Param[]{id}); > container.getComponent(User.class); > > on each lookup with a different id? > > > -- > View this message in context: http://www.nabble.com/scoped-containers...-tp23488025p23489308.html > Sent from the NanoContainer - PicoContainer - Users mailing list > archive at Nabble.com. > > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: scoped containers...Hello Konstantin,
Nonetheless, i thank you for still following this. :-) Little objects like User will be instantiated: user = new UserImpl1(ID id); This will happen very often, when creating user from IDs in a file or from a request. But then again, i like to change the constructor to: user = new UserImpl2(SomeOtherClass some, ID id); Here i would like to take profit from injection. One way to do this is to create a new child container, adding either UserImpl1 or UserImpl2 with its runtime parameter, as you have shown me. This works perfectly, but is a very expensive operation compared to the little object i want to have instantiated. Another idea would be to add UserImpl to the container as well as adding a "placeholder" or "shadow parameter" ID. Then i ask the container to compile me a function for getting a component of a "UserImpl" and the function will have this "placeholder" as parameter: Maybe like this: container.addComponent(User.class, UserImpl.class, ID.class); Function<ID, User> function = container.getComponentFunction(UserImpl.class, ID.class); and then later: ID id = ...; User user = function.getComponent(id); I can re-use this function. Each time i will call getComponent(id), it will instantiate (light weight) the User. No complicated dependencies resolving is necessary anymore, since this path has been compiled already once within this function. Something like that. But you might be right also, maybe this is not, what i should do with pico container. It probably destroys as well all the neat features that can be dynamically added to the container and such. Bye! |
|
|
Re: scoped containers...Hello Paul,
Yeah, in the end there is this "HttpServletRequest" object, which has to be injected somehow, the same problem like with my ID. So if iam in a web framework, i need a container, which reads the HttpServletRequest from somewhere on "provide". At the moment i still stick to that ThreadLocal solution. Whenever i want a component with an ID as parameter, i write it into a ThreadLocal variable. The "ID provider" then reads it from this variable and provides this ID. And no, i do not depend on a web framework. i just have many "entities", as someone before named it. It can be User, Product, Picture, etc etc etc. And all those parameter can come from files, request, etc etc. |
|
|
Re: scoped containers...Olaf Krische wrote at Mittwoch, 13. Mai 2009 21:46:
> > Hello Konstantin, > > > Konstantin Priblouda wrote: >> >> Let's imagine more interesting use case: >> - I like to specify dependency on concrete user, using its ID as >> parameter and have it injected by pico container for my objects. >> >> This can be done by wrapping your user factory in pico container >> ( just interface, immutable etc - relatively easy) with simple >> functionality - if someone asks for ID, return user with id or delegate >> to parent if there is none. Then you could do like this: >> >> PicoContainer parent = new ...: >> // ... rig it up ... >> PicoContainer userContainer = new UserFactoryPicoContainer(parent); >> >> PicoContainer child = new MutablePicoContainer(userContainer) >> >> // here fun starts >> >> child.addComponent("needUserWithId239",NeedAUser.class,new Param[]{ 239 >> }); >> ... >> >> Then if you ask for "needUserWithIde239", dependeny lookup will be >> delegated to userContainer, which will provide user with correct id for >> injection. >> > > But this is exactly the thing, that i wanted to avoid. I have millions of > IDs. I can not add all "IDs" in advance to the child. Nor i wanna create a > child, registering an ID and then asking for a component with the ID, > since all the dependencies must be resolved then, which i can imagine is a > kind of "expensive" operation. In that case you can register the services depending on the user id also using a threadlocal cache instead of a standard cache. Mixing services with standard cache behaviour and threadlocal cache behaviour is completely transparent for the individual services and you can register them in the same container at once. - Jörg > > Hm. --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: scoped containers...Olaf,
Here is the smallest posible stub web-technology that uses PicoContainer and PicoContainer-Web for a DI controlled 'action' design. Of course its useless as a web technology but you could build a web framework on top of it. Three scoped components, one servlet :- http://svn.codehaus.org/picocontainer/java/2.x/trunk/web/examples/stub-webapp/src/java/org/picocontainer/web/sample/stub/ The components have no deps on anything from org.picocontainer.* itself. Regards, - Paul On May 14, 2009, at 9:38 AM, Olaf Krische wrote: > > Hello Paul, > > > Paul Hammant-3 wrote: >> >> be unfeasable. A Provider is the right solution for this. >> >> Your action should look like: >> >> class AddressChangeAction extends BaseAction { >> User user; >> public AddressChangeAction(User user) { >> this.user = user; >> } >> public void doAction { >> user.setAddressLine1(getRequest().getParam("line1"); >> user.setCity(getRequest().getParam("city"); >> user.setAZipCode(getRequest().getParam("zipcode"); // etc >> >> } >> } >> >> And you should have a Provider like so : >> http://svn.codehaus.org/picocontainer/java/2.x/trunk/web/examples/ajax-email/src/java/org/picocontainer/web/sample/ajaxemail/UserFromCookieProvider.java >> > > Yeah, in the end there is this "HttpServletRequest" object, which > has to be > injected somehow, the same problem like with my ID. So if iam in a web > framework, i need a container, which reads the HttpServletRequest from > somewhere on "provide". > > At the moment i still stick to that ThreadLocal solution. Whenever i > want a > component with an ID as parameter, i write it into a ThreadLocal > variable. > The "ID provider" then reads it from this variable and provides this > ID. > > And no, i do not depend on a web framework. i just have many > "entities", as > someone before named it. It can be User, Product, Picture, etc etc > etc. And > all those parameter can come from files, request, etc etc. > -- > View this message in context: http://www.nabble.com/scoped-containers...-tp23488025p23540796.html > Sent from the NanoContainer - PicoContainer - Users mailing list > archive at Nabble.com. > > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
| Free embeddable forum powered by Nabble | Forum Help |