• Home
  • RSS Feed
  • Log in


MultiSPI – consuming service provider interfaces in 2011
Posted by Andrew Phillips mid-morning: February 13th, 2011

Implementing a Java SPI isn’t a particularly 2011 experience1. Creating a correctly-named text file in META-INF/services, making sure it is correctly packaged and remembering to keep it up to date when you refactor is sufficiently annoying and error-prone that there are at least a couple of utils that aim to make this easier.

At XebiaLabs, however, we’re not just the implementors of our plugin SPI. We also write the deployment engine that consumes these plugins. And unfortunately, there isn’t much out there to help you read, load and verify services. Hence MultiSPI.

What about ServiceLoader?

Evidently, the engineers at SunOracle – as prominent SPI consumers – shared this frustration. In Java 6, they introduced ServiceLoader to at least make “vanilla” SPI consumption easier. MultiSPI isn’t just a fully-compatible alternative for those still working with Java 5, however. It also supports a number of common additional use cases:

  1. Inspecting the list of class names before they are loaded, for instance to remove or replace some items (think user-definable overrides), to use different class loaders for different packages (think OSGi) etc.
  2. Inspecting the classes before they are instantiated, for instance to check for required annotations or implemented interfaces, to delay creation of instances etc.
  3. Using non-vanilla instantiation strategies, for instance to support factory methods, or in conjunction with dependency injection etc.

Providing services in 2011

More importantly, though, MultiSPI doesn’t just support reading service implementations from META-INF/services files. Because let’s face it, if you’re designing a component-provider mechanism today, it probably won’t be based on the vanilla SPI specification.

MultiSPI supports annotation- and manifest-scanning out-of-the-box, but you can add providers for any scheme of your choice, be it XML descriptors, system properties, environment variables or whatever. Of course, you can also mix and match different providers, especially useful if (as in our case with Labs) you are supporting multiple versions of an SPI.

SPIs and dependency injection

Ultimately, of course, SPIs are just service factories, and if you’re working within a dependency injection context you probably don’t want to invoke an SPI loader explicitly, you just want the resulting services to “be available” for injection into your business logic.
Indeed, Spring added a ServiceLoader-backed factory in 2.5, and of course you can do the same with MultiSPI, whether you want the implementation class names, the classes or the instances themselves. There’s Spring and Guice examples; here’s the Spring context that prepares a set of class names, classes and instances, for example:

<bean id="multiSpi" class="com.qrmedia.commons.multispi.MultiSpi">
  <constructor-arg>
    <set>
      <bean class="com.qrmedia.commons.multispi.provider.MetaInfServicesProvider" />
      <bean class="com.qrmedia.commons.multispi.provider.AnnotationScanningProvider">
        <constructor-arg value="uk.gov.mi6.LicenseToKill" />
        <constructor-arg value="uk.gov" />
      </bean>
    </set>
  </constructor-arg>
</bean>

<bean id="agentNames" factory-bean="multiSpi" factory-method="findImplementationNames">
  <constructor-arg value="uk.gov.mi6.Agent" />
</bean>

<bean id="agentClasses" factory-bean="multiSpi" factory-method="findImplementations">
  <constructor-arg value="uk.gov.mi6.Agent" />
</bean>

<bean id="agents" factory-bean="multiSpi" factory-method="loadImplementations">
  <constructor-arg value="uk.gov.mi6.Agent" />
</bean>

Of course you can use many different MultiSpi instances, with different provider configurations, in your application at the same time.

Using MultiSPI

To use MultiSPI, just add the following dependency and repositories to your POM:

<dependency>
  <groupId>com.qrmedia.commons</groupId>
  <artifactId>multi-spi</artifactId>
  <version>1.0-SNAPSHOT</version>
</dependency> 

<repository>
  <id>qrmedia-releases</id>
  <url>http://aphillips.googlecode.com/svn/maven-repository/releases</url>
  <releases>
    <enabled>true</enabled>
  </releases>
  <snapshots>
    <enabled>false</enabled>
  </snapshots>
</repository>
<repository>
  <id>qrmedia-snapshots</id>
  <url>http://aphillips.googlecode.com/svn/maven-repository/snapshots</url>
  <releases>
    <enabled>false</enabled>
  </releases>
  <snapshots>
    <enabled>true</enabled>
  </snapshots>
</repository>

If you think you might run into conflicting dependencies and want something that just works without having to deal with <excludes>, you can use:

<dependency>
  <groupId>com.qrmedia.commons</groupId>
  <artifactId>multi-spi</artifactId>
  <version>1.0-SNAPSHOT</version>
  <classifier>jar-with-dependencies</classifier>
</dependency>

instead.

The Maven site and project reports are here.

Footnotes

  1. I’ll leave the debate about whether even writing Java can still be considered a 2011 experience to our Clojure, Scala etc. fans ;-)
Share

Tags: dependency injection, Java, spi
Filed under Java, Tools | No Comments »



No Responses to “MultiSPI – consuming service provider interfaces in 2011”



Leave a Reply

Click here to cancel reply.


Xebia Sites

  • Xebia Corporate
  • Xebia France
  • Xebia India
  • XebiCon 2012

Categories

  • Java (312)
  • Agile (192)
  • General (141)
  • Scrum (70)
  • Testing (65)
  • Architecture (65)
  • Performance (47)
  • Middleware (59)
    • Deployment (40)
  • Xebia Labs (41)
  • SOA (31)
  • Project Management (31)
  • Podcast (31)
  • Tools (28)
  • Uncategorized (24)
  • lean architecture (20)
  • Quality Assurance (19)
  • Articles (15)
  • Requirements Management (14)
  • Virtualization (21)

Tag Cloud

    lean architectuur lean architecture Agile TDD Ajax Spring Lean Eclipse Java Hibernate Flex Architecture Groovy agile architectuur Oracle SOA JPA XML product owner ACT Javascript Scala Moving to India Grails Concurrency Control Xebia Scrum JPA implementation patterns Maven Frameworks

Archives

  • May 2012
  • April 2012
  • March 2012
  • February 2012
  • January 2012
  • December 2011
  • November 2011
  • October 2011
  • September 2011
  • August 2011
  • July 2011
  • June 2011
Avatars by Sterling Adventures