On 13 Dec 2005, at 16:46, Jim Marino wrote:
Thanks for the feedback James! Some comments inline...
On Dec 13, 2005, at 6:53 AM, James Strachan wrote:
BTW I really like the SCA specification, though coming from a
POJO / Spring background the distinction between @Reference and
@Property seems a little surprising at first - I just wanted to
describe my initial confusion and see if I'm on the right track to
their intended differences and how they should be used.
Can you use @Property for services and @Reference for
configuration values?
=============================================================
The specification seems to imply @Property is used to mark "a
configuration property value" and @Reference is used to inject "a
service that resolves the reference". For the moment lets ignore
the difference between property injection by value versus by
reference (we'll come on to that in a moment).
What is the real difference, from the perspective of an
application programmer - between a service and a configuration
property? It seems a fairly vague distinction - are there some
rules the application developer can know when writing a POJO on
what the difference between the two are. e.g. a JMS
ConnectionFactory and a JDBC DataSource are probably
configuration properties right?.
A service offers behavior and the reference may be decorated with
QoS. A property is just a data value that does not offer
fundamental behavior (of course a pojo data value could have some
logic on it, but generally those are component implementation types)
So a component property value is really just a primitive type then?
Or maybe something that can be coerced to/from a String? :). FWIW the
latter is the definition Spring uses - it uses the Java Beans
PropertyEditor to see if values can be read/written as strings.
The reason why we put this distinction into the spec (at one point
we had them collapsed) was the ability to specify QoS on references
as opposed to properties. If people think the distinction is more
problematic than useful then we should definitely look at removing
it. For example, one thing the distinction buys people is the
ability to specify attributes specific to references, such as the
potential autowire capability (see below). That may not be
compelling enough. Do others have opinions here?
I do, however, like the distinction in SCDL for <references> and
<properties>. We still need to distinguish between a component name
in a reference and a string data value and that seems like a nice
way to do it (it also groups stuff nicely). What do you think?
It does feel a little like different concepts are kinda being
overloaded. How properties are configured (looking values up by name
or not) seems to be quite separate to creating possibly remote
references to services which may have additional QoS.
In Spring worlds I see folks inject by value and by reference both
for primitive values and for services - they are both very useful.
e.g. I'm using DataSource here as a service; but its equally
interchangable for primitive values too...
<!-- by value -->
<bean id="foo" class="SomeService">
<property name="dataSource">
<!-- lets inject by value creating a new
implementation -->
<bean class="com.acme.MyDataSource">
<property uri="someuri"/>
</bean>
</bean>
</bean>
<!-- by reference (name) -->
<bean id="bar" class="SomeService">
<!-- the use of the @Reference could make this line
unnecessary -->
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- by reference (name) where the name comes from the @Reference
annotation -->
<bean id="another" class="SomeService">
</bean>
So am wondering if injection by value or by reference should be a
different concept to a 'possibly remote service reference with some
QoS'.
Is a "service" in this case something which is @Remotable or has
@Service? If either of those two are the case then can't the
runtime figure out the difference based on the type without the
application developer having to keep services & non-services in
sync? Is the difference between the two really just that of by-
value rather than by-reference configuration (and I was reading
too much into the description of the annotations)?
@Remotable is used to define remotable services - the default, when
no annotation is specified is local. @Service is optionally used to
define the business interface of a local service in cases where it
needs to be specified (i.e. the type may implement additional
interfaces which are not business interfaces that should be exposed
as a reference). References can be local or remote, so they can
follow by-value or by-ref semantics. I may be missing something
here since it is early so let me know.
I guess we're talking about two different things. Spring has a by-
value and by-reference configuration mechanism as I've shown above;
I'm kinda using this mental model (which I'm sure many Java
developers these days share) - and was getting confused over the
wording of the SCA spec which is why its confusing for me when you
talk about by-value or by-ref semantics of @Reference.
The use of @Reference implies that the runtime will use the name you
supply (or the property name if not) and look the service up by name
- the name of the @Reference is the name of the service to inject.
The value of this service is then injected into the property/field -
but to me its still injection by reference, since you are using a
name as an indirection. When injecting by value in Spring there is no
name - so there is no worry that your 'dataSource' property name on
service A might accidentally use the same 'dataSource' service of
another component etc. So the by-value or by-reference distinction is
quite handy.
Having said that; the @Property also has a name, so I guess @Property
is injection could be by reference as well :). With my Spring-head on
I'd kinda assumed the @Property.name was just used to rename the
field/property in XML land; not to do a reference look up in some
context. So (in a Spring sense) are both @Property and @Reference by
reference (they look up the names in a context)?
I guess I'm really just highlighting where there is a conceptual
clash with the POJO/Spring mental model and just wanted
clarification. It might be useful to map the SCA annotations to how
you may configure the POJOs in Spring (without any of the remoting
stuff to start with) and understand how the annotations map to a
Spring world to avoid confusion. e.g. a wiki page some place on 'what
SCA annotations mean in a Spring container' or something. It would be
good if Tuscany could sit on top of Spring as one possible Dependency
Injection container without folks getting horribly confused with
properties, references, services and by-value and by-reference.
i.e. there's a bunch of annotations which seem mostly to be to do
with Dependency Injection and lifecycle (@Init, @Destroy, @Property,
@Reference, @ComponentName) - it'd be interesting to see how they
could map to Spring. As an experiment I hacked up a Spring
PostProcessor to deal with most of the dependency injection
annotations in SCA...
http://svn.xbean.org/trunk/sca/src/main/java/org/xbean/sca/
ScaBeanPostProcessor.java?rev=174&view=auto
I'm keen to ensure that POJOs can work well in both environments. Of
course we could just completely ignore all the SCA annotations when
deploying a POJO inside Spring but I think it'd be good Io encourage
them to be reused in both SCA and pure Spring runtimes when they make
sense (then many more folks might use them all the time, whether
services are local or remote).
e.g. in Spring we can configure a service by name and inject it
into a beans property whether it has no annotation, @Property or
@Reference; so I'm wondering if the distinction between @Property
and @Reference makes sense WRT configuration property value versus
service - other than @Reference acts as a hint to the runtime to
auto-wire the property value by using a named reference.
In SCA these annotations are also optional so if the implementation
does not want to be aware of the distinction, it does not need to
be as long as it does not have to specify a mandatory property or
reference.
We are also looking to potentially add autowire capability (we may
need it for the Tuscany runtime for "recursive injection" where
module components or "aggregates" are assembled as pojos, which in
turn contain other components, etc. In this case we want to wire
things like a data binding component to a module component and do
it by saying something to the effect of "for this type of component
- a module component pojo - inject a component that implements this
interface". This will allow us to use SCA to "assemble" the runtime.
Related to this, we have been discussing the usefulness of
autowiring in general. A couple of very sketchy ideas we need to
flush out are:
- The ability to specify autowire in the component type reference
such as "wire a component the implements the interface specified by
the reference or implements the interface specified by the
reference and has the same name as the reference"
I've gotta say I'm a little uneasy at putting too much of this
configuration into the annotations - unless its just a hint to the
runtime - as its class level, not instance level configuration. e.g.
I may want to auto-wire 1 set of POJOs of service in one XML config,
but in the same JVM configure it quite differently (I may use the
same service class with 2 different database connections or 2
different back end services for different customer groups).
There's an interesting blog entry which describes one solution using
Spring and describes how its not necessarily ideal...
http://www.jroller.com/page/habuma/20051206
- The possibility of creating a way to describe auto-wiring, a type
of "pointcut" expression language
Yeah - the stuff in Spring 2.0-M1 is well worth a look to see how the
AOP BeanConfigurer works. I like being able to use annotations to
create pointcuts in XML-land to configure things.
I would view things like DataSources as local (i.e. by ref)
services that happen to be provided by the runtime as opposed to
properties (basically "data" used for configuration that does not
offer behavior).
Yeah - see my first part of the response in this mail - spring
developers use both kinds of injection for things like DataSources.
References tend to be used when you have many services sharing the
same thing - there's nothing particularly special about the types
involved & its typically outside of the POJO - the XML file - which
decides if its good to use a reference or not.
So at first it seems a little surprising as to why a POJO needs to
understand whether a property is set via direct property
configuration (@Property) or via looking up some named reference
(@Reference). It kinda feels wrong to make the POJO developer
choose how its going to be configured - especially when one of
SCA's goals is to hide middleware (which includes configuration).
I guess one effect of @Reference is that the container can
automatically inject the named POJO without it explicitly being
configured in some XML file. Maybe - considering Spring for a
moment here - if we don't explicitly configure a property then the
runtime would automatically inject it for us.
e.g.
public class Foo {
@Reference(name="myBar")
private Something bar;
...
}
the container would know how to inject the "bar" property by
looking up myBar - so in Spring we could just do...
<bean id="myBean" class="Foo">
<!-- runtime automatically injects "bar" property -->
</bean>
Though I guess there's nothing to stop someone reusing Foo and
explicitly configuring it in some runtime if they really want to...
<bean id="myBean" class="Foo">
<!-- lets override the name used... ->
<property name="bar" ref="aDifferentBar"/>
</bean>
I think autowire is useful in basic cases like this.
Agreed. I just wanted to highlight the need to overload/override the
automatic autowiring sometimes. i.e. annotations should often just be
a hint, the runtime may allow you to override things if necessary.
We should bring it up with the spec group.
Just out of interest; is the spec group a private separate mail list?
It might be worth using a tuscany mail list for public discussions of
the spec. I guess we could just reuse the dev list and use a [spec]
prefix on subjects so folks can filter them out if they like.
James
-------
http://radio.weblogs.com/0112098/