From 740a94b20259ded197cc8a412f3c4b5fbe9c2799 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 9 Mar 2018 12:17:24 +0000 Subject: [PATCH] Make Gson special config conditional on Boot 1.5 That was the samples still work with Spring Boot 2.0.0. Fixes gh-157 (but we should add some tests) --- .../function/web/flux/FunctionController.java | 3 +- ...tpMessageConvertersAutoConfiguration.java} | 59 ++++++++++++------- .../web/flux/ReactorAutoConfiguration.java | 23 -------- .../main/resources/META-INF/spring.factories | 3 +- 4 files changed, 41 insertions(+), 47 deletions(-) rename spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/{BetterGsonHttpMessageConverter.java => GsonHttpMessageConvertersAutoConfiguration.java} (78%) diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/FunctionController.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/FunctionController.java index f8e97c000..51c1797b1 100644 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/FunctionController.java +++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/FunctionController.java @@ -22,6 +22,7 @@ import java.util.function.Supplier; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.reactivestreams.Publisher; import org.springframework.cloud.function.context.catalog.FunctionInspector; import org.springframework.cloud.function.context.message.MessageUtils; @@ -99,7 +100,7 @@ public class FunctionController { @GetMapping(path = "/**") @ResponseBody - public Object get( + public Publisher get( @RequestAttribute(required = false, name = "org.springframework.cloud.function.web.flux.constants.WebRequestConstants.function") Function, Flux> function, @RequestAttribute(required = false, name = "org.springframework.cloud.function.web.flux.constants.WebRequestConstants.supplier") Supplier> supplier, @RequestAttribute(required = false, name = "org.springframework.cloud.function.web.flux.constants.WebRequestConstants.argument") String argument) { diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/BetterGsonHttpMessageConverter.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/GsonHttpMessageConvertersAutoConfiguration.java similarity index 78% rename from spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/BetterGsonHttpMessageConverter.java rename to spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/GsonHttpMessageConvertersAutoConfiguration.java index aaf31dc49..08f917733 100644 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/BetterGsonHttpMessageConverter.java +++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/GsonHttpMessageConvertersAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2016-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,42 +22,57 @@ import java.io.OutputStreamWriter; import java.io.Reader; import java.lang.reflect.Type; import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import com.google.gson.Gson; import com.google.gson.JsonIOException; import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.web.HttpMessageConverters; +import org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.AbstractGenericHttpMessageConverter; +import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; +import org.springframework.http.converter.json.GsonHttpMessageConverter; import org.springframework.util.Assert; -/** - * Implementation of {@link org.springframework.http.converter.HttpMessageConverter} that - * can read and write JSON using the - * Google Gson library's {@link Gson} - * class. - * - *

- * This converter can be used to bind to typed beans or untyped {@code HashMap}s. By - * default, it supports {@code application/json} and {@code application/*+json} with - * {@code UTF-8} character set. - * - *

- * Tested against Gson 2.6; compatible with Gson 2.0 and higher. - * - * @author Roy Clarkson - * @since 4.1 - * @see #setGson - * @see #setSupportedMediaTypes - */ -public class BetterGsonHttpMessageConverter - extends AbstractGenericHttpMessageConverter { +// TODO: remove this when https://jira.spring.io/browse/SPR-16529 is resolved +@Configuration +@ConditionalOnClass(HttpMessageConverters.class) +@AutoConfigureBefore(HttpMessageConvertersAutoConfiguration.class) +public class GsonHttpMessageConvertersAutoConfiguration { + + @Bean + public HttpMessageConverters httpMessageConverters(Gson gson) { + List> converters = new ArrayList<>(); + for (HttpMessageConverter converter : new HttpMessageConverters() + .getConverters()) { + if (converter instanceof GsonHttpMessageConverter) { + BetterGsonHttpMessageConverter gsonConverter = new BetterGsonHttpMessageConverter(); + gsonConverter.setGson(gson); + converters.add(gsonConverter); + } + else { + converters.add(converter); + } + } + return new HttpMessageConverters(false, converters); + } + +} + +class BetterGsonHttpMessageConverter extends AbstractGenericHttpMessageConverter { public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/ReactorAutoConfiguration.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/ReactorAutoConfiguration.java index b39872094..af002ba84 100644 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/ReactorAutoConfiguration.java +++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/ReactorAutoConfiguration.java @@ -24,13 +24,11 @@ import com.google.gson.Gson; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.web.HttpMessageConverters; -import org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration; import org.springframework.cloud.function.context.FunctionCatalog; import org.springframework.cloud.function.context.catalog.FunctionInspector; import org.springframework.cloud.function.web.flux.request.FluxHandlerMethodArgumentResolver; @@ -41,8 +39,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.json.GsonHttpMessageConverter; import org.springframework.util.ClassUtils; import org.springframework.web.method.support.AsyncHandlerMethodReturnValueHandler; import org.springframework.web.method.support.HandlerMethodArgumentResolver; @@ -58,7 +54,6 @@ import reactor.core.publisher.Flux; @Configuration @ConditionalOnWebApplication @ConditionalOnClass({ Flux.class, AsyncHandlerMethodReturnValueHandler.class }) -@AutoConfigureBefore(HttpMessageConvertersAutoConfiguration.class) @Import(FunctionController.class) public class ReactorAutoConfiguration { @@ -78,24 +73,6 @@ public class ReactorAutoConfiguration { return new BasicStringConverter(inspector, beanFactory); } - // TODO: remove this when https://jira.spring.io/browse/SPR-16529 is resolved - @Bean - public HttpMessageConverters httpMessageConverters(Gson gson) { - List> converters = new ArrayList<>(); - for (HttpMessageConverter converter : new HttpMessageConverters() - .getConverters()) { - if (converter instanceof GsonHttpMessageConverter) { - BetterGsonHttpMessageConverter gsonConverter = new BetterGsonHttpMessageConverter(); - gsonConverter.setGson(gson); - converters.add(gsonConverter); - } - else { - converters.add(converter); - } - } - return new HttpMessageConverters(false, converters); - } - @Configuration @ConditionalOnMissingClass("org.springframework.core.ReactiveAdapter") protected static class FluxReturnValueConfiguration { diff --git a/spring-cloud-function-web/src/main/resources/META-INF/spring.factories b/spring-cloud-function-web/src/main/resources/META-INF/spring.factories index 812023313..28b9bbf0d 100644 --- a/spring-cloud-function-web/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-function-web/src/main/resources/META-INF/spring.factories @@ -1,2 +1,3 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.function.web.flux.ReactorAutoConfiguration \ No newline at end of file +org.springframework.cloud.function.web.flux.ReactorAutoConfiguration,\ +org.springframework.cloud.function.web.flux.GsonHttpMessageConvertersAutoConfiguration \ No newline at end of file