How to deploy Plugins
Introduction
This section provides information on how to package and deploy plugins.
Note
|
To quick start a new Java plugin, you can clone the plugin skeleton repository. It contains a basic skeleton for a plugin and an helper script that allows to build, deploy the plugin. |
Java Plugins
Java and Kotlin plugins must be packaged as jar files.
To deploy a plugin, just copy its jar file into the directory ./plugins
of RESTHeart.
Important
|
After deploying a jar plugin, you must restart RESTHeart. |
Example
As an example we will build and deploy the simple Greeter Service example plugin.
Let’s clone the RESTHeart repository that includes the examples
directory and build the greeter-service
example.
$ git clone --depth 1 git@github.com:SoftInstigate/restheart.git
$ cd restheart/examples/greeter-service
$ ../mvnw clean package
The built plugin jar file is target/greeter-service.jar
. Copy it into the RESTHeart plugins directory.
$ cp target/greeter-service.jar <RH_HOME>/plugins
Restarting RESTHeart will produce the following log message:
$ java -jar restheart.jar etc/restheart.yml -e etc/default.properties
INFO org.restheart.Bootstrapper - Starting RESTHeart instance default
...
INFO org.restheart.plugins.PluginsFactory - Found plugin jar file:/Users/uji/development/restheart/core/target/plugins/greeter-service.jar
...
INFO org.restheart.Bootstrapper - URI /greetings bound to service greetings, secured: false, uri match PREFIX
....
Let’s test it (for example, using the httpie client):
$ http -b :8080/greetings
{
"message": "Hello World!"
}
External dependencies
The Random String Service example plugin shows how to add to the classpath an external dependency required by a plugin.
By external dependency we mean a dependency that is not included in restheart.jar, thus it must be added to the classpath for the service to work.
Important
|
To add an external dependency to the classpath just copy it into the RESTHeart plugins directory. |
The plugin pom.xml file defines the following dependencies:
<dependencies>
<dependency>
<groupId>org.restheart</groupId>
<artifactId>restheart-commons</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
</dependencies>
The scope of restheart-commons
is provided
since it is provided by the RESTHeart runtime, together with many others.
To get a list of all the dependencies included in the RESTHeart runtime, you can use the following command:
$ cd <RH_HOME>/core
$ ../mvnw dependency:tree -Dscope=compile
On the other side, the scope of commons-lang3
is compile
as it is not provided by the RESTHeart runtime. Thus it is an external dependency and it must be copied into the RESTHeart plugins directory.
Let’s build the plugin.
$ git clone --depth 1 git@github.com:SoftInstigate/restheart.git
$ cd restheart/examples/random-string-service
$ ../mvnw clean package
The pom.xml uses the maven-dependency-plugin
to copy the jars of the external dependencies into the directory target/lib
To deploy the plugin copy its jar file and the jars of the dependencies into the plugins directory.
$ cp target/random-string-service.jar target/lib/* <RH_HOME>/plugins/
JavaScript Plugins
Important
|
JavaScript plugins can be deployed only running RESTHeart on GraalVM and on restheart native. |
Note
|
Deploying JavaScript plugins does not require restarting RESTHeart, they can be hot-deployed! To update an already deployed JavaScript plugin, touch its root directory.
|
The JavaScript plugins are packaged in directories containing the JavaScript files and the package.json
file.
The JavaScript plugin Credit Card Hider is an example.
Its package.json file declares the Interceptor cc-hider.js
via the property rh:interceptors
(Services are declared with rh:services
):
{
"name": "restheart-demo-cc-hider",
"version": "1.0.0",
"description": "demo plugins for RESTHeart",
"rh:interceptors": [ "cc-hider.js" ]
}
Let’s deploy it.
$ git clone --depth 1 git@github.com:SoftInstigate/restheart.git
$ cp -r restheart/examples/credit-card-hider <RH_HOME>/plugins
RESTHeart log files shows the following message:
INFO o.r.polyglot.PolyglotDeployer - Added interceptor ccHider, description: hides credit card numbers
Refer to the Credit Card Hider README.md for more information on how to play with this JavaScript plugin.
Note
|
More JavaScript plugins examples are available in the test-js-plugins directory. |
Deploy Java plugins on RESTHeart Native
RESTHeart native can run JavaScript plugins as previously described.
However you cannot deploy Java plugins in RESTHeart native by merely copying jars file into the plugins directory (this will be allowed in the future).
In order to use Java plugins on RESTHeart native you must build them as native image together with RESTHeart.
The repository restheart-plugin-skeleton defines a skeleton project for Java plugins. Its pom.xml maven file defines the native
profile that uses the native-maven-plugin
to build the native image, defining the required dependencies.
Fork the repository
$ git clone git@github.com:SoftInstigate/restheart-plugin-skeleton.git
$ cd restheart-plugin-skeleton
Make sure you are using GraalVM.
$ java -version
openjdk version "17.0.3" 2022-04-19
OpenJDK Runtime Environment GraalVM CE 22.1.0 (build 17.0.3+7-jvmci-22.1-b06)
OpenJDK 64-Bit Server VM GraalVM CE 22.1.0 (build 17.0.3+7-jvmci-22.1-b06, mixed mode, sharing)
Make sure you have native-image
installed.
$ gu install native-image
Build it.
$ ./mvnw clean package -Pnative
Native image reflection configuration for Java plugins
Only required for RESTHeart version < 6.5
Note
|
Starting from RESTHeart 6.5, this configuration is no longer needed. All plugins are automatically configured for reflection (as required by the native-image build tool) via the PluginsReflectionRegistrationFeature feature. |
Note
|
more on GraalVM reflection configuration can be found at Reflection on Native Image |
For a simple example you can look at reflect-config.json file of the plugin skeleton project.
In short you need to create in your plugin source project the file src/main/resources/META-INF/native-image/<group-id>/<artifact-id>/reflect-config.json
and add an entry per each plugin.
The following entry is an example:
[
{
"name": "org.restheart.examples.HelloWorldService",
"methods": [{ "name": "<init>", "parameterTypes": [] }]
}
]
For each of your Service
, Interceptor
and Initializer
you need to specify an entry with name
equal to the class name of your component and the methods
array with:
-
the default Constructor (always)
-
the method annotated with
@InjectConfiguration
(if any) -
the method annotated with
@InjectMongoClient
(if any) -
the method annotated with
@InjectPluginsRegistry
(if any)