Plugin Core Concepts RESTHeart
This page covers the essential concepts you need to understand when developing RESTHeart plugins.
|
Tip
|
New to plugins? Start with the Plugin Development Overview and Tutorial first. |
Project Setup and Dependencies
The only required dependency to develop a plugin is restheart-commons.
With maven:
<dependency>
<groupId>org.restheart</groupId>
<artifactId>restheart-commons</artifactId>
<version>VERSION</version>
</dependency>
With Gradle:
dependencies {
implementation 'org.restheart:restheart-commons:VERSION'
}
|
Tip
|
Use the plugin skeleton project for a ready-to-go Maven setup. |
The @RegisterPlugin Annotation
Every plugin must be annotated with @RegisterPlugin. This annotation:
-
Allows RESTHeart to discover your plugin at startup
-
Defines the plugin’s name, description, and behavior
-
Specifies configuration like URIs, security settings, and execution priorities
Basic example:
@RegisterPlugin(name = "foo",
description = "just an example service",
defaultUri="/foo", // optional, default /<service-name>
secure=false, // optional, default false
enabledByDefault=false) // optional, default true
public class MyPlugin implements JsonService {
...
}
Annotation Parameters:
| param | plugin | description | mandatory | default value |
|---|---|---|---|---|
|
all |
the name of the plugin |
yes |
none |
|
all |
description of the plugin |
yes |
none |
|
all |
|
no |
|
|
service |
the default URI of the Service; can be overridden by the service configuration option |
no |
/<srv-name> |
|
service |
|
no |
|
|
service |
|
no |
|
|
service |
list of interceptPoints to be executed on requests handled by the service, e.g. |
no |
|
|
interceptor |
the intercept point: |
no |
REQUEST_AFTER_AUTH |
|
initializer |
specify when the initializer is executed: |
no |
|
|
proxy interceptor |
Only used by Interceptors of proxied resources (the content is always available to Interceptor of Services) Set it to true to make available the content of the request (if interceptPoint is REQUEST_BEFORE_AUTH or REQUEST_AFTER_AUTH) or of the response (if interceptPoint is RESPONSE or RESPONSE_ASYNC) |
no |
|
|
interceptor, initializer |
the execution priority (less is higher priority) |
no |
|
|
service |
With blocking = |
no |
|
|
authorizer |
|
no |
ALLOWER |
Configuration
Plugins are configured in restheart.yml using the plugin name from @RegisterPlugin:
ping:
enabled: true
secure: false
uri: /ping
msg: 'Ping!'
Special configuration options automatically managed by RESTHeart:
-
enabled: Enable/disable the plugin (overrides
enabledByDefaultin@RegisterPlugin) -
uri: Set the service URI (overrides
defaultUriin@RegisterPlugin) -
secure: Require authentication/authorization (
true) or allow open access (false)
|
Warning
|
Services have secure: false by default! Always set secure: true for production services that need protection.
|
Accessing configuration in code:
@Inject("conf")
Map<String, Object> conf;
// Use helper method to get values
String msg = argValue(conf, "msg");
Dependency Injection
Use @Inject to access RESTHeart’s built-in objects and services. Available providers:
| Injection | Type | Use For |
|---|---|---|
|
|
Plugin’s configuration |
|
|
RESTHeart’s global configuration |
|
|
MongoDB database access |
|
|
Access to other plugins |
|
|
Programmatic permission management |
|
|
GraphQL app definition cache |
Example:
public class MyPlugin implements JsonService {
@Inject("mclient")
private MongoClient mclient;
@Inject("conf")
private Map<String, Object> conf;
@Override
public void handle(JsonRequest req, JsonResponse res) {
// Use injected MongoClient
var db = mclient.getDatabase("mydb");
// Use injected configuration
var setting = argValue(conf, "mySetting");
}
}
|
Tip
|
See Providers for how to create your own injectable objects. |
Request and Response Types
Services and Interceptors are generic classes that use type parameters to define how they handle request and response data.
RESTHeart provides specialized Request/Response pairs for different data formats:
| Type Pair | Content Format | Best For |
|---|---|---|
|
JSON objects |
REST APIs, JSON services |
|
BSON (MongoDB format) |
MongoDB operations |
|
MongoDB-specific |
Advanced MongoDB features |
|
Raw bytes |
Binary data, files |
|
Plain text |
Text processing |
|
CSV to BSON |
CSV imports |
Why this matters:
-
The type you choose determines how request content is parsed and cached
-
Each type provides helper methods for its specific use case (e.g.,
MongoRequest.getPageSize()) -
Content is parsed once and cached for efficiency
-
Type safety helps prevent errors at compile time
Example:
@RegisterPlugin(name = "myService", defaultUri = "/myapi")
public class MyService implements JsonService {
@Override
public void handle(JsonRequest req, JsonResponse res) {
// req and res are strongly typed for JSON
JsonObject content = req.getContent();
res.setContent(Json.object().put("status", "ok"));
}
}
|
Tip
|
Start with JsonService for most REST APIs. See Services for detailed examples of each type.
|
How Content Parsing Works
Understanding how RESTHeart handles request content is important for efficient plugin development.
The parsing lifecycle:
-
When a request arrives, RESTHeart determines which Service will handle it
-
The Service creates typed Request and Response objects
-
On first call to
request.getContent(), the content is parsed usingparseContent() -
The parsed content is cached in the request object
-
Subsequent calls to
getContent()return the cached object (no re-parsing)
Why this matters:
-
Content is only parsed when you actually need it (lazy evaluation)
-
Multiple plugins can access the same content without overhead
-
You can safely call
getContent()multiple times
Custom parsing:
If you create a custom ServiceRequest, implement the parseContent() method:
public abstract class ServiceRequest<T> {
/**
* Parses the content from the exchange and converts it into type T.
* Called automatically by getContent() on first invocation.
*/
public abstract T parseContent() throws IOException, BadRequestException;
}
Next Steps
-
Apply these concepts: Build a Service
-
See it in action: Plugin Development Tutorial
-
Advanced topics: Create Custom Providers