# Holon Platform Project Reactor integration Module - Reference manual

version 5.2.1

Copyright © 2016-2018

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.2.1</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.2.1</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.2.1</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.2.1</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 creation examples

    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

##### 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 configuration `target` 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.

##### 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`

##### 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

##### 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

##### 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

##### 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 the `authorizationBasic(String username, String password)` builder method.

- The `Bearer` authorization scheme, providing a token, through the `authorizationBearer(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 the `HttpMethod` 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 a `Flux` 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 HTTP `GET` method and obtain the response entity as an `InputStream`. 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 HTTP `GET` method and obtain the response entity contents as a `Flux` 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 HTTP `POST` and directly obtain the `Location` response header value as a Java `URI` 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` | Invoke the request and receive a response back. | HTTP method Optional `RequestEntity` Expected response entity type (`Void` for none) | A `Mono` of `ReactiveResponseEntity` type with the expected response entity payload type | None
`invokeForSuccess` | Invoke the request and receive a response back only if the response has a success (`2xx`) status code. | HTTP method Optional `RequestEntity` Expected response entity type (`Void` for none) | A `Mono` of `ReactiveResponseEntity` type with the provided response entity payload type | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown
`invokeForEntity` | Invoke the request and receive back the response content entity, already deserialized in the expected response type. | HTTP method Optional `RequestEntity` Expected response entity type | A `Mono` with the response entity value, already deserialized in the expected response entity type | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown
`invokeForFlux` | Invoke the request and receive back a response content entity, already deserialized in a `Flux` of the expected response type. | HTTP method Optional `RequestEntity` Expected response entity type | A `Flux` with the response entity values, already deserialized in the expected response entity type | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown

By method invocations:

1. `GET`:

Operation | Parameters | Returns | Response status handling
--- | --- | --- | ---
`get` | Expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of `ReactiveResponseEntity<T>` type, with expected response entity payload type | None
`getForEntity` | Expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of the response entity value (`T`), already deserialized in the expected response entity type | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown
`getForStream` | None | A `Mono` of the response payload `InputStream` | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown
`getAsList` | Expected response entity type (`Class<T>`) | A `Flux` of the deserialized response entities using the provided response entity type | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown

2. `POST`:

Operation | First parameter | Second parameter | Returns | Response status handling
--- | --- | --- | --- | ---
`post` | The request entity represented as `RequestEntity` instance | Optional expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of `ReactiveResponseEntity<T>` type, with expected response entity payload type. If the second parameter is not specified, a `Void` type `ReactiveResponseEntity` is returned | None
`postForEntity` | The request entity represented as `RequestEntity` instance | Expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of the response entity value (`T`), already deserialized in the expected response entity type | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown
`postForLocation` | The request entity represented as `RequestEntity` instance | None | A `Mono` of the `Location` response header value | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown

3. `PUT`:

Operation | First parameter | Second parameter | Returns | Response status handling
--- | --- | --- | --- | ---
`put` | The request entity represented as `RequestEntity` instance | Optional expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of `ReactiveResponseEntity<T>` type, with expected response entity payload type. If the second parameter is not specified, a `Void` type `ReactiveResponseEntity` is returned | None
`putForEntity` | The request entity represented as `RequestEntity` instance | Expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of the response entity value (`T`), already deserialized in the expected response entity type | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown

4. `PATCH`:

Operation | First parameter | Second parameter | Returns | Response status handling
--- | --- | --- | --- | ---
`patch` | The request entity represented as `RequestEntity` instance | Optional expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of `ReactiveResponseEntity<T>` type, with expected response entity payload type. If the second parameter is not specified, a `Void` type `ReactiveResponseEntity` is returned | None
`patchForEntity` | The request entity represented as `RequestEntity` instance | Expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of the response entity value (`T`), already deserialized in the expected response entity type | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown

5. `DELETE`:

Operation | Parameter | Returns | Response status handling
--- | --- | --- | ---
`delete` | Optional expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of `ReactiveResponseEntity<Void>` type | None
`deleteOrFail` | None | A `Mono` of `Void` type | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown
`deleteForEntity` | Expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of the response entity value (`T`), already deserialized in the expected response entity type | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown

6. `OPTIONS`:

Operation | Parameter | Returns | Response status handling
--- | --- | --- | ---
`options` | Optional expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of `ReactiveResponseEntity<T>` type, with expected response entity payload type. If the second parameter is not specified, a `Void` type `ReactiveResponseEntity` is returned | None
`optionsForEntity` | Expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of the response entity value (`T`), already deserialized in the expected response entity type | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown

7. `TRACE`:

Operation | Parameter | Returns | Response status handling
--- | --- | --- | ---
`trace` | Optional expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of `ReactiveResponseEntity<T>` type, with expected response entity payload type. If the second parameter is not specified, a `Void` type `ReactiveResponseEntity` is returned | None
`traceForEntity` | Expected response entity type, either using a `Class<T>` or a `ResponseType<T>` to handle generic types | A `Mono` of the response entity value (`T`), already deserialized in the expected response entity type | If the response status code is not `2xx`, an `UnsuccessfulResponseException` is thrown

8. `HEAD`:

Operation | Returns | Response status handling
--- | --- | ---
`head` | A `Void` type `ResponseEntity` | A `Mono` of `ReactiveResponseEntity<Void>` type

#### 4.10. `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.2.1</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