You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/graalvm.md
+12Lines changed: 12 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -151,6 +151,18 @@ In order to use Java or Kotlin plugins on RESTHeart native you must build them a
151
151
152
152
Refer to [Deploy Java Plugins On Restheart Native](https://restheart.org/docs/plugins/deploy/#deploy-java-plugins-on-restheart-native) for detailed instructions on how to do it.
153
153
154
+
### Automatic reflection configuration for plugins
155
+
156
+
Since RESTHeart v7, plugin reflection configuration for native images is handled automatically. RESTHeart implements a GraalVM feature that automatically generates the necessary reflection configuration for plugins annotated with `@RegisterPlugin`.
157
+
158
+
This means you no longer need to manually maintain `reflect-config.json` files for your plugins. The reflection configuration is automatically generated at build time, streamlining the development process for plugins that will be bundled in RESTHeart native builds.
- `GraphQLInterceptor`: Intercepts GraphQL requests (available since RESTHeart v7)
25
25
- `ProxyInterceptor`: Intercepts proxied requests
26
26
27
27
NOTE: `MongoInterceptor` is particularly useful as it allows intercepting requests to the `MongoService`, adding logic to its data API. For instance, the following response interceptor removes the property `secret` from `GET /coll`.
28
28
29
+
NOTE: `GraphQLInterceptor` became available in RESTHeart v7 when `GraphQLRequest` was moved to `restheart-commons`, enabling plugin developers to intercept and modify GraphQL requests and responses. This allows implementing custom logic such as query validation, result transformation, or access logging for GraphQL operations.
Copy file name to clipboardExpand all lines: docs/plugins/services.adoc
+68Lines changed: 68 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -83,12 +83,80 @@ The following table describes the arguments of the annotation for Services:
83
83
|`true` to require successful authentication and authorization to be invoked; can be overridden by the service configuration option `secure`
84
84
|no
85
85
|`false`
86
+
|`blocking`
87
+
|`true` to execute the service in the worker thread pool (blocking mode), `false` to execute in the IO thread (non-blocking mode)
88
+
|no
89
+
|`true`
86
90
|`dontIntercept`
87
91
|list of interceptPoints to be executed on requests handled by the service, e.g. `dontIntercept = { InterceptPoint.ANY, InterceptPoint.RESPONSE }`
88
92
|no
89
93
|`{}`
90
94
|===
91
95
96
+
=== Blocking vs Non-Blocking Services
97
+
98
+
RESTHeart allows you to control the execution model of your services using the `blocking` parameter in the `@RegisterPlugin` annotation.
99
+
100
+
==== Blocking Services (Default)
101
+
102
+
By default, services are executed in **blocking mode** (`blocking = true`). In this mode, when a request arrives, it is dispatched to a worker thread from the thread pool whose size is configured by the `worker-threads` parameter.
103
+
104
+
This concurrency model performs well for CPU-bound and blocking operations, such as:
105
+
- MongoDB operations executed with the `mongodb-driver-sync`
106
+
- Database queries
107
+
- File I/O operations
108
+
- Network calls to external services
109
+
110
+
[source,java]
111
+
----
112
+
@RegisterPlugin(
113
+
name = "blocking-service",
114
+
description = "A service that performs blocking operations",
115
+
blocking = true) // Default value, can be omitted
116
+
public class BlockingService implements JsonService {
117
+
@Override
118
+
public void handle(JsonRequest req, JsonResponse res) {
119
+
// Blocking operation - this will be executed in a worker thread
120
+
var result = performDatabaseQuery();
121
+
res.setContent(result);
122
+
}
123
+
}
124
+
----
125
+
126
+
==== Non-Blocking Services
127
+
128
+
For non-blocking operations, you can specify `blocking = false`. In this mode, the service is executed directly by the IO thread, avoiding the overhead of thread dispatching and context switching.
129
+
130
+
This approach follows the **Event Loop** concurrency model and can perform better for:
131
+
- Reactive operations
132
+
- Async computations
133
+
- Services that don't perform blocking I/O
134
+
135
+
[source,java]
136
+
----
137
+
@RegisterPlugin(
138
+
name = "non-blocking-service",
139
+
description = "A service that performs non-blocking operations",
140
+
blocking = false) // Enable non-blocking mode
141
+
public class NonBlockingService implements JsonService {
142
+
@Override
143
+
public void handle(JsonRequest req, JsonResponse res) {
144
+
// Non-blocking operation - executed directly by IO thread
145
+
var result = performAsyncComputation();
146
+
res.setContent(result);
147
+
}
148
+
}
149
+
----
150
+
151
+
==== Performance Considerations
152
+
153
+
- **Blocking services**: Better for CPU-intensive tasks and operations that involve waiting for I/O
154
+
- **Non-blocking services**: Better for lightweight operations and reactive programming patterns
155
+
156
+
WARNING: Be careful not to perform blocking operations (like database calls) in non-blocking services, as this will block the IO thread and negatively impact performance.
157
+
158
+
Since RESTHeart uses Virtual Threads, there are virtually no limits on the number of blocking threads.
159
+
92
160
=== Service with custom generic types
93
161
94
162
To implement a `Service` that handles different types of `Request` and `Response`, it must implement the base `Service` interface.
Copy file name to clipboardExpand all lines: docs/upgrade-to-v8.adoc
+22Lines changed: 22 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -295,6 +295,28 @@ public void init() {
295
295
}
296
296
```
297
297
298
+
=== MongoService Driver Update
299
+
300
+
RESTHeart v8 completes the migration from `mongo-driver-legacy` to `mongo-driver-sync` that was started in v7.
301
+
302
+
*Impact for Plugin Developers*
303
+
304
+
This change affects plugins that:
305
+
- Use `@Inject("mclient")` to access the MongoDB client
306
+
- Interact with MongoDB through the MongoService
307
+
- Implement custom MongoDB operations
308
+
309
+
*Benefits*
310
+
311
+
- Improved performance and stability
312
+
- Better alignment with MongoDB's current driver architecture
313
+
- Enhanced support for modern MongoDB features
314
+
- Consistent synchronous API patterns
315
+
316
+
*Migration Notes*
317
+
318
+
No code changes are required for existing plugins using `@Inject("mclient")`, as the injected `MongoClient` interface remains the same. The underlying implementation has been updated to use the modern MongoDB driver.
319
+
298
320
=== Lazy-load Request Content
299
321
300
322
Up to RESTHeart v7, requests processed by the `MongoService` are designed to lazy-load their content. This means that the request body is only read when `MongoRequest.getContent()` is invoked for the first time.
0 commit comments