Hi all guys,

I think the main idea of services binding[1] in SPI is good but still
a little far to be complete, because what they miss are *qualifiers*,
I mean, Guice allows binding the same interface/service to multiple
instances by qualifying them via annotations, i.e.

bind(CreditCardProcessor.class).annotatedWith(Names.named("Visa")).to(VisaCreditCardProcessor.class);
bind(CreditCardProcessor.class).annotatedWith(Names.named("Mastercard")).to(MastercardCreditCardProcessor.class);

So users can require service injection depending on bound metadata,
rather than requiring and explicit class implementation:

@Inject
@Named("Visa")
CreditCardProcessor creditCardProcessor;

Now, coming back to the current SPI implementation, it just allows
doing silly bindings, such as bind the service to the first discovered
implementation or getting all the discovered implementations, mainly
because META-INF/services files just enlist service implementation,
i.e.

file META-INF/services/org.acme.CreditCardProcessor
-----------------------------------------------------------------
org.acme.VisaCreditCardProcessor
org.acme.MastercardCreditCardProcessor

There are not qualifiers :( While at the time of coding the first
version of SPI it made me happy, now I am not longer satisfied.

We can do something better, my proposal is:

* allows specifying a set of metadata - please remind that qualifiers,
binding annotations, can be more complex rather than just @Named - in
META-INF/services files for each service, something like

file META-INF/services/org.acme.CreditCardProcessor
-----------------------------------------------------------------
org.acme.VisaCreditCardProcessor; type=Visa; version=1.0.0;
org.acme.MastercardCreditCardProcessor; type=Mastercard; version=1.5.0;

* defining a new binding annotation, something like:

@Documented
@Retention( RetentionPolicy.RUNTIME )
public @interface Property
{

    String name();

    String value();

    @Documented
    @BindingAnnotation
    @Retention( RetentionPolicy.RUNTIME )
    @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
    @interface List
    {
        Property[] value();
    }

}

in order users can request injections specifying injections like:

@Inject
@Property.List({
    @Property( name="type", value="Visa" ),
    @Property( name="version", value="1.0.0" )
})
CreditCardProcessor creditCardProcessor;

WDYT? Do you have any idea?
Many thanks in advance!
-Simo

[1] http://onami.incubator.apache.org/spi/services.html

http://people.apache.org/~simonetripodi/
http://simonetripodi.livejournal.com/
http://twitter.com/simonetripodi
http://www.99soft.org/

Reply via email to