Skip to content

Support for media type capabilities

Marcel Konrad requested to merge media-type-capabilities into master

This is draft MR for parsing header "capabilities", which are optional representation features a client can request during content negotiation, such as formatted labels. Its intention is to serve as a foundation for #562 (closed). Each capability is represented by a key-value-pair and needs to be registered for a specific content type. This can be done by using a spring configuration. A client can then request specific capabilities for a given media type by providing additional media type parameters, for example: application/json;formatted-labels=true. Using dependency injection, it is possible to access those parameters in request handler methods by defining an optional MediaTypeCapabilities parameter, which will be automatically parsed and populated with the supported capabilities for the resulting media type. Each capability can have its own unique type that will be parsed if the given capability is present in the request header.

This implementation has the benefit that we do not need to re-declare request handler methods or declare any additional produces headers. We could simply register supported capabilities for a given content type and add a MediaTypeCapabilities parameter to the affected methods, which could then forward the MediaTypeCapabilities instance to the representation adapters, where the actual mapping takes place.

A controller method could look as follows:

@GetMapping("/{id}", produces = ["application/vnd.orkg.resource.v1+json"])
fun findById(
    @PathVariable id: ThingId,
    capabilities: MediaTypeCapabilities
): ResourceRepresentation =
    service.findById(id).mapToResourceRepresentation(capabilities)
        .orElseThrow { ResourceNotFound.withId(id) }

Accessing capability contents looks as follows:

fun method(capabilities: MediaTypeCapabilities) {
    val formattedLabels: Boolean = capabilities.get(FORMATTED_LABEL_CAPABILITY)
    val other: OtherObject = capabilities.get(OTHER_CAPABILITY)
}

Please let me know what you think of the approach, or if you have a better name for it. I thought about "flags", but since values can be of arbitrary types, its not necessarily a "flag". Another idea would be "context".

Edited by Marcel Konrad

Merge request reports