markusthoemmes commented on a change in pull request #2414: SPI approach for pluggable implementations URL: https://github.com/apache/incubator-openwhisk/pull/2414#discussion_r131227962
########## File path: docs/spi.md ########## @@ -0,0 +1,75 @@ +# SPI extensions in OpenWhisk + +Alternate implementations of various components follow an SPI (Service Provider Interface) pattern: +* The pluggable component is defined as an Spi trait: +```scala +import whisk.spi.Spi +trait ThisIsPluggable extends Spi { ... } +``` +* Implementations implement the Spi trait +```scala +class TheImpl extends ThisIsPluggable { ... } +class TheOtherImpl extends ThisIsPluggable { ... } +``` + +Runtime resolution of an Spi trait to a specific impl is provided by: +* SpiLoader - a utility for loading the impl of a specific Spi, using a resolver to determine the impls factory classname, and reflection to load the factory object +* SpiFactory - a way to define a factory for each impl, all of which are loaded via reflection +* application.conf - each SpiFactory is resolved to a classname based on the config key provided to SpiLoader + +A single SpiFactory per unique Spi is usable at runtime, since the key will have a single string value. + +# Example + +The process to create and use an SPI is as follows: + +## Define the Spi and impl(s) + +* create your Spi trait `YourSpi` as an extension of whisk.spi.Spi +* create your impls as classes that extend `YourSpi` + +## Define the SpiFactory to load the impl + +```scala +class YourImplFactory extends SpiFactory[YourSpi]{ + def apply(dependencies: Dependencies): { ...construct the impl...} +} +``` +for singleton behavior you can use +```scala +class YourImplFactory extends SingletonSpiFactory[YourSpi]{ + def buildInstance(dependencies: Dependencies): { ...construct the impl...} +} +``` + +## Invoke SpiLoader.instanceOf to acquire an instance of the SPI + +SpiLoader accepts a key to use for resolving which impl should be loaded. The mapping of key to classname is implemented in an instance of `whisk.spi.SpiClassResolver` +Example whisk.spi.SpiClassResolver impls are: +* whisk.spi.ClassnameResolver - classname is not interpreted by used literally from the value of the key +* whisk.spi.TypesafeConfigClassResolver - classname is looked up as a String from the provided instance of com.typesafe.config.Config (available via `ActorSystem.settings.config` within an Akka app) + +Invoke the loader using `SpiLoader.instanceOf[<the SPI interface>](<key to resolve the classname>)(<implicit resolver>)` + +The configKey indicates which config (in application.conf) is used to determine which impl is used at runtime. +```scala +val messagingProvider = SpiLoader.instanceOf[MessagingProvider]("whisk.spi.messaging.impl") Review comment: Outdated. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services