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]>

Reply via email to