On 04/08/2010 03:42 PM, Vincent Massol wrote:
On Apr 8, 2010, at 3:17 PM, Sergiu Dumitriu wrote:
On 04/08/2010 02:21 PM, Vincent Massol wrote:
Hi devs,
Since the JSR330 is now accepted as final and thus as a standard, I'd like to propose
that we modify our component annotations to use it.
+1
Rationale
========
The advantages of using it are:
* Be standard, ie:
** Our components will be able to be re-used by injectors other than ours (Guice for
example)
** Since IDEs will support JSR330 they'll be able to offer features for our code
(auto complete, graph, etc), for ex
http://blogs.jetbrains.com/idea/tag/dependency-injection/
Proposed Changes
===============
Note: JSR330 doesn't specify how components should be bound, hence the need to keep
xwiki-specific metadata for the bindings.
* @Component and @ComponentRole stay unchanged
Except that the package changes, right?
Nope, we keep our annotations for the bindings part since it's not part of the JSR330
spec.
OK, I see, so there's no specification JAR to use, this is just a naming
convention.
There's a JAR to use (javax.inject.jar) but it contains only the JSR330 classes
defined here:
>>> * Deprecate @Requirement, replaced by
@Inject
>>> * Use @Named or application-specific annotations (based on @Qualifier)
instead of hints specified in the @Requirement annotation
>>> * Add new @Role(Class) to specify a dependency role in the case of
collections (since generics are not available using reflection in Java)
>>
>> @Role will kind of break the "be standard, so supported by other
>> injectors" motivation. Are you sure there's no way for doing this?
Maybe
>> we should have commented during the standardization process.
>
> Not really, binding is out of scope for JSR330. Here's what they say:
>
> "
> This package provides dependency injection annotations that enable portable classes,
but it leaves external dependency configuration up to the injector implementation.
Programmers annotate constructors, methods, and fields to advertise their injectability
(constructor injection is demonstrated in the examples above). A dependency injector
identifies a class's dependencies by inspecting these annotations, and injects the
dependencies at run time. Moreover, the injector can verify that all dependencies have
been satisfied atbuild time. A service locator, by contrast, cannot detect unsatisfied
dependencies until run time.
>
> Injector implementations can take many forms. An injector could configure itself
using XML, annotations, a DSL (domain-specific language), or even plain Java code. An
injector could rely on reflection or code generation. An injector that uses compile-time
code generation may not even have its own run time representation. Other injectors may not
be able to generate code at all, neither at compile nor run time. A "container",
for some definition, can be an injector, but this package specification aims to minimize
restrictions on injector implementations.
> "
>
>>> * Deprecate @InstantiationStrategy, replaced by @Singleton. We don't need
to introduce any other scope annotations for now.
>>> * Note that the default scope in the JSR330 spec is "per lookup".
Since our default is singleton, we'll need to add @Singleton annotations everywhere we
used to not have anything.
>>
>> This (@Singleton everywhere) is the biggest inconvenience, but we'll manage.
>
> Yep it'll be a pain.
>
>> We also need to update the component tutorial.
>
> Yes, and the Module doc too.
>
>>> Example before:
>>>
>>> @Component("html")
>>> public class HTMLMacro extends AbstractMacro<HTMLMacroParameters>
>>> {
>>> ...
>>> @Requirement
>>> private HTMLCleaner htmlCleaner;
>>> ...
>>> @Requirement("xhtmlmacro/1.0")
>>> private PrintRendererFactory xhtmlRendererFactory;
>>> ...
>>>
>>
>> @Requirement(role = Transformation.class)
>> private List<Transformation> transformations = new
>> ArrayList<Transformation>();
>>
>>> Same example after the change:
>>>
>>> @Component("html")
>>> public class HTMLMacro extends AbstractMacro<HTMLMacroParameters>
>>> {
>>> ...
>>> @Inject
>>> private HTMLCleaner htmlCleaner;
>>> ...
>>> @Inject
>>> @Named("xhtmlmacro/1.0")
>>> private PrintRendererFactory xhtmlRendererFactory;
>>> ...
>>
>> @Inject
>> @Role(Transformation.class)
>> private List<Transformation> transformations = new
>> ArrayList<Transformation>();
>>
>> Right?
>
> yes (same for Maps).
>
> For the record, note that in Guice the binding is done like this:
> bind(new TypeLiteral<Map<GeneticOperator, Double>>() {}).to(...);
> See also
http://code.google.com/p/google-guice/source/browse/trunk/src/com/google/in…
>
> Thanks
> -Vincent