2016/02/07 - Apache Onami has been retired.

For more information, please explore the Attic.

Binding Services

The org.apache.onami.spi.ServiceLoaderModule provides APIs to bind Services to Provided discovered via SPI pattern.

Given an hypothetical CreditCardProcessor:

package com.acme;

public interface CreditCardProcessor
{

    void doSomething();

}

With related implementations:

package com.acme.first;

@javax.inject.Named( "Visa" ) // any @javax.inject.Qualifier or @com.google.inject.BindingAnnotation annotated annotation
public final class VisaCreditCardProcessor
    implements CreditCardProcessor
{

    public void doSomething()
    {
        // ...
    }

}

and

package com.acme.second;

@javax.inject.Named( "MasterCard" ) // any @javax.inject.Qualifier or @com.google.inject.BindingAnnotation annotated annotation
public final class MasterCardCreditCardProcessor
    implements CreditCardProcessor
{

    public void doSomething()
    {
        // ...
    }

}

Then define the SPI in META-INF/services/com.acme.CreditCardProcessor file(s):

# created by Jack Bauer in less than 24h

com.acme.first.VisaCreditCardProcessor
com.acme.second.MasterCardCreditCardProcessor   # EOL comment

# comments and blank lines supported


#

Then users can require Services binding discovering implementation(s) with the service loader:

import static com.google.inject.Guice.createInjector;

import com.acme.FooService;
import com.google.inject.Injector;

import org.apache.onami.spi.ServiceLoaderModule;

...

Injector injector = createInjector( new ServiceLoaderModule()
{

    @Override
    protected void configureServices()
    {
        discover( CreditCardProcessor.class ); //.fromClassLoader( ClassLoader classLoader );
    }

} );

and the require injections somewhere else:

public class PowerTool
{

    @Inject
    @javax.inject.Named( "MasterCard" )
    private CreditCardProcessor creditCardProcessor;

    // setters and algorithms omitted

}

if a service is not annotated by a qualifier/binding annotation, i.e.

package com.acme;

public final class DefaultCreditCardProcessor
    implements CreditCardProcessor
{

    public void doSomething()
    {
        // ...
    }

}

Then defined the SPI in META-INF/services/com.acme.CreditCardProcessor file:

# created by Jack Bauer in less than 24h

com.acme.DefaultCreditCardProcessor

it is enough requiring its injection:

public class PowerTool
{

    @Inject
    // this is bound to com.acme.DefaultCreditCardProcessor
    private CreditCardProcessor creditCardProcessor;

    // setters and algorithms omitted

}

Qualifier annotations

Services implementations can be annotated with whatever annotation which, at their time, are annotated with a @javax.inject.Qualifier or @com.google.inject.BindingAnnotation annotation; i.e. given the following annotations:

@com.google.inject.BindingAnnotation
@Retention( RUNTIME )
@Target( { FIELD, TYPE } )
public @interface Visa
{}

and

@com.google.inject.BindingAnnotation
@Retention( RUNTIME )
@Target( { FIELD, TYPE } )
public @interface MasterCard
{}

users can annotate services implementations:

package com.acme.first;

@Visa
public final class VisaCreditCardProcessorImpl
    implements CreditCardProcessor
{

    public void doSomething()
    {
        // ...
    }

}

and

package com.acme.second;

@MasterCard
public final class MasterCardCreditCardProcessorImpl
    implements CreditCardProcessor
{

    public void doSomething()
    {
        // ...
    }

}

Then define the SPI in META-INF/services/com.acme.CreditCardProcessor file(s):

# created by Jack Bauer in less than 24h

com.acme.first.VisaCreditCardProcessorImpl
com.acme.second.MasterCardCreditCardProcessorImpl

Injections can be required by qualifying the injections:

public class PowerTool
{

    @Inject
    @Visa
    private CreditCardProcessor creditCardProcessor;

    @Inject
    @MasterCard
    private CreditCardProcessor creditCardProcessor;

    // setters and algorithms omitted

}

Loading Services from SystemProperties

Alternatively, SPIs can be specified via Java System properties:

java -Dcom.acme.CreditCardProcessor=com.acme.first.VisaCreditCardProcessorImpl,com.acme.second.MasterCardCreditCardProcessorImpl

Where , is the separator character between Providers.

Note

If SPIs will be found in Java System properties, META-INF/services/com.acme.FooService file(s) will be ignored

Apache Maven Users

Just add the dependency below and let Maven do the rest:

<dependency>
  <groupId>org.apache.onami.spi</groupId>
  <artifactId>org.apache.onami.spi.services</artifactId>
  <version>1.0.1-SNAPSHOT</version>
  <scope>compile</scope>
</dependency>