You are browsing the docs for Nexus v1.7.x, the latest release is available here
Plugins
Starting from version 1.5, Delta introduces the ability to extend its functionality using plugins. Plugins enable developers to add new functionality to Nexus Delta without the need to modify Delta itself. Plugins can introduce various new functionalities, including new API endpoints and indexing capabilities.
Plugins are still an experimental feature and Delta SDKs and dependent modules(rdf, sourcing) provide no binary compatibility guarantees.
Plugin development
Plugins used by Delta need to be packaged as a .jar
file containing the plugin code with all its dependencies. Delta loads plugins from .jar
files located in a directory specified by DELTA_PLUGINS
environment variable.
Plugins must define exactly one class which extends PluginDef trait.
The class must define following methods:
def info: PluginDescription
this method returns instance of PluginDescription which defines the plugin name and version.
def initialize(locator: Locator): Task[Plugin]
this method can be used to initialize the plugin and returns an instance of a Plugin
, which can additionally define logic to stop the plugin gracefully.
def module: ModuleDef
this method must return ModuleDef
from distage library. This is the only way in which plugins can use dependencies provided by core of Delta and other plugins, as well as provide dependencies which can be used by Delta and other plugins.
Example
- TestPluginRoutes.scala
-
source
package ch.epfl.bluebrain.nexus.delta.testplugin import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.delta.sdk.Permissions import monix.execution.Scheduler class TestPluginRoutes(permissions: Permissions)(implicit sc: Scheduler) { def routes: Route = pathPrefix("test-plugin") { concat( get { complete(permissions.fetchPermissionSet.map(ps => s"${ps.mkString(",")}").runToFuture) } ) } }
- TestPluginDef.scala
-
source
package ch.epfl.bluebrain.nexus.delta.testplugin import ch.epfl.bluebrain.nexus.delta.sdk.model.ComponentDescription.PluginDescription import ch.epfl.bluebrain.nexus.delta.sdk.model.Name import ch.epfl.bluebrain.nexus.delta.sdk.plugin.{Plugin, PluginDef} import ch.epfl.bluebrain.nexus.delta.sdk.{Permissions, PriorityRoute} import izumi.distage.model.Locator import izumi.distage.model.definition.ModuleDef import monix.bio.Task import monix.execution.Scheduler case class TestPluginDef() extends PluginDef { override def module: ModuleDef = new ModuleDef { make[TestPlugin] make[TestPluginRoutes].from { (permissions: Permissions, scheduler: Scheduler) => implicit val sc = scheduler new TestPluginRoutes(permissions) } many[PriorityRoute].add((routes: TestPluginRoutes) => PriorityRoute(1, routes.routes, requiresStrictEntity = true) ) } override val info: PluginDescription = PluginDescription(Name.unsafe("testplugin"), "0.1.0") override def initialize(locator: Locator): Task[Plugin] = Task.pure(locator.get[TestPlugin]) }
Delta SDK
The Delta SDK can be included as following dependencies:
- SDK - general Delta SDK
- SDK views - SDK with functionality related to views.
All the above dependencies should be used in provided
scope and must not be bundled in the plugin.
libraryDependencies += "ch.epfl.bluebrain.nexus" %% "delta-sdk" % deltaVersion % Provided
libraryDependencies += "ch.epfl.bluebrain.nexus" %% "delta-sdk-views" % deltaVersion % Provided
Dependency injection
Delta uses distage library for dependency injection. Each plugin must define ModuleDef
to create instances of its own classes. All the dependencies provided by ModuleDef
s defined in Delta modules, as well as other plugins can be used here.
The plugin can also define instances of following traits/classes, which will be used in Delta:
- PriorityRoute - allows the plugin to define Akka HTTP Route with priority. The priority is used by Delta to prioritize route evaluation
- ScopeInitialization - allows the plugin to define hooks which will be run on organization and project creation.
- EventExchange - enables Delta to exchange plugin events for their different representation. Needs to be defined by the plugin in order for resources created by the plugin to be indexed or available via SSE endpoints.
- ReferenceExchange - enables Delta to exchange a resource reference for a JSON-LD value allowing Delta to handle multiple resources in a uniform way
- MetadataContextValue - registers metadata context of this plugin into global metadata context
- RemoteContextResolution - enables Delta to resolve static contexts defined by the plugin
- ServiceDependency - allows the plugin to define dependencies which will be displayed in
/version
endpoint. - ApiMappings - allows the plugin to define default API mappings used to shorten URLs
- ResourceToSchemaMappings - allows the plugin to define mapping from the resource type to schema, which can be used to interact with resources created by the plugin through
/resources
endpoints. - EntityType - allows plugin to define its entity type in order to create Akka Persistence
persistence_id
s.
Class loading
In order to avoid clashes between different plugins, Delta uses custom classloader to load plugin classes, which will load classes from the plugin first, then using application classloader and other plugins after that. It is therefore recommended to not include in the plugin jar any dependencies which are also provided by SDK. Libraries can be easily excluded from dependencies in sbt
:
libraryDependencies ++= Seq(
"com.lightbend.akka" %% "akka-stream-alpakka-sse" % alpakkaVersion excludeAll (
ExclusionRule(organization = "com.typesafe.akka", name = "akka-stream_2.13"),
ExclusionRule(organization = "com.typesafe.akka", name = "akka-http_2.13")
)
Configuration
Plugins should provide their default configuration in {plugin_name}.conf
file, where plugin_name
is the same as the one in PluginDescription
. Plugins should include their config inside plugins.{plugin_name}
namespace in the config. plugins.{plugin_name}.priority
configuration setting defines priority of the plugin, which is used to determine order in which routes provided by plugins are evaluated.
Adding plugins to a Delta deployment
Delta loads plugins from .jar
files present in a folder specified by DELTA_PLUGINS
environment variable. In order to make delta discover the plugin, the .jar
file of the plugin must be added(or symlinked) to that directory. In the official Delta Docker image the plugins are loaded from /opt/docker/plugins
directory.
Enabling/disabling plugins
Additionally, plugins can be enabled/disabled using plugins.{plugin_name}.enabled
property. Setting this property to false
, will disable the given plugin.
Existing plugins
Currently, following Delta functionality is provided by plugins:
- archives API Reference | code
- SPARQL views API Reference | code
- Elasticsearch views API Reference | code
- composite views API Reference | code
- files and storages API Reference | code
- global search API Reference | code
- graph analytics API Reference | code
Elasticsearch plugin is required in order to provide listings in the API, other plugins can be excluded if their functionality is not needed. All the above plugins are included in the Delta Docker image.