Copyright © 2016-2019
Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
1. Introduction
The Reactor module provides integration between the Holon Platform core APIs, such as Datastore
and RestClient
, and the Project Reactor reactive programming model, using the Flux
and Mono
APIs.
1.1. Sources and contributions
The Holon Platform Reactor module source code is available from the GitHub repository https://github.com/holon-platform/holon-reactor.
See the repository README
file for information about:
-
The source code structure.
-
How to build the module artifacts from sources.
-
Where to find the code examples.
-
How to contribute to the module development.
2. Obtaining the artifacts
The Holon Platform uses Maven for projects build and configuration. All the platform artifacts are published in the Maven Central Repository, so there is no need to explicitly declare additional repositories in your project pom
file.
At the top of each section of this documentation you will find the Maven coordinates (group id, artifact id and version) to obtain the artifact(s) as a dependency for your project.
A BOM (Bill Of Materials) pom
is provided to import the available dependencies for a specific version in your projects. The Maven coordinates for the core BOM are the following:
Maven coordinates:
<groupId>com.holon-platform.reactor</groupId>
<artifactId>holon-reactor-bom</artifactId>
<version>5.5.0</version>
The BOM can be imported in a Maven project in the following way:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.holon-platform.reactor</groupId>
<artifactId>holon-reactor-bom</artifactId>
<version>5.5.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.1. Using the Platform BOM
The Holon Platform provides an overall Maven BOM (Bill of Materials) to easily obtain all the available platform artifacts.
See Obtain the platform artifacts for details.
3. Reactive Datastore
Maven coordinates:
<groupId>com.holon-platform.reactor</groupId>
<artifactId>holon-reactor-datastore</artifactId>
<version>5.5.0</version>
The ReactiveDatastore API is the reactive version of the Holon Platform core Datastore API using the Project Reactor programming model.
The ReactiveDatastore
operations provides the same semantic and parameters as the core Datastore
API operations, but use the Project Reactor Mono
and Flux
types as operation results, dependently on the result cardinality.
Additionaly, the ReactiveBulkInsert
, ReactiveBulkUpdate
and ReactiveBulkUpdate
bulk operations handlers are provided to obtain a bulk operation result as a Mono<OperationResult>
type.
The ReactiveQuery API can be used to configure and execute queries, and obtain the query results as Mono
and Flux
types, according to the query projection cardinality.
Finally, a ReactiveTransaction API is available for reactive Datastores which supports transactions, to reactively handle the transactions lifecycle.
See the available ReactiveDatastore
implementations for more information about reactive Datastores.
The MongoDB ReactiveDatastore
implementation documentation is available form here.
4. Reactive RestClient
Maven coordinates:
<groupId>com.holon-platform.reactor</groupId>
<artifactId>holon-reactor-http</artifactId>
<version>5.5.0</version>
The ReactiveRestClient API is the reactive version of the Holon Platform core RestClient API using the Project Reactor programming model.
The ReactiveRestClient
operations provides the same semantic and parameters as the core RestClient
API operations, but use the Project Reactor Mono
and Flux
types as operation results, dependently on the result cardinality.
The ReactiveInvocation
API is used to configure and execute HTTP operations using the REST paradigm, providing the operation results through the Mono
and Flux
types.
4.1. Obtain a ReactiveRestClient
instance
Concrete ReactiveRestClient
implementations are obtained from a ReactiveRestClientFactory, registered using Java service extensions through a com.holonplatform.reactor.http.ReactiveRestClientFactory
file under the META-INF/services
folder.
A ReactiveRestClient
instance can be obtained using one of the create(…)
methods provided by the interface, either specifying the fully qualified class name of the ReactiveRestClient
implementation to obtain or using the default implementation according to the available ReactiveRestClientFactory
within the current ClassLoader
(a specific ClassLoader
can be used instead of the current one).
If more than one RestClienReactiveRestClientFactorytFactory is bound to the same ReactiveRestClient implementation type, or if more than one ReactiveRestClientFactory is available in the ClassLoader when the implementation class is not specified, the ReactiveRestClientFactory to use to build the ReactiveRestClient instance is selected according to the factory priority level, which can be specified using the Priority annotation, if available.
|
The forTarget(…) static methods of the ReactiveRestClient interface can be used as shorters to create a ReactiveRestClient using the default implementation and setting a default base URI to use for the client requests.
|
ReactiveRestClient client = ReactiveRestClient.create(); (1)
client = ReactiveRestClient.create("com.holonplatform.jaxrs.client.reactor.JaxrsReactiveReactiveRestClient"); (2)
client = ReactiveRestClient.forTarget("https://host/api"); (3)
1 | Create a ReactiveRestClient API using the default available implementation for current ClassLoader |
2 | Create a ReactiveRestClient API using a specific implementation class name |
3 | Create a ReactiveRestClient API using the default available implementation and setting the default base URI |
4.1.1. Available implementations
The ReactiveRestClient
implementations provided by the Holon Platform are are:
-
A JAX-RS based implementation, using a standard JAX-RS
Client
to perform invocations, available from the holon-jaxrs.html#JaxrsReactiveRestClient[Holon platform JAX-RS module]; -
A Spring based implementation, using the Spring
WebClient
API to perform invocations;
4.2. Configure defaults
The ReactiveRestClient
API supports some default configuration attributes, which will be used for each request performed using a ReactiveRestClient
instance:
-
A default target, i.e. the default base URI which will be used for all the requests performed with the
ReactiveRestClient
API, unless overridden using the specific request configurationtarget
method. -
A set of default headers to be included in all the requests performed with the
ReactiveRestClient
API.
ReactiveRestClient client = ReactiveRestClient.create();
client.defaultTarget(new URI("https://rest.api.example")); (1)
client.withDefaultHeader(HttpHeaders.ACCEPT_LANGUAGE, "en-CA"); (2)
client.withDefaultHeader(HttpHeaders.ACCEPT_CHARSET, "utf-8"); (3)
1 | Set the default target request base URI, which will be used as target URI for every request configured using request() , if not overridden using target(URI) . |
2 | Add a default request header which will be automatically added to every invocation request message |
3 | Add another default request header |
4.3. Build and configure a request
To build a client request, the ReactiveRequestDefinition API is used, which represents both a fluent builder to configure the request message and a ReactiveInvocation API to perform the actual invocation and obtain a response.
The request can be configured using the ReactiveInvocation
API methods as described below.
4.3.1. Request URI
The request URI can be composed using:
-
A request target, i.e. the base URI of the request. If a default request target was configured for the
ReactiveRestClient
instance, it will be overriden by the specific request target. -
One ore more request *path*s, which will be appended to the base request target URI, adding slash characters to separate them from one another, if necessary.
ReactiveRestClient client = ReactiveRestClient.create();
ReactiveRequestDefinition request = client.request().target(URI.create("https://rest.api.example")); (1)
request = request.path("apimethod"); (2)
request = request.path("subpath"); (3)
1 | Set the request target, i.e. the base request URI |
2 | Set the request path, which will be appended to the base request URI |
3 | Append one more path to the request URI. The actual URI will be: https://rest.api.example/apimethod/subpath |
4.3.2. URI template variable substitution values
The ReactiveRestClient
API supports URI template variables substitution through the resolve(…)
method.
IMPORTART: URI templates variables substitution is only supported for the request URI components specified as path(…)
elements, not for the target(…)
base URI part.
client.request().target("https://rest.api.example").path("/data/{name}/{id}").resolve("name", "test")
.resolve("id", 123); (1)
Map<String, Object> templates = new HashMap<>(1);
templates.put("id", "testValue");
request = client.request().target("https://rest.api.example").path("/test/{id}").resolve(templates); (2)
1 | Subsitute two template variables values |
2 | Subsitute template variables values using a name-value map |
4.3.3. URI query parameters
The ReactiveRestClient
API supports URI query parameters specification, with single or multiple values, through the queryParameter(…)
methods.
client.request().queryParameter("parameter", "value") (1)
.queryParameter("multiValueParameter", 1, 2, 3); (2)
1 | Set a single value query parameter |
2 | Set a multiple values query parameter |
4.3.4. Request headers
HTTP headers can be added to the request using the generic header(String name, String… values)
method (supporting single or multiple header values) or a set of frequently used headers convenience setter methods, such as accept
, acceptLanguage
(supporting Java Locale
types as arguments) and cacheControl
.
The HttpHeaders interface can be used to refer to HTTP header names as constants. |
The MediaType enumeration can be used for the Accept header values using the accept(MediaType… mediaTypes) builder method.
|
The CacheControl API provides a fluent builder to build and set a Cache-Control header value for the request, using the cacheControl(CacheControl cacheControl) builder method.
|
client.request().header("Accept", "text/plain"); (1)
client.request().header(HttpHeaders.ACCEPT, "text/plain"); (2)
client.request().accept("text/plain", "text/xml"); (3)
client.request().accept(MediaType.APPLICATION_JSON); (4)
client.request().acceptEncoding("gzip"); (5)
client.request().acceptCharset("utf-8"); (6)
client.request().acceptCharset(Charset.forName("utf-8")); (7)
client.request().acceptLanguage("en-CA"); (8)
client.request().acceptLanguage(Locale.US, Locale.GERMANY); (9)
client.request().cacheControl(CacheControl.builder().noCache(true).noStore(true).build()); (10)
1 | Set a request header, providing its name and its value |
2 | Set a request header, providing its name through the HttpHeaders enumeration and its value |
3 | Set the request Accept header values |
4 | Set the request Accept header value using the MediaType enumeration |
5 | Set the request Accept-Encoding header value |
6 | Set the request Accept-Charset header value |
7 | Set the request Accept-Charset header value using the Java Charset class |
8 | Set the request Accept-Language header value |
9 | Set the request Accept-Language header values using the Java Locale class |
10 | Build a CacheControl definition and set it as Cache-Control request header value |
4.3.5. Authorization headers
The ReactiveRestClient
API provides two convenience request builder methods to setup a request Authorization
header using:
-
The
Basic
authorization scheme, providing a username and a password, through theauthorizationBasic(String username, String password)
builder method. -
The
Bearer
authorization scheme, providing a token, through theauthorizationBearer(String bearerToken)
builder method.
client.request().authorizationBasic("username", "password"); (1)
client.request().authorizationBearer("An389fz56xsr7"); (2)
1 | Set the Authorization request header value using the Basic scheme and providing the credentials. Username and password will be encoded according to the HTTP specifications |
2 | Set the Authorization request header value using the Bearer scheme and providing the bearer token value. See RFC6750 |
4.4. Invoke the request and obtain a response
The ReactiveRequestDefinition
API can be used to perform the actual invocation and obtain a response.
The ReactiveRequestDefinition
API provides a generic invocation method:
<T, R> Mono<ReactiveResponseEntity<T>> invoke(HttpMethod method, RequestEntity<R> requestEntity, ResponseType<T> responseType)
This method requires the following parameters:
-
The HTTP method to use to perform the request (
GET
,POST
, and so on), specified using theHttpMethod
enumeration. -
An optional request entity, i.e. the request message payload (body), represented through the
RequestEntity
API. -
The expected response entity type using the
ResponseType
class, to declare the Java type of the response payload and apply a suitable converter, if available, to obtain the HTTP response body as the expected Java type.
The method returns a Mono
of ReactiveResponseEntity
type, which can be used to reactively handle the operation response.
The ReactiveResponseEntity
API is a ResponseEntity
extension which can be used to:
-
Inspect the response message, for example to obtain the HTTP response status code, as a number or represented through the HttpStatus enumeration.
-
Obtain the HTTP response raw payload or get it as a Java object, unmarshalled by a suitable converter which must be available from the concrete
ReactiveRestClient
API implementation. -
Obtain the response entity as a
Mono
or aFlux
of the required type.
For non textual request or response payload types, any marshalling/unmarshalling strategy and implementation must be provided by the concrete ReactiveRestClient API. See the specific Available implementations documentation for additional information.
|
See the next sections for details about the invocation parameters and return types.
4.5. Request entity
The RequestEntity interface can be used to provide a request entity to the ReactiveRestClient
API invocation methods, i.e. the request message payload.
The request entity is represented by a Java object and its serialization format is specified using a media type declaration (i.e. a MIME type definition) through the Content-Type
request header value.
Depending on the ReactiveRestClient API implementation used, you must ensure the request media type is supported and a suitable request message body converter is available to deal with the Java object type and the media type of the request entity.
|
The RequestEntity
interface provides a set of convenience static methods to build a request entity instance using the most common media types, such a text/plain
, application/json
, application/xml
and application/x-www-form-urlencoded
(the latter also providing a fluent form data builder method).
RequestEntity<String> request1 = RequestEntity.text("test"); (1)
RequestEntity<TestData> request2 = RequestEntity.json(new TestData()); (2)
RequestEntity request3 = RequestEntity
.form(RequestEntity.formBuilder().set("value1", "one").set("value2", "a", "b").build()); (3)
1 | Build a text/plain type request entity, using test as request entity value |
2 | Build a application/json type request entity, using a TestData class instance as request entity value |
3 | Build a application/x-www-form-urlencoded type request entity, using the formBuilder method to build the form data map |
The RequestEntity.EMPTY
constant value can be used to provide an empty request entity.
RequestEntity<?> emptyRequest = RequestEntity.EMPTY; (1)
1 | Build an empty request empty, to provide a request message without a payload |
4.6. Response type
The ResponseType interface can be used to provide the expected response entity type to the ReactiveRestClient
API invocation methods.
In addition to a simple Java class type, a parametrized type can be declared, allowing to use Java generic types as response types.
ResponseType<TestData> responseType1 = ResponseType.of(TestData.class); (1)
ResponseType<List<TestData>> responseType2 = ResponseType.of(TestData.class, List.class); (2)
1 | Declares a response type as TestData type |
2 | Declares a response type as a List of TestData types |
4.7. Response entity
The ReactiveResponseEntity interface is used by ReactiveRestClient
API to represent the invocation response and to deal with the response entity obtained as invocation result.
Since it is a HttpResponse
instance, the ReactiveRestClient
API can be used to inspect the response message, for example the HTTP message headers, including the HTTP status code.
Mono<ReactiveResponseEntity<TestData>> response = ReactiveRestClient
.forTarget("https://rest.api.example/testget").request().accept(MediaType.APPLICATION_JSON)
.get(TestData.class); (1)
response.doOnSuccess(r -> {
HttpStatus status = r.getStatus(); (2)
int statusCode = r.getStatusCode(); (3)
long contentLength = r.getContentLength().orElse(-1L); (4)
Optional<String> value = r.getHeaderValue("HEADER_NAME"); (5)
});
1 | Perform a GET request, setting the Accept header as application/json and declaring the TestData class as expected response entity Java type |
2 | Get the response status as HttpStatus enumeration value |
3 | Get the response status code |
4 | Get the Content-Length header value |
5 | Get a generic header value |
To obtain the response entity value as the expected Java type, the asMono()
method can be used. The returned object generic type is provided according to the specified Response type, so the payload value will be and instance of the expected response Java type.
Furthermore, the ReactiveResponseEntity
API makes available the asMono(Class<E> entityType)
method, to obtain the response entity as a different type from the one specified with the Response type invocation parameter, if the media type is supported by the concrete ReactiveRestClient
API implementation and a suitable converter is available.
In a similar way, the asFlux(Class<E> entityType)
and asInputStream()
methods provide the response entity content as a Flux
and as a InputStream
respectively.
Mono<ReactiveResponseEntity<TestData>> response = ReactiveRestClient
.forTarget("https://rest.api.example/testget").request().accept(MediaType.APPLICATION_JSON)
.get(TestData.class); (1)
response.doOnSuccess(r -> {
Mono<TestData> entity = r.asMono(); (2)
Mono<String> asString = r.asMono(String.class); (3)
});
1 | Perform a GET request, setting the Accept header as application/json and declaring the TestData class as expected response entity Java type |
2 | Get the response entity Mono value as a TestData type, according to the declared response type |
3 | Get the response entity Mono value as a String |
Depending on the concrete ReactiveRestClient API implementation, you must ensure the response media type is supported and a suitable message body converter is available to deal with the Java object type and the media type of the response entity.
|
4.8. Specific request invocation methods
In most cases, it is easier and faster to use HTTP method-specific invocation methods, made available by the ReactiveRestClient
invocation API.
Each invocation method is relative to a specific HTTP request method and it is named accordingly. More than one method version is provided for each HTTP request method, providing the most suitable parameters and response types for for the most common situations.
For each HTTP request method (apart from the HEAD
request method), the ReactiveRestClient
API makes available a set of invocation methods organized as follows:
1. A set of methods to optionally provide a Request entity and to obtain a Response entity. If the response is expected to contain a payload which has to be deserialized into a Java object, the Response type can be specified, either as a simple or parametrized Java class.
final ReactiveRestClient client = ReactiveRestClient.forTarget("https://rest.api.example/test");
Mono<ReactiveResponseEntity<TestData>> response = client.request().get(TestData.class); (1)
response = client.request().get(ResponseType.of(TestData.class)); (2)
response = client.request().put(RequestEntity.json(new TestData()), TestData.class); (3)
1 | Perform an invocation using the GET method and obtain a ResponseEntity expecting the TestData class as response entity type |
2 | The same invocation using the ResponseType API to specify the expected response entity type |
3 | Perform an invocation using the PUT method and providing an application/json type request entity, expecting a TestData response entity type |
When a response entity is not expected, this category of invocation methods return a Void
type ReactiveResponseEntity
.
Mono<ReactiveResponseEntity<Void>> response2 = client.request().post(RequestEntity.json(new TestData())); (1)
response2.doOnSuccess(r -> {
HttpStatus status = r.getStatus(); (2)
});
1 | Perform an invocation using the POST method and providing an application/json type request entity, but no response entity is expected |
2 | Get the response HTTP status |
2. A set of method to directly obtain the deserialized response entity value, named with the ForEntity
suffix. This methods expects a successful response (i.e. a response with a 2xx
HTTP status code), otherwise an UnsuccessfulResponseException
is thrown. The exception which can be inspected to obtain the response status code and the response itself.
Mono<TestData> value = client.request().getForEntity(TestData.class); (1)
Mono<List<TestData>> values = client.request().getForEntity(ResponseType.of(TestData.class, List.class)); (2)
1 | Perform an invocation using the GET method and directly obtain the TestData type response entity value, if available |
2 | Perform an invocation using the GET method and directly obtain a List of TestData type response entity values, if available |
The UnsuccessfulResponseException type, which is thrown by the xxxForEntity
invocation methods when the response status code do not belongs to the 2xx
family, provides some information about the invocation failure:
-
The actual response status code.
-
A reference to the actual response entity instance.
try {
client.request().getForEntity(TestData.class);
} catch (UnsuccessfulResponseException e) {
// got a response with a status code different from 2xx
int httpStatusCode = e.getStatusCode(); (1)
Optional<HttpStatus> sts = e.getStatus(); (2)
ResponseEntity<?> theResponse = e.getResponse(); (3)
}
1 | Get the actual response status code |
2 | Get the response status code as a HttpStatus |
3 | Get the ResponseEntity instance |
3. A set of convenience methods are provided for frequent needs and situations, for example:
-
A
getForStream
method to perform a request using the HTTPGET
method and obtain the response entity as anInputStream
. This can be useful, for example, for API invocations which result is a stream of byte or characters.
Mono<InputStream> responseEntityStream = client.request().getForStream();
-
A
getAsList
method, to perform a request using the HTTPGET
method and obtain the response entity contents as aFlux
of deserialized Java objects in a specified expected response type.
Flux<TestData> collectionOfValues = client.request().getAsList(TestData.class);
-
A
postForLocation
to perform a request using the HTTPPOST
and directly obtain theLocation
response header value as a JavaURI
instance, if available.
Mono<URI> locationHeaderURI = client.request().postForLocation(RequestEntity.json(new TestData()));
4.9. RestClient
API invocation methods reference
Below a reference list of the ReactiveRestClient
invocation API, available from the reactive request definition API:
ReactiveRestClient reactiveRestClient = ReactiveRestClient.forTarget("http://api.example"); // Obtain a
// ReactiveRestClient
ReactiveRequestDefinition request = reactiveRestClient.request(); // Request definition
Generic invocations:
Operation | Description | Parameters | Returns | Response status handling |
---|---|---|---|---|
|
Invoke the request and receive a response back. |
|
A |
None |
|
Invoke the request and receive a response back only if the response has a success ( |
|
A |
If the response status code is not |
|
Invoke the request and receive back the response content entity, already deserialized in the expected response type. |
|
A |
If the response status code is not |
|
Invoke the request and receive back a response content entity, already deserialized in a |
|
A |
If the response status code is not |
By method invocations:
1. GET
:
Operation | Parameters | Returns | Response status handling |
---|---|---|---|
|
Expected response entity type, either using a |
A |
None |
|
Expected response entity type, either using a |
A |
If the response status code is not |
|
None |
A |
If the response status code is not |
|
Expected response entity type ( |
A |
If the response status code is not |
2. POST
:
Operation | First parameter | Second parameter | Returns | Response status handling |
---|---|---|---|---|
|
The request entity represented as |
Optional expected response entity type, either using a |
A |
None |
|
The request entity represented as |
Expected response entity type, either using a |
A |
If the response status code is not |
|
The request entity represented as |
None |
A |
If the response status code is not |
3. PUT
:
Operation | First parameter | Second parameter | Returns | Response status handling |
---|---|---|---|---|
|
The request entity represented as |
Optional expected response entity type, either using a |
A |
None |
|
The request entity represented as |
Expected response entity type, either using a |
A |
If the response status code is not |
4. PATCH
:
Operation | First parameter | Second parameter | Returns | Response status handling |
---|---|---|---|---|
|
The request entity represented as |
Optional expected response entity type, either using a |
A |
None |
|
The request entity represented as |
Expected response entity type, either using a |
A |
If the response status code is not |
5. DELETE
:
Operation | Parameter | Returns | Response status handling |
---|---|---|---|
|
Optional expected response entity type, either using a |
A |
None |
|
None |
A |
If the response status code is not |
|
Expected response entity type, either using a |
A |
If the response status code is not |
6. OPTIONS
:
Operation | Parameter | Returns | Response status handling |
---|---|---|---|
|
Optional expected response entity type, either using a |
A |
None |
|
Expected response entity type, either using a |
A |
If the response status code is not |
7. TRACE
:
Operation | Parameter | Returns | Response status handling |
---|---|---|---|
|
Optional expected response entity type, either using a |
A |
None |
|
Expected response entity type, either using a |
A |
If the response status code is not |
8. HEAD
:
Operation | Returns | Response status handling |
---|---|---|
|
A |
A |
4.9.1. Property
and PropertyBox
support
The ReactiveRestClient
API fully supports the Holon Platform Property model when used along with the PropertyBox data type as a request/response entity in RESTful API calls.
Regarding the JSON media type, the PropertyBox
type marshalling and unmarshalling support is provided by the Holon Platform JSON module. For the builtin ReactiveRestClient
API implementations, the PropertyBox
type JSON support is automatically setted up when the suitable Holon platform JSON module artifacts are available in classpath.
When a response entity value has to be deserialized into a PropertyBox
object type, the property set to be used must be specified along with the reponse entity type, in order to instruct the JSON module unmarshallers about the property set with which to build the response PropertyBox
instances.
For this purpose, the ReactiveRestClient
invocation API propertySet(…)
methods can be used to specify the property set with which to obtain a PropertyBox
type response entity value.
final PathProperty<Integer> CODE = create("code", int.class);
final PathProperty<String> VALUE = create("value", String.class);
final PropertySet<?> PROPERTIES = PropertySet.of(CODE, VALUE);
ReactiveRestClient client = ReactiveRestClient.create();
Mono<PropertyBox> box = client.request().target("https://rest.api.example").path("/apimethod")
.propertySet(PROPERTIES).getForEntity(PropertyBox.class); (1)
Mono<PropertyBox> box2 = client.request().target("https://rest.api.example").path("/apimethod")
.propertySet(CODE, VALUE).getForEntity(PropertyBox.class); (2)
Flux<PropertyBox> boxes = client.request().target("https://rest.api.example").path("/apimethod")
.propertySet(PROPERTIES).getAsList(PropertyBox.class); (3)
1 | GET request for a PropertyBox type Mono response, using PROPERTIES as property set |
2 | GET request for a PropertyBox type Mono response, using directly an array of properties |
3 | GET request for a Flux of PropertyBox type response, using PROPERTIES as property set |
5. ReactiveRestClient
implementation using the Spring WebClient
API
Maven coordinates:
<groupId>com.holon-platform.reactor</groupId>
<artifactId>holon-reactor-spring</artifactId>
<version>5.5.0</version>
The holon-reactor-spring
artifact provides a Reactive RestClient implementation using the Spring 5+ WebClient
API.
The Spring ReactiveRestClient
implementation is represented by the SpringReactiveRestClient interface, which provides a create(WebClient webClient)
method to create a ReactiveRestClient
instance using a provided Spring WebClient
reference.
WebClient webClient = getWebClient(); (1)
ReactiveRestClient client = SpringReactiveRestClient.create(webClient); (2)
1 | Create or obtain a WebClient implementation |
2 | Create a ReactiveRestClient using the WebClient implementation |
When a WebClient
instance is available as a Holon Platform [Context] resource, a ReactiveRestClientFactory
is automatically registered to provide a SpringReactiveRestClient
implementation using that WebClient
implementation. This way, the default ReactiveRestClient.create(…)
static methods can be used to obtain a ReactiveRestClient
implementation.
If the Spring context scope is enabled with the default beans lookup strategy, it is sufficient that a WebClient bean type is registered in the Spring application context to obtain it as a context resource.
|
@Configuration
@EnableBeanContext (1)
class Config {
@Bean (2)
public WebClient webClient() {
return WebClient.create();
}
}
void restclient() {
ReactiveRestClient client = ReactiveRestClient.create(); (3)
client = ReactiveRestClient.create(SpringReactiveRestClient.class.getName()); (4)
}
1 | Use the @EnableBeanContext to enable Spring beans context |
2 | Provide a WebClient bean definition |
3 | The ReactiveRestClient.create() method can be used to obtain a ReactiveRestClient implementation backed by the defined WebClient bean definition |
4 | If more than one ReactiveRestClientFactory is available, the SpringReactiveRestClient class name can be specified to ensure that a SpringReactiveRestClient type is obtained as a ReactiveRestClient implementation |