proteus framework
DESCRIPTION
Proteus Framework. Redefining the plugin. Why a new framework?. Present approaches (e.g. OSGi ) use non-standard approaches that create too many breaking points Designing a plugin architecture for both scalability and supportability requires an extra level of design often overlooked - PowerPoint PPT PresentationTRANSCRIPT
S
Proteus FrameworkRedefining the plugin
Why a new framework?
Present approaches (e.g. OSGi) use non-standard approaches that create too many breaking points
Designing a plugin architecture for both scalability and supportability requires an extra level of design often overlooked
Few developers embrace the built-in plugin capabilities of the Java platform
Forward Compatibility
Definition: the ability of an SDK to ensure that plugins written in version n continue work without recompilation in version n+1
As the architect of a plugin-driven application, how do you guarantee forward compatibility when the plugin consumer has imported your interfaces into their binaries?
What’s wrong with OSGi?
In a word: nothing However, it may not be the right framework for
your application. Why pick Struts over Spring? Why use Spring over pure EJB? Advocates of each of these frameworks can quickly enumerate why they felt (or chose) one framework over the other.
One framework doesn't solve every problem
OSGi vs Proteus
Both embody the notion of SOA in a Virtual Machine Modularity is at the core of both designs Plugins (or Bundles, in OSGi parlance) are published, found by a
consumer dynamically at runtime, and bound in order to issue service invocation requests
OSGi relies on the MANIFEST.MF metadata to publish (export) its plugins (bundles)
Proteus relies on compiled code, Plugin Archetypes that define a class of service, and core Java SE’s Service Provider Interface (SPI) architecture
Runtime vs Compile Time
OSGi relies on "proprietary” MANIFEST.MF metadata to wire up services Googling shows just how hard time consuming it can be to
wire up existing libraries into OSGi Inherent class loader problems come along for free
Proteus adopts the standardized Java Service Provider Interface (SPI) architecture built-in to Java SE No wiring beyond declaring the factory in META-INF/services Not designed to solve the “2 versions of the same library”
problem
Comparing Coding Styles
OSGiString serviceName = Service.class.getName();ServiceReference ref = ctx.getServiceReference(serviceName); Service svc = (Service) ctx.getService(ref));svc.callSomeMethod();
ProteusINamespace ns = new Namespace(“com.foo”, “Bar”);IPluginRegistrar pluginRegistrar = delegate.getPluginRegistrar(ns);MyService svc = pluginRegistrar.createPlugin(new Version(1), MyService.class);svc.callSomeMethod();
Breaking Dependencies
Instead of the plugin consumer directly importing the plugins actual interface, the plugin consumer needs to import a proxy that represents a specific version of a plugin interface. Java includes native support for dynamic proxy objects!
Plugin consumer achieves compile type type checking, but they do so by compiling against a specific version of a proxy interface instead of the actual physical interface used by the actual plugin Look at the last slide again- notice the explicit version request of
a proxy interface, 1.0 of MyService.
GoF Interface Development
Develop against an interface, not an implementation
Proteus, like OSGi, forces the developer to embrace this fundamental tenant of object oriented development
Plugin Archetype is a physical construct that drives interface over implementation development at the plugin level Comprised of a namespace and a set of versioned interfaces Typically deployed in a single .jar file Plugin Archetype = Category of Plugin
Versions: First Class Citizens
Semantic Versioning http://semver.org Major.Minor.Patch Versions must increase over time
Minor version may include new, backwards compatible functionality 1.0 is forward compatible with 1.1 1.1 is not backward compatible with 1.0
Patch level is never considered when determining version compatibility Patches must not introduce new functionality, only bug fixes!
All Proteus plugin access includes an explicit version reference
Triple-Bonded Factory Design
Proteus Factory Registrar is the master registrar that manages one or more Plugin Archetypes
Each Plugin Archetype maintains its own Plugin Registrar that manages one or more concrete implementations of the archetype.
The Plugin Registrar is a factory that can create instances of a specific version and/or instance of the plugin archetypeProteus Factory Registrar Plugin Registrar Plugin
Instance
Proteus Factory Registrar
Entry point into the Proteus plugin architecture Registrar is solely responsible for being the
authoritative registrar for all known Plugin Archetypes
Access to the Proteus Factory Registrar is implicit through an injected delegate:
IPluginRegistrar pluginRegistrar = delegate.getPluginRegistrar(NAMESPACE);
a priori Archetype Knowledge
Applications must have a priori knowledge of the plugin archetypes they intend to support
Application is designed against a specific archetype interface version Remember, archetype is defined by a namespace and version
Java SE Service Provider Interface ServiceLoader architecture used to dynamically locate and enumerate plugin archetypes instances Archetypes are declared in the .jar manifest according to Java SE by
defining their fully qualified class within a text file defined by Java SE SPI architeture:
META-INF/services/org.proteusframework.spi.ProteusRegistrarFactory
Plugin Registrar
Plugin Registrar is the authoritative registrar for a specific Plugin Archetype.
Specific plugin instances can be be created by version
Proteus embraces Java GenericsVersion ver = new Version(1);MyInterface plugin =
pluginRegistrar.createPlugin(ver, MyInterface.class);
Dynamic Plugin Discovery
Plugin Archetypes require a priori knowledge programmed into the application
Concrete instances of a plugin archetype have no such requirement; discovered dynamically by Java SE by searching the CLASSPATH for .jar manifest entries
META-INF/services/org.proteusframework.pluigin.spi.MyPlugin
Plugin Architecture Review
The Proteus Factory Registrar manages a collection of Plugin Archetypes
A Plugin Archetype Registrar Factory creates a singular Plugin Registrar
A Plugin Registrar manages a collection of homogenous Plugin Instances
A Plugin Instance provides a specific configurable concrete plugin
Defining a Plugin Archetype
Archetype Package Structure
Interfaces Defines one or more versions of a plugin’s interface
Registrar Plugin Archetype Registrar Factory that collects concrete instances of the
archetype and stands ready to instantiate specific plugin implementation versions SPI
Abstract plugin factory extended by concrete instances Plugin Archetype Registrar Factory delegates construction of the plugin instance
here META-INF/services
How a plugin archetype is declared within a Proteus Application
Archetype Definition
By and large boilerplate code Anticipate implement a mvn plugin so that a plugin can
be created via mvn archetype:archetype command Decide on a namespace Implement one or more plugin interface versions Link the interfaces to semantic versions within the
VersionCollection
Concrete Plugin Structure
Plugin Factory Implementation
Version Implementation
Proxy Interface unused by concrete plugin implementations Concrete plugin extends the actual version interface; the
plugin instance is explicitly dependent upon the Plugin Archetype .jar
public class Version1Impl extends AbstractStandardPlugin implements ISampleVersion1
Specific Version Each plugin is tied to a specific version explicitly be the
versioned interface it implements from the plugin archetype
Bootstrap a Proteus Application
Create a main class that extends AbstractRuntimeEnginepublic class SampleApplication extends AbstractRuntimeEngine
Create an instance of either a StandardProteusApplication or ExtendedProteusApplication
IProteusApplication myApplication = new StandardProteusApplication();
Instantiate the runtime engine IRuntimeEngine myRuntimeEngine = new SampleApplication();
Bootstrap a Proteus Application
Inject the runtime engine into the application myApplication.setRuntimeEngine(myRuntimeEngine);
Start the applicationmyApplication.startApplication();
Formally launch the application in the run() methodpublic void run() {runningFlag = true; ... }
Application Configuration
Standard Proteus applications can easily separate out their configuration from the actual runtime implementation
Use of IConfigurationLoader provides an abstraction on IProteusApplication between configuration and storage Java SE deployment will differ from an Android
deployment
Plugin Instantiation
Get version 1 interface from the default plugin provider Default can be defined during runtime engine
configuration (e.g. .properties file)
MyExpectedVersion1Interface example1 = pluginRegistrar.createPlugin(new Version(1),
MyExpectedVersion1Interface.class);
Plugin Instantiation
Get version 1 interface from a specific concrete plugin
INamespace pluginNS = new Namespace(”com.foo", “FooRegistrar");IVersionDescriptor vd = new VersionDescriptor(pluginNS, new Version(1, 0));
MyVersion1Interface example2 = pluginRegistrar.createPlugin(vd, MyVersion1Interface.class);
Application Shutdown
Resource cleanup requires that the engine be shutdown propertly Accomplished with a single call:
myApplication.stopApplication();