You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@hivemind.apache.org by Knut Wannheden <kn...@gmail.com> on 2004/11/08 12:52:15 UTC
ioc type-3 autowiring support
Hi all,
Recently the topic of supporting autowiring of constructor parameters
(IoC type 3) has come up a few times. I've taken a stab at
implementing this in the BuilderFactory and it turns out to be rather
easy. A few considerations and notes:
- The constructor autowiring would only kick in if there are no
explicitly declared constructor parameters. Otherwise it could both
prove complex to implement _and_ use.
- All the constructor parameters have to be declared as interfaces.
- If there are multiple constructors present BuilderFactory would
chose the one with the highest number of parameters (greedy).
Does this sound reasonable? I still have a few open issues I'd like to discuss:
- Should there be an attribute on <construct> to explicitly enable or
disable this constructor autowiring (e.g. "autowire-constructor")?
IMO the BuilderFactory should be default autowire the constructor if
there are no declared constructor parameters. This should work well
for both the setter based _and_ constructor based dependency injection
camps.
- Should BuilderFactory report an error if there are multiple
constructors which seem equally adequate (same number of parameters
and a matching service for each)?
--knut
---------------------------------------------------------------------
To unsubscribe, e-mail: hivemind-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: hivemind-dev-help@jakarta.apache.org
Re: ioc type-3 autowiring support
Posted by Howard Lewis Ship <hl...@gmail.com>.
I like where you are heading with this; I think HiveMind's constructor
injection support is somewhat weak and doesn't have to be. I agree
that th ebest solution is to throw out any ambiguous constructors, and
start with the longest constructor ... but I think if that prooves
difficult, you should down the list until some match is found.
On Mon, 8 Nov 2004 14:32:05 +0100, Knut Wannheden
<kn...@gmail.com> wrote:
> On Mon, 08 Nov 2004 13:55:26 +0100, Achim Huegen <ah...@gmx-topmail.de> wrote:
>
>
> > Knut Wannheden wrote:
> > > ..
> > > - Should there be an attribute on <construct> to explicitly enable or
> > > disable this constructor autowiring (e.g. "autowire-constructor")?
> > > IMO the BuilderFactory should be default autowire the constructor if
> > > there are no declared constructor parameters. This should work well
> > > for both the setter based _and_ constructor based dependency injection
> > > camps.
> >
> > I can imagine services where it is possible to use both constructor
> > parameters and setters for configuration. To prevent double wiring it
> > would be nice to switch off one type of autowiring. How about extending
> > the autowire-services attribute to support yes/no/constructor/setter ?
> >
>
> I can see that one would use constructor based injection to autowire
> services and setter based injection for configurations, but in which
> cases would one provide both constructor based and setter bases
> injection for the same dependency? Can you provide an example? And
> is there even a problem with double wiring?
>
> > > - Should BuilderFactory report an error if there are multiple
> > > constructors which seem equally adequate (same number of parameters
> > > and a matching service for each)?
> > >
> >
> > Probably these constructors have never been designed for autowiring.
> > So I would log a warning only.
> >
>
> For constructor autowiring the BuilderFactory would only consider
> those constructors where all parameters' types are interfaces
> (including the common ClassResolver, ErrorHandler, ErrorLog, Log, and
> Messages interfaces) or maybe String for injecting the service id.
> Based on this there are a number of situations to deal with:
>
> - should the set of considered constructors be pruned by rejecting
> constructors declaring multiple parameters of same type?
> - what if there are multiple considered constructors with an equal
> number of (but different) parameters?
> - what if there is no service implementing the interface declared by a
> constructor parameter? is this a constructor which wasn't designed for
> constructor injection?
> - what if there are multiple service implementations for a parameter
> of the constructor?
>
> Hmm...
>
> --knut
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: hivemind-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: hivemind-dev-help@jakarta.apache.org
>
>
--
Howard M. Lewis Ship
Independent J2EE / Open-Source Java Consultant
Creator, Jakarta Tapestry
Creator, Jakarta HiveMind
http://howardlewisship.com
---------------------------------------------------------------------
To unsubscribe, e-mail: hivemind-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: hivemind-dev-help@jakarta.apache.org
Re: ioc type-3 autowiring support
Posted by Knut Wannheden <kn...@gmail.com>.
On Mon, 08 Nov 2004 13:55:26 +0100, Achim Huegen <ah...@gmx-topmail.de> wrote:
> Knut Wannheden wrote:
> > ..
> > - Should there be an attribute on <construct> to explicitly enable or
> > disable this constructor autowiring (e.g. "autowire-constructor")?
> > IMO the BuilderFactory should be default autowire the constructor if
> > there are no declared constructor parameters. This should work well
> > for both the setter based _and_ constructor based dependency injection
> > camps.
>
> I can imagine services where it is possible to use both constructor
> parameters and setters for configuration. To prevent double wiring it
> would be nice to switch off one type of autowiring. How about extending
> the autowire-services attribute to support yes/no/constructor/setter ?
>
I can see that one would use constructor based injection to autowire
services and setter based injection for configurations, but in which
cases would one provide both constructor based and setter bases
injection for the same dependency? Can you provide an example? And
is there even a problem with double wiring?
> > - Should BuilderFactory report an error if there are multiple
> > constructors which seem equally adequate (same number of parameters
> > and a matching service for each)?
> >
>
> Probably these constructors have never been designed for autowiring.
> So I would log a warning only.
>
For constructor autowiring the BuilderFactory would only consider
those constructors where all parameters' types are interfaces
(including the common ClassResolver, ErrorHandler, ErrorLog, Log, and
Messages interfaces) or maybe String for injecting the service id.
Based on this there are a number of situations to deal with:
- should the set of considered constructors be pruned by rejecting
constructors declaring multiple parameters of same type?
- what if there are multiple considered constructors with an equal
number of (but different) parameters?
- what if there is no service implementing the interface declared by a
constructor parameter? is this a constructor which wasn't designed for
constructor injection?
- what if there are multiple service implementations for a parameter
of the constructor?
Hmm...
--knut
---------------------------------------------------------------------
To unsubscribe, e-mail: hivemind-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: hivemind-dev-help@jakarta.apache.org
Re: ioc type-3 autowiring support
Posted by Achim Huegen <ah...@gmx-topmail.de>.
Knut Wannheden wrote:
> Hi all,
> ..
> - Should there be an attribute on <construct> to explicitly enable or
> disable this constructor autowiring (e.g. "autowire-constructor")?
> IMO the BuilderFactory should be default autowire the constructor if
> there are no declared constructor parameters. This should work well
> for both the setter based _and_ constructor based dependency injection
> camps.
I can imagine services where it is possible to use both constructor
parameters and setters for configuration. To prevent double wiring it
would be nice to switch off one type of autowiring. How about extending
the autowire-services attribute to support yes/no/constructor/setter ?
> - Should BuilderFactory report an error if there are multiple
> constructors which seem equally adequate (same number of parameters
> and a matching service for each)?
>
Probably these constructors have never been designed for autowiring.
So I would log a warning only.
Achim Huegen
---------------------------------------------------------------------
To unsubscribe, e-mail: hivemind-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: hivemind-dev-help@jakarta.apache.org
Re: ioc type-3 autowiring support
Posted by Knut Wannheden <kn...@gmail.com>.
IMHO the approach you mention sounds a little bit to complicated...
I'll already have problems writing a simple documentation for the
current implementation. As I mentioned the setter based injection
will also take care of it automatically.
But as there are many other opportunities for improvement (e.g.
suggested <default/> element, guard against double service injection)
I think we can keep it in mind for later.
--knut
On Mon, 8 Nov 2004 13:27:55 -0300, Marcus Brito <mb...@gmail.com> wrote:
> Yes, sounds reasonable. At first I was baffled by the "throw an error
> if no constructor match" part, but then I realized it does makes
> sense: this will occur only if the class doesn't have a constructor we
> can satisfy, not even a default constructor.
>
> What about the service ID autowiring? Drop it completly? I still think
> that the approach I mentioned in my previous message is valid (try to
> match it only if we couldn't find a matching constructor without it).
>
>
>
> -- Marcus Brito <mb...@gmail.com>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: hivemind-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: hivemind-dev-help@jakarta.apache.org
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: hivemind-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: hivemind-dev-help@jakarta.apache.org
Re: ioc type-3 autowiring support
Posted by Marcus Brito <mb...@gmail.com>.
Yes, sounds reasonable. At first I was baffled by the "throw an error
if no constructor match" part, but then I realized it does makes
sense: this will occur only if the class doesn't have a constructor we
can satisfy, not even a default constructor.
What about the service ID autowiring? Drop it completly? I still think
that the approach I mentioned in my previous message is valid (try to
match it only if we couldn't find a matching constructor without it).
-- Marcus Brito <mb...@gmail.com>
---------------------------------------------------------------------
To unsubscribe, e-mail: hivemind-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: hivemind-dev-help@jakarta.apache.org
Re: ioc type-3 autowiring support
Posted by Knut Wannheden <kn...@gmail.com>.
Hi all,
I've now committed the constructor based autowiring in BuilderFactory
as I previously described it. Go ahead and give it a try if you like.
Updating the BuilderFactory documentation was by far the hardest part
and I'm still not a 100% satisfied with it. Improvement suggestions
are most welcome!
Cheers,
--knut
On Mon, 8 Nov 2004 15:08:49 +0100, Knut Wannheden
<kn...@gmail.com> wrote:
> Agreed, String is probably to common to be used for autowiring. There
> is after all still the possibility to declare a setter for a
> "serviceId" property which will be autowired.
>
> A detailed outline of the constructor autowiring strategy (which will
> be employed iff "autowire-services" is "true" _and_ there are no
> specified constructor parameters):
>
> 1. Gather all constructors which should be considered for autowiring.
> This includes all constructors where all parameter types are
> interfaces and none of the parameter types appears more than once.
> Note that this also includes the default constructor.
> 2. Order the considered constructors by length (given by number of parameters).
> 3. Iterate through the ordered list of constructors
> 3.1 Match common parameter types (excluding String) as with current
> autowiring and interfaces with registered service implementation.
> a) For one or more service parameters there is no registered
> implementation: Ignore silently and try next constructor (3).
> b) For one or more service parameters there is more than one
> registered service implementation: Log a warning and try next
> constructor (3).
> c) All parameters can be matched: Break (4).
> 4. Instantiate implementation using found constructor. Throw
> ApplicationRuntimeException if this fails or no constructor was found.
>
> Sounds reasonable?
>
> Note that setter based injection will occur regardless of whether
> constructor based injection was employed or not. It solely depends on
> the "autowire-services" property.
>
> --knut
>
---------------------------------------------------------------------
To unsubscribe, e-mail: hivemind-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: hivemind-dev-help@jakarta.apache.org
Re: ioc type-3 autowiring support
Posted by Knut Wannheden <kn...@gmail.com>.
Agreed, String is probably to common to be used for autowiring. There
is after all still the possibility to declare a setter for a
"serviceId" property which will be autowired.
A detailed outline of the constructor autowiring strategy (which will
be employed iff "autowire-services" is "true" _and_ there are no
specified constructor parameters):
1. Gather all constructors which should be considered for autowiring.
This includes all constructors where all parameter types are
interfaces and none of the parameter types appears more than once.
Note that this also includes the default constructor.
2. Order the considered constructors by length (given by number of parameters).
3. Iterate through the ordered list of constructors
3.1 Match common parameter types (excluding String) as with current
autowiring and interfaces with registered service implementation.
a) For one or more service parameters there is no registered
implementation: Ignore silently and try next constructor (3).
b) For one or more service parameters there is more than one
registered service implementation: Log a warning and try next
constructor (3).
c) All parameters can be matched: Break (4).
4. Instantiate implementation using found constructor. Throw
ApplicationRuntimeException if this fails or no constructor was found.
Sounds reasonable?
Note that setter based injection will occur regardless of whether
constructor based injection was employed or not. It solely depends on
the "autowire-services" property.
--knut
On Mon, 8 Nov 2004 10:26:42 -0300, Marcus Brito <mb...@gmail.com> wrote:
> > Also for constructor autowiring I think that BuilderFactory should
> > wire parameters of type ClassResolver, ErrorHandler, ErrorLog, Log,
> > and Messages automatically as with the setter based injection. The
> > difference being that with constructor based injection there is no
> > name to these properties. I think maybe it should even inject the
> > service id if there is a String parameter.
>
> Agreed about the common interfaces autowiring, but I'm not so sure
> about wiring the service ID if there's a string parameter. At least,
> we should not treat it in the same way as the other properties.
>
> I can think of two distinct scenarios: new code and legacy code. For
> new code (where the decision to use hivemind has been taken before the
> code was written), I believe the developers will take care to write
> "compatible" constructors, and autowiring the service ID is handy
> here.
>
> For legacy code, this may be a bit too much -- String is a way too
> common class for us to assume that this will be the service ID. I
> would say that the service ID shouldn't be considered for constructor
> matching (i.e, the autowirer will look for the constructor without
> it), and will be wired if the only way to match a constructor is
> considering it. Something like this:
>
> BlackOperation(Assassin ocelot, Spy snake) { ... }
> BlackOperation(Assassin ocelot, Spy snake, String codeName) { ... }
>
> If there are registered Assassin and Spy services, the first
> constructor would be matched, and the service ID won't be wired. Now,
> if the only way to match a constructor is including the service
> property (let's say the first constructor didn't exist) then yes, the
> service ID will be used to match the constructor and autowired.
>
> The only gotcha is simplicity: all this constructor matching magic may
> be a bit over the top. If many people find this is the case (ah,
> feedback), I would say that the service ID shouldn't be matched at
> all.
>
> > If the user wants to call the no-arg constructor I think he will have
> > to set "autowire-services" to false. Note that if the no-arg
> > constructor is the only constructor considered for autowiring he
> > doesn't have a problem. And in the case there are others he will
> > probably disable autowiring anyways, otherwise his implementation is a
> > mix of constructor based and setter based injection.
>
> Again using the argument of legacy code, I could picture a scenario
> where the user doesn't want to autowire constructor arguments, but
> autowire properties. Anyway, I agree with you here:
> "autowire-services" should suffice to enable/disable autowiring, and
> we would be sacrificing the flexibiity to separately toggle
> constructor and property autoring for consistency and simplicity,
> which sounds like a good compromise.
>
> P.S.: sorry for replying the previous message in private. I'm starting
> to really hate this Reply-To bug in gmail/mailman.
>
> -- Marcus Brito <mb...@gmail.com>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: hivemind-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: hivemind-dev-help@jakarta.apache.org
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: hivemind-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: hivemind-dev-help@jakarta.apache.org
Re: ioc type-3 autowiring support
Posted by Marcus Brito <mb...@gmail.com>.
> Also for constructor autowiring I think that BuilderFactory should
> wire parameters of type ClassResolver, ErrorHandler, ErrorLog, Log,
> and Messages automatically as with the setter based injection. The
> difference being that with constructor based injection there is no
> name to these properties. I think maybe it should even inject the
> service id if there is a String parameter.
Agreed about the common interfaces autowiring, but I'm not so sure
about wiring the service ID if there's a string parameter. At least,
we should not treat it in the same way as the other properties.
I can think of two distinct scenarios: new code and legacy code. For
new code (where the decision to use hivemind has been taken before the
code was written), I believe the developers will take care to write
"compatible" constructors, and autowiring the service ID is handy
here.
For legacy code, this may be a bit too much -- String is a way too
common class for us to assume that this will be the service ID. I
would say that the service ID shouldn't be considered for constructor
matching (i.e, the autowirer will look for the constructor without
it), and will be wired if the only way to match a constructor is
considering it. Something like this:
BlackOperation(Assassin ocelot, Spy snake) { ... }
BlackOperation(Assassin ocelot, Spy snake, String codeName) { ... }
If there are registered Assassin and Spy services, the first
constructor would be matched, and the service ID won't be wired. Now,
if the only way to match a constructor is including the service
property (let's say the first constructor didn't exist) then yes, the
service ID will be used to match the constructor and autowired.
The only gotcha is simplicity: all this constructor matching magic may
be a bit over the top. If many people find this is the case (ah,
feedback), I would say that the service ID shouldn't be matched at
all.
> If the user wants to call the no-arg constructor I think he will have
> to set "autowire-services" to false. Note that if the no-arg
> constructor is the only constructor considered for autowiring he
> doesn't have a problem. And in the case there are others he will
> probably disable autowiring anyways, otherwise his implementation is a
> mix of constructor based and setter based injection.
Again using the argument of legacy code, I could picture a scenario
where the user doesn't want to autowire constructor arguments, but
autowire properties. Anyway, I agree with you here:
"autowire-services" should suffice to enable/disable autowiring, and
we would be sacrificing the flexibiity to separately toggle
constructor and property autoring for consistency and simplicity,
which sounds like a good compromise.
P.S.: sorry for replying the previous message in private. I'm starting
to really hate this Reply-To bug in gmail/mailman.
-- Marcus Brito <mb...@gmail.com>
---------------------------------------------------------------------
To unsubscribe, e-mail: hivemind-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: hivemind-dev-help@jakarta.apache.org
Re: ioc type-3 autowiring support
Posted by Marcus Brito <mb...@gmail.com>.
It's all about defaults. Currently Hivemind has a nice, working
implementation for autowiring properties. If we add constructor
autowiring, we might have some conflicts.
Anyway... yes, it sounds reasonable. It looks like your remarks are
right on the point: autowiring only if there are no declared
arguments, only for interfaces and trying to match as many arguments
as possible. If there are multiple choices, an error should be
reported: the user must specify the arguments -- this is inline with
the property autowiring.
About enabling/disabling autowiring, we should go the same way as
property autowiring: if the user specify any constructor arguments,
autowiring is disabled. This poses just one problem: what if the user
*wants* to call the no-arg constructor? Maybe an <empty/> or
<default/> element nested in <construct>?
-- Marcus Brito <mb...@gmail.com>
---------------------------------------------------------------------
To unsubscribe, e-mail: hivemind-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: hivemind-dev-help@jakarta.apache.org