From fe2bc9149906d7ebd1129febc34456d75a3505e0 Mon Sep 17 00:00:00 2001 From: Richard Richter Date: Thu, 28 May 2020 15:01:13 +0200 Subject: [PATCH] RestConfig: added fallback */* converter and more explanation comments --- .../midpoint/rest/impl/RestConfig.java | 71 ++++++++++++++++++- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/RestConfig.java b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/RestConfig.java index 9d3a537013f..b50f7cd9a66 100644 --- a/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/RestConfig.java +++ b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/RestConfig.java @@ -6,10 +6,21 @@ */ package com.evolveum.midpoint.rest.impl; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpInputMessage; +import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; +import org.springframework.http.converter.AbstractHttpMessageConverter; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -26,10 +37,16 @@ public class RestConfig implements WebMvcConfigurer { - // TODO probably @Override addArgumentResolvers for @Converter processing? - + /** + * Registers content-types for path extension and request parameter usage. + * Not needed for header-based content negotiation and midPoint typically + * doesn't use this, but it doesn't hurt and may be handy for download URLs. + *

+ * See this + * tutorial for more about content negotiation. + */ @Override - public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { + public void configureContentNegotiation(@NotNull ContentNegotiationConfigurer configurer) { for (MediaType mediaType : MidpointYamlHttpMessageConverter.MEDIA_TYPES) { configurer.mediaType(mediaType.getSubtype(), mediaType); } @@ -53,4 +70,52 @@ public MidpointJsonHttpMessageConverter jsonConverter( PrismContext prismContext, LocalizationService localizationService) { return new MidpointJsonHttpMessageConverter(prismContext, localizationService); } + + /** + * All beans above will be first in the converter list and other Spring converters + * will be available as well. + * We want to add "catch-all" converter for cases like error output for any (even unsupported) + * content type. + */ + @Override + public void extendMessageConverters(List> converters) { + converters.add(new FallbackConverter()); + } + + private static class FallbackConverter extends AbstractHttpMessageConverter { + /** + * Supports all media types - that's the purpose of this converter. + */ + protected FallbackConverter() { + super(MediaType.ALL); + } + + /** + * Supports all object types - that's the purpose of this converter. + */ + @Override + protected boolean supports(@NotNull Class clazz) { + return true; + } + + /** + * Only for output, this can't read anything. + */ + @Override + public boolean canRead(@NotNull Class clazz, @Nullable MediaType mediaType) { + return false; + } + + @Override + protected @NotNull Object readInternal( + @NotNull Class clazz, @NotNull HttpInputMessage inputMessage) { + throw new UnsupportedOperationException("FallbackConverter is write-only"); + } + + @Override + protected void writeInternal(@NotNull Object o, @NotNull HttpOutputMessage outputMessage) + throws IOException, HttpMessageNotWritableException { + outputMessage.getBody().write(o.toString().getBytes(StandardCharsets.UTF_8)); + } + } }