....
definitions:
SomeResponse:
type: "object"
required: "data"
properties:
...
data:
description: The binary data of the response object.
type: "string"
format: "byte"
...
24 February 2020
Implementing JAX/RS REST APIs with Swagger/OpenAPI following a Design-First approach starts with the formal specification of the REST API. Then OpenAPI generators are used to create server as well as client stubs. Nowadays, the REST APIs often exchange JSON response and request objects. If binary fields are part of such JSON structures, the generated code encodes/decodes such binary fields. For some combinations of generators the produced client and server do not fit together.
Let’s say an API defines a response model object as follows:
....
definitions:
SomeResponse:
type: "object"
required: "data"
properties:
...
data:
description: The binary data of the response object.
type: "string"
format: "byte"
...
The code produced by generator jaxrs-spec
encodes the data
field as an
array of bytes (numbers). The ASCII string "Java" for example results in an
encoded JSON field "data": [ 112, 141, 166, 141 ]
.
On the other side, the generator java
creates client code that encodes
such byte strings of the API spec as base 64 strings. The sample string
"Java" results in "data": "SmF2YQ=="
.
Eventually, this leads to a situation, the generated client and server are not compatible and cannot exchange binary data.
The simplest approach to fix this issue is by configuring the binary data strategy on the server-side:
import javax.json.bind.*;
import javax.ws.rs.ext.*;
/**
* The JsonbConfigurator configures the binary data strategy of JSON Binding.
* Instead of the default strategy "byte array" the "base 64" encoding is
* activated.
*/
@Provider
public class JsonbConfigurator implements ContextResolver<Jsonb> {
@Override
public Jsonb getContext(Class<?> type) {
JsonbConfig config = getJsonbConfig();
return JsonbBuilder.newBuilder().withConfig(config).build();
}
private JsonbConfig getJsonbConfig() {
return new JsonbConfig().withBinaryDataStrategy(BinaryDataStrategy.BASE_64);
}
}
If you add this class to your JAX/RS server project, client and server both encode and decode binary data as base 64 strings and start to work well together. Such a Jakarta EE based solution should definitely preferred over the customization of generator’s templates, in particular if you take long-term maintainability into account.