Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Gyrex/Context Runtime"

(added content)
m (Introduction)
 
(10 intermediate revisions by one other user not shown)
Line 1: Line 1:
== Introduction ==
+
{{Gyrex}}
  
Eclipse is a dynamic and extensible platform. For example, the Eclipse extension
+
== Introduction  ==
registry allows for a great extensibility where some code defines an extension
+
Eclipse is a dynamic and extensible platform. For example, the Eclipse extension registry allows for a great extensibility where some component defines an extension point and allows others to provide an implementation for it. Another possibility are OSGi services. There can be multiple extensions as well as multiple instances of an OSGi service. This is especially of interest in a multi-tenant environment because it allow for tenant-specific extensions as well as implementations.
point and allows others to provide an implementation for it. Another possibility
+
are OSGi services.  
+
  
The Gyrex Platform includes a context sensitive runtime to support dynamic
+
This flexibility requires some management and processes to handle all the extensions and service implementations in order to pick the right one to use in a specific situation. We refer to this situation as "''execution context''" ("''runtime context''", or just "''context''") in Gyrex. Gyrex allows to put or execute  operations within (or on behalf of) a particular context. The context runtime is one of the key elements of Gyrex and allows - for example - the development of multi-tenant software offerings.  
constraints. Every operation in Gyrex happens within (or on behalf of) a
+
particular context. The contextual runtime is one of the key elements of Gyrex  
+
and allows - for example - the development of multi-tenant software offerings.
+
  
Let's look at an example. In an e-commerce shopping system the shopping cart
+
Let's look at an example. On an online shopping website inventory information is displayed along the items. The inventory information is retrieved from a service. This service is defined in a bundle with a default implementation backed by a database. This will be the default for all shops served by the system. The other day a new client comes along which likes the shopping website to retrieve the inventory information directly from an inventory system instead of a database. With OSGi or the Eclipse extension registry this is a no-brainer. You simply implement the special inventory service and provide it as an OSGi service (or Eclipse extension). But now the shopping website needs to deal with two services implementations (or two extensions). It needs to know which one to use in which shop. Ideally this would be configurable by a system operator. Here comes the Gyrex Context Runtime to the rescue. Using the Context Runtime a shop can be defined as a runtime context. The shopping website simply delegates the call. Instead of asking the extension registry or the OSGi service registry directly, it asks the context which service (or extension) to use. The rest will all be configurable through an administration interface (or via APIs). Your code does not need to implement any filtering or permission checks. The Gyrex Context Runtime takes care of that.
calculation could be made extensible using the extension registry or using
+
OSGi services. A default implementation would e provided which does a simple
+
total calculation. This will be the default for all shops served by your system.
+
The other day a new client comes along and has very special requirements for
+
the shopping cart calculation. With OSGi or the Eclipse extension registry this
+
is a no-brainer. You simply implement the special calculation and provide it
+
as an OSGi service. But now the "host" code needs to deal with two services (or
+
two extension). It need to know which one to use in which shop. Here comes the
+
contextual runtime to the rescue. Using the contextual runtime a shop will be
+
defined as the runtime context. Your code simply delegates the call. Instead of
+
asking the extension registry or the OSGi service registry directly, it asks the
+
context which service (or extension) to use. The rest will all be configurable
+
through an administration interface or via APIs. Your code does not need to
+
implement any filtering or permission checks. The contextual runtime takes care
+
of that.
+
  
 +
== The Runtime Context  ==
 +
The runtime context is the central element of the context runtime. It provides API to get a specific, ready-configured service instance. Callers will pass a key and it will return an object. Thus, the context is basically a configurable object registry. However, it's dynamic, i.e. it can change between invocations. Therefore callers may not hold on to the returned instances forever.
  
== The Runtime Context ==
+
The context will support dependency-injection, i.e. it can be injected into objects. The injection is also dynamic. The context keeps track of all injected objects and updates the objects if an injected value changes. These capabilities will be implemented on top of the Eclipse e4 dependency-injection mechanism.
  
The runtime context is the central element of the contextual runtime. It
+
Out of the box, the context runtime will support retrieval of the following objects:
provides APIs to get a specific, ready-configured service for the client code
+
* Context specific objects
base to use. The lookup of the service will be very simple. You simply pass
+
* OSGi services
a class object to context and it will return an instance of the class for you
+
* Eclipse extensions
to work with. Thus, the context is essentially an object registry. However,
+
* Eclipse adapters for adaptable objects
it's dynamic, i.e. it can change between invocations.
+
* Eclipse preferences
  
Contexts are hierarchical organized in a path like structure. There is a root
+
=== Context Specific Objects ===
context ("/") which typically defines the core pieces of a system. In a single
+
Context specific objects are objects which exist specifically in/for a particular context. They are contributed to the context runtime using a factory/provider pattern. Whenever necessary the context runtime delegates to the provider to create such an object for a context. The provider are registered as OSGi services using the whiteboard pattern.
system it's actually possible to just work with the root context.  
+
  
Context values are inherited. Thus, if a context does not have a value defined,
+
Those familiar with OSGi services can compare the behavior to OSGi service factories. But instead of creating a service instance per consuming bundle it’s possible to create a service instance per consuming context. Context specific objects allow a convenient programming model of context specific behavior. All other object retrievals are implemented based on context specific objects.
it's parent will be queried until a value is found. It's also possible to  
+
explicitly undefine (set to "null") a value in a client context.
+
  
Note, for security reasons (see below) a context will not allow simple
+
=== OSGi Services ===
retrieval of its parent context. Instead always the context registry has to
+
These are pure OSGi services. A context acquires services instances on behalf of the consuming bundle. Therefore it needs a <code>BundleContext</code> on which’s behalf services shall be acquired. This is also important for security reasons to properly verify that a consumer is really allowed to consume a particular OSGi service.
be used to lookup a particular context.
+
  
 +
The OSGi service registry does not know about runtime contexts. OSGi services have a different lifecycle than runtime contexts. In order to access a runtime context as well as context objects from within an OSGi service its method signatures need to requested the objects explicitly.
  
== Contextual Objects ==
+
The advantage of using a runtime context to acquire an OSGi service is that the caller does not need to implement any logic which service to use in case many services are available. A runtime context will filter all service instances that are not relevant in a specific context. Of course, clients may still want to track all instances of a service themselves. Therefore the context runtime will also offer convenient API for filtering a set of given services (eg., <code>ServiceReference</code>).
  
The objects ("values") provided by the context are pure Java objects. They
+
It is assumed that OSGi services are configured by the service exporter/creator which is an external entity that may not even know about the context. Therefore, dependency injection into OSGi services will not be supported by the context runtime. But it will be possible to inject OSGi services into context objects. Injected OSGi services will be dynamic, i.e. they will be uninjected when they go away and updated when they change.
can be OSGi services, Eclipse extensions, Eclipse adapters from the
+
IAdapterFactory or other contextual objects. Contextual objects are objects
+
provided specifically for a context. A provider can be registered as an OSGi  
+
service which will provide context specific objects. To some extend, this can
+
be compare to OSGi service factories. The only difference is, that the service
+
implementation is not bound to the bundle requesting the service but to the
+
context requesting the service. This allows for a concept of context singletons.
+
  
 +
=== Eclipse Extensions ===
 +
These are pure Eclipse extensions (<code>IExtension</code>). In the context runtime it should be possible to limit the visibility of available extensions in a particular context. Therefore, the runtime context will offer API to retrieve a filtered set of extensions that are available for use in a particular context. It may also offer convenient API to filter a set of given extensions.
  
== Context Registry & Security ==
+
At this point, dependency injection will not be supported for Eclipse extensions. This may be re-evaluated in the future.
  
The configuration of contexts is persisted and kept across sessions. A central
+
=== Eclipse Adapters ===
registry is available of "loading" of contexts. However, access to the registry
+
Eclipse provides an implementation and makes heavy use of the adaptable pattern (<code>IAdaptable</code>). As with OSGi services and Eclipse extensions they don’t know anything about a runtime context. However, it should be possible to use specific adapter implementations in a particular context. Therefore, the runtime context will offer API to retrieve a context specific (“preferred”) adapter from a set of available adapter implementations.
may be guarded by security constraints to allow only trusted code access to  
+
 
a specific set of contexts. This prevents client code with a lower lever of  
+
At this point, dependency injection will not be supported for Eclipse extensions. This may be re-evaluated in the future.
trust to not execute operations outside of the client context.
+
 
 +
=== Eclipse Preferences ===
 +
In order to support implementers with context specific configuration capabilities of their implementations a runtime context will provide access to the Eclipse Preferences API using a context specific view. This also includes proper handling of the built-in preference scopes.
 +
 
 +
Another interesting capability is the injection of preferences into context objects. It will be supported to inject preference node objects as well as pure value objects into context objects.
 +
 
 +
 
 +
== Multi-Version Support  ==
 +
Multi-version support is an essential requirement especially in a multi-tenant software offering. There are tenants who always want the latest and greatest and there will also be tenants who are very conservative in there update strategies.
 +
 
 +
In a multi-version environment, several versions of a service may be available. This includes multiple implementation versions as well as multiple service definitions.
 +
 
 +
Multi-version support applies to Context Specific Objects, OSGi Services, Eclipse Adapters and partially Eclipse Extensions (multiple extensions for one extension point).
 +
 
 +
=== Multiple Service Definitions ===
 +
If a service is defined by an interface (or an abstract class) the interface may be available in a 1.1 version as well as a 2.0 version. Complementary, there will be a (at least) one implementation for each service definition.
 +
 
 +
In order to handle this scenario correctly, the runtime context must know which version of a service definition the caller requested. Therefore, we’ll rely on the OSGi fundamentals that there will be different class objects for the service definitions. The usage of <code>java.lang.Class</code> keys ensures that a context knows about the requested service definition version. It can then inspect the available service implementations and filter out the incompatible once.
 +
 
 +
=== Multiple Service Implementations ===
 +
It may be possible that multiple service implementations are available for the same service definition. For example, a service interface may be available in a 1.1 version only. But there might be a 1.1.1 implementation and a 1.1.2 implementation (containing a little change in the implementation).
 +
In order to handle this scenario correctly, the runtime context must know which version of a service implementation to return to the caller. This will be implemented using a configuration capability. A context may be configured with an LDAP-style filter (a concept used broadly within OSGi). A matching will be performed on available service implementations and the first matching one will be returned.
 +
 
 +
Note, “first” implies an ordering mechanism involved. We’ll rely on the natural ordering of service implementations. In the case of OSGi services this may be the service ranking. For extensions the order is determined by the Eclipse extension registry.
 +
This scenario also includes the situation when there are tenant-specific implementations of a service available. However, in order to not require all available contexts to be configured to ‘’not’’ use a tenant specific implementation, the context runtime will provide capabilities to define a preferred service implementation.
 +
 
 +
 
 +
== Context Hierarchy ==
 +
Contexts are hierarchical organized in a path like structure. Based on this hierarchical organization a context is able to inherit behavior (configuration) from a parent context.
 +
 
 +
There is a root context ("/") which typically defines the core pieces (“root”) of a system. In a single system it's actually possible to just work with the root context. In a multi-tenant system the root context may define default behavior for all tenant contexts (for example, preferred system-wide service implementations). Complementary, a tenant context is able to define default behavior for all sub-contexts of that tenant.
 +
 
 +
=== Hierarchy Organization ===
 +
At this point, the actual organization of contexts is left to the implementers of systems. As already outlined above, several possibilities are available.
 +
 
 +
TODO: We should elaborate this further and come up with some recommended strategies/examples for different scenarios.
 +
 
 +
==== Simple Tenant-Centric Example ====
 +
<code>/<tenant>/…</code>
 +
* / - for establishing system wide default behavior<br>Examples:
 +
** Use simple database based inventory management service implementation
 +
* /<tenant> - for establishing tenant wide default behavior
 +
** Use tenant-specific inventory management service implementation
 +
 
 +
==== Multi-Organization Tenant Example ====
 +
<code>/<tenant-head-organization>/<tenant-sub-organization>/…</code>
 +
 
 +
 
 +
== Context Registry ==
 +
The configuration of contexts is persisted and kept across sessions. A central registry is responsible for "loading" of contexts. However, access to the registry may be guarded by security constraints to allow only trusted code access to a specific set of contexts. This prevents client code with a lower level of trust to not execute operations outside of the client context.  
 +
 
 +
The registry may provide capabilities to define new contexts and maintain existing contexts. It may also provide capabilities to export a context configuration as well as creating new contexts based on such exported configurations to support advanced operations (such as cloning).
 +
 
 +
 
 +
== Security  ==
 +
Wherever possible, the context runtime relies on OSGi fundamentals for security. For example, OSGi permissions shall be used to verify that a consumer is able to consume a service. OSGi permissions may also be used to limit the packages a consumer may have access to.
 +
 
 +
 
 +
== Context Applications ==
 +
TODO (an application model for context specific applications based on the OSGi application admin spec)

Latest revision as of 13:53, 28 November 2012

Gyrex
Website
Download
Community
Mailing ListForumsIRCmattermost
Issues
OpenHelp WantedBug Day
Contribute
Browse SourceProject Set File

Introduction

Eclipse is a dynamic and extensible platform. For example, the Eclipse extension registry allows for a great extensibility where some component defines an extension point and allows others to provide an implementation for it. Another possibility are OSGi services. There can be multiple extensions as well as multiple instances of an OSGi service. This is especially of interest in a multi-tenant environment because it allow for tenant-specific extensions as well as implementations.

This flexibility requires some management and processes to handle all the extensions and service implementations in order to pick the right one to use in a specific situation. We refer to this situation as "execution context" ("runtime context", or just "context") in Gyrex. Gyrex allows to put or execute  operations within (or on behalf of) a particular context. The context runtime is one of the key elements of Gyrex and allows - for example - the development of multi-tenant software offerings.

Let's look at an example. On an online shopping website inventory information is displayed along the items. The inventory information is retrieved from a service. This service is defined in a bundle with a default implementation backed by a database. This will be the default for all shops served by the system. The other day a new client comes along which likes the shopping website to retrieve the inventory information directly from an inventory system instead of a database. With OSGi or the Eclipse extension registry this is a no-brainer. You simply implement the special inventory service and provide it as an OSGi service (or Eclipse extension). But now the shopping website needs to deal with two services implementations (or two extensions). It needs to know which one to use in which shop. Ideally this would be configurable by a system operator. Here comes the Gyrex Context Runtime to the rescue. Using the Context Runtime a shop can be defined as a runtime context. The shopping website simply delegates the call. Instead of asking the extension registry or the OSGi service registry directly, it asks the context which service (or extension) to use. The rest will all be configurable through an administration interface (or via APIs). Your code does not need to implement any filtering or permission checks. The Gyrex Context Runtime takes care of that.

The Runtime Context

The runtime context is the central element of the context runtime. It provides API to get a specific, ready-configured service instance. Callers will pass a key and it will return an object. Thus, the context is basically a configurable object registry. However, it's dynamic, i.e. it can change between invocations. Therefore callers may not hold on to the returned instances forever.

The context will support dependency-injection, i.e. it can be injected into objects. The injection is also dynamic. The context keeps track of all injected objects and updates the objects if an injected value changes. These capabilities will be implemented on top of the Eclipse e4 dependency-injection mechanism.

Out of the box, the context runtime will support retrieval of the following objects:

  • Context specific objects
  • OSGi services
  • Eclipse extensions
  • Eclipse adapters for adaptable objects
  • Eclipse preferences

Context Specific Objects

Context specific objects are objects which exist specifically in/for a particular context. They are contributed to the context runtime using a factory/provider pattern. Whenever necessary the context runtime delegates to the provider to create such an object for a context. The provider are registered as OSGi services using the whiteboard pattern.

Those familiar with OSGi services can compare the behavior to OSGi service factories. But instead of creating a service instance per consuming bundle it’s possible to create a service instance per consuming context. Context specific objects allow a convenient programming model of context specific behavior. All other object retrievals are implemented based on context specific objects.

OSGi Services

These are pure OSGi services. A context acquires services instances on behalf of the consuming bundle. Therefore it needs a BundleContext on which’s behalf services shall be acquired. This is also important for security reasons to properly verify that a consumer is really allowed to consume a particular OSGi service.

The OSGi service registry does not know about runtime contexts. OSGi services have a different lifecycle than runtime contexts. In order to access a runtime context as well as context objects from within an OSGi service its method signatures need to requested the objects explicitly.

The advantage of using a runtime context to acquire an OSGi service is that the caller does not need to implement any logic which service to use in case many services are available. A runtime context will filter all service instances that are not relevant in a specific context. Of course, clients may still want to track all instances of a service themselves. Therefore the context runtime will also offer convenient API for filtering a set of given services (eg., ServiceReference).

It is assumed that OSGi services are configured by the service exporter/creator which is an external entity that may not even know about the context. Therefore, dependency injection into OSGi services will not be supported by the context runtime. But it will be possible to inject OSGi services into context objects. Injected OSGi services will be dynamic, i.e. they will be uninjected when they go away and updated when they change.

Eclipse Extensions

These are pure Eclipse extensions (IExtension). In the context runtime it should be possible to limit the visibility of available extensions in a particular context. Therefore, the runtime context will offer API to retrieve a filtered set of extensions that are available for use in a particular context. It may also offer convenient API to filter a set of given extensions.

At this point, dependency injection will not be supported for Eclipse extensions. This may be re-evaluated in the future.

Eclipse Adapters

Eclipse provides an implementation and makes heavy use of the adaptable pattern (IAdaptable). As with OSGi services and Eclipse extensions they don’t know anything about a runtime context. However, it should be possible to use specific adapter implementations in a particular context. Therefore, the runtime context will offer API to retrieve a context specific (“preferred”) adapter from a set of available adapter implementations.

At this point, dependency injection will not be supported for Eclipse extensions. This may be re-evaluated in the future.

Eclipse Preferences

In order to support implementers with context specific configuration capabilities of their implementations a runtime context will provide access to the Eclipse Preferences API using a context specific view. This also includes proper handling of the built-in preference scopes.

Another interesting capability is the injection of preferences into context objects. It will be supported to inject preference node objects as well as pure value objects into context objects.


Multi-Version Support

Multi-version support is an essential requirement especially in a multi-tenant software offering. There are tenants who always want the latest and greatest and there will also be tenants who are very conservative in there update strategies.

In a multi-version environment, several versions of a service may be available. This includes multiple implementation versions as well as multiple service definitions.

Multi-version support applies to Context Specific Objects, OSGi Services, Eclipse Adapters and partially Eclipse Extensions (multiple extensions for one extension point).

Multiple Service Definitions

If a service is defined by an interface (or an abstract class) the interface may be available in a 1.1 version as well as a 2.0 version. Complementary, there will be a (at least) one implementation for each service definition.

In order to handle this scenario correctly, the runtime context must know which version of a service definition the caller requested. Therefore, we’ll rely on the OSGi fundamentals that there will be different class objects for the service definitions. The usage of java.lang.Class keys ensures that a context knows about the requested service definition version. It can then inspect the available service implementations and filter out the incompatible once.

Multiple Service Implementations

It may be possible that multiple service implementations are available for the same service definition. For example, a service interface may be available in a 1.1 version only. But there might be a 1.1.1 implementation and a 1.1.2 implementation (containing a little change in the implementation). In order to handle this scenario correctly, the runtime context must know which version of a service implementation to return to the caller. This will be implemented using a configuration capability. A context may be configured with an LDAP-style filter (a concept used broadly within OSGi). A matching will be performed on available service implementations and the first matching one will be returned.

Note, “first” implies an ordering mechanism involved. We’ll rely on the natural ordering of service implementations. In the case of OSGi services this may be the service ranking. For extensions the order is determined by the Eclipse extension registry. This scenario also includes the situation when there are tenant-specific implementations of a service available. However, in order to not require all available contexts to be configured to ‘’not’’ use a tenant specific implementation, the context runtime will provide capabilities to define a preferred service implementation.


Context Hierarchy

Contexts are hierarchical organized in a path like structure. Based on this hierarchical organization a context is able to inherit behavior (configuration) from a parent context.

There is a root context ("/") which typically defines the core pieces (“root”) of a system. In a single system it's actually possible to just work with the root context. In a multi-tenant system the root context may define default behavior for all tenant contexts (for example, preferred system-wide service implementations). Complementary, a tenant context is able to define default behavior for all sub-contexts of that tenant.

Hierarchy Organization

At this point, the actual organization of contexts is left to the implementers of systems. As already outlined above, several possibilities are available.

TODO: We should elaborate this further and come up with some recommended strategies/examples for different scenarios.

Simple Tenant-Centric Example

/<tenant>/…

  • / - for establishing system wide default behavior
    Examples:
    • Use simple database based inventory management service implementation
  • /<tenant> - for establishing tenant wide default behavior
    • Use tenant-specific inventory management service implementation

Multi-Organization Tenant Example

/<tenant-head-organization>/<tenant-sub-organization>/…


Context Registry

The configuration of contexts is persisted and kept across sessions. A central registry is responsible for "loading" of contexts. However, access to the registry may be guarded by security constraints to allow only trusted code access to a specific set of contexts. This prevents client code with a lower level of trust to not execute operations outside of the client context.

The registry may provide capabilities to define new contexts and maintain existing contexts. It may also provide capabilities to export a context configuration as well as creating new contexts based on such exported configurations to support advanced operations (such as cloning).


Security

Wherever possible, the context runtime relies on OSGi fundamentals for security. For example, OSGi permissions shall be used to verify that a consumer is able to consume a service. OSGi permissions may also be used to limit the packages a consumer may have access to.


Context Applications

TODO (an application model for context specific applications based on the OSGi application admin spec)

Back to the top