Stephen McConnell wrote: > >It also allows you to specify suppliers (the answer to question 2 is > >"yes" for MicroContainer): > > > > public static Composer getInstance( Supplier supplier ) > > { > > return (Composer) new MicroContainer( ComposerImpl.class ) > > .component( Supplier.ROLE, supplier ) // Specify supplier of service. > > // (The supplier must be another proxy.) > > .sharedInstance( true ) // Handling policy > > .create(); // Create the proxy instance with a > > // contained component instance. > > } > > > >I would love to see something similar in Merlin. > > > Me too! Should this be focussed on Merlin current or Merlin II (where Merlin II can > be considered more as a general container services > framework)? My suggestion > would be to trial some things using the containerkit ResourceProvider model and sort > out what mata info needs to be declared to support the above - for example, the > sharedInstance is presumable a policy of the implementation class. I.e. where > information is specific to a component - ensure the possibility for the declaration > of this at the .xinfo level. Concerning proxies - this is also something I would like to see.
Let me explain how MicroContainer handles this now, and how I see Merlin handling it: First, what you see here is basically the instantiation of a MicroContainer *factory*. It is not until the create() method is called at the very end that the actual MicroContainer is created and returned. new MicroContainer( ComposerImpl.class ) .component( Supplier.ROLE, supplier ) .sharedInstance( true ) .create() Another way of writing it would be: MicroContainer mc = new MicroContainer( ComposerImpl.class ); // 1 mc.addComponent (Supplier.ROLE, supplier); // 2 mc.setSharedInstance (true); // 3 Composer myComponent = (Composer) mc.create(); // 4 And bang, myComponent holds a reference to a proxy containing one instance of ComposerImpl. How to integrate this with .xinfo-level metainfo? Well, I've numbered the steps above: *** First, assume that all service instances are SINGLETON (as I understand Merlin, Singleton handling policy is equivalent to ThreadSafe in ExcaliburCM) We can handle TRANSIENT and POOLED as well, but for now leave that. *** 1. At this point all we know is the component's implementing class. That's enough to grab the associated .xinfo, if any. So we grab it and store it. 2. Here the user provides a supplier for a role. Store that role->impl mapping. 3. User overrides handling policy. 4. At this point we have (a) .xinfo description providing defaults (b) user overrides. Merge those. For dependencies this means that for every dependency in the xinfo not satisfied by the user via overrides, consult the service registry. If the handler policy has not been set, use whatever is in xinfo, and if there is no xinfo, well... do something reasonable. End result: A full environment for the target component. If possible, create a proxy around the target component that holds the ComponentManager etc. for the component and that exposes all the target component's interfaces. Return that. What I'm still trying to figure out is just how the ServiceRegistry works. Does it "learn"? When I create a new instance of a Foo component, will the registry capture the creation parameters and use it to satisfy future requests for a Foo component? Now on to how to handle TRANSIENT services: The problem with transient services is that you can not give the same instance to two composers. This ceases to be a problem with proxie'd services, as you can stuff all creation parameters into the proxy and then let the proxy create a new component instance every time it is needed. A clone() method on steriods, in short. What appears as a component is actually a proxy that can work as a factory when needed. So suppose we have an instance of component A that is TRANSIENT. We have two components with dependencies on A: B and C. We can not give our only instance of A to both B and C. Solution: When overriding the role->component mapping for B and C (that is, we say "when satisfying B and C's dependency on A, use this component"), A's clone() method is called, and B and C receives a clone each of A. THis cal always be done, if the clone method is implemented so that it only actually performs a cloning if the handling policy is TRANSIENT. (This, BTW, is why the "supplier" in my MicroContainer example must be a MicroContainer: It guarantees cloneability: .component( Supplier.ROLE, supplier ) // Specify supplier of service. // The supplier must be another proxy. ) /LS -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>