diff --git a/spring-cloud-function-context/pom.xml b/spring-cloud-function-context/pom.xml
index f111e1a40..badafe205 100644
--- a/spring-cloud-function-context/pom.xml
+++ b/spring-cloud-function-context/pom.xml
@@ -32,6 +32,16 @@
spring-boot-configuration-processor
true
+
+ com.google.code.gson
+ gson
+ true
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ true
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java
index dcf7db156..ba415f6b9 100644
--- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java
+++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java
@@ -39,6 +39,9 @@ import java.util.function.Supplier;
import javax.annotation.PreDestroy;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -46,7 +49,10 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.function.context.FunctionCatalog;
import org.springframework.cloud.function.context.FunctionRegistration;
import org.springframework.cloud.function.context.FunctionRegistry;
@@ -62,8 +68,11 @@ import org.springframework.cloud.function.core.FunctionFactoryMetadata;
import org.springframework.cloud.function.core.IsolatedConsumer;
import org.springframework.cloud.function.core.IsolatedFunction;
import org.springframework.cloud.function.core.IsolatedSupplier;
+import org.springframework.cloud.function.json.GsonMapper;
+import org.springframework.cloud.function.json.JacksonMapper;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotatedElementUtils;
@@ -86,6 +95,8 @@ import org.springframework.util.StringUtils;
@ConditionalOnMissingBean(FunctionCatalog.class)
public class ContextFunctionCatalogAutoConfiguration {
+ static final String PREFERRED_MAPPER_PROPERTY = "spring.http.converters.preferred-json-mapper";
+
@Autowired(required = false)
private Map> suppliers = Collections.emptyMap();
@@ -169,6 +180,26 @@ public class ContextFunctionCatalogAutoConfiguration {
}
+ @Configuration
+ @ConditionalOnClass(Gson.class)
+ @Conditional(PreferGsonOrMissingJacksonCondition.class)
+ protected static class GsonConfiguration {
+ @Bean
+ public GsonMapper jsonMapper(Gson gson) {
+ return new GsonMapper(gson);
+ }
+ }
+
+ @Configuration
+ @ConditionalOnClass(ObjectMapper.class)
+ @ConditionalOnProperty(name = ContextFunctionCatalogAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "jackson", matchIfMissing = true)
+ protected static class JacksonConfiguration {
+ @Bean
+ public JacksonMapper jsonMapper(ObjectMapper mapper) {
+ return new JacksonMapper(mapper);
+ }
+ }
+
@Component
protected static class ContextFunctionRegistry {
@@ -643,4 +674,22 @@ public class ContextFunctionCatalogAutoConfiguration {
}
+ private static class PreferGsonOrMissingJacksonCondition extends AnyNestedCondition {
+
+ PreferGsonOrMissingJacksonCondition() {
+ super(ConfigurationPhase.REGISTER_BEAN);
+ }
+
+ @ConditionalOnProperty(name = ContextFunctionCatalogAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "gson", matchIfMissing = false)
+ static class GsonPreferred {
+
+ }
+
+ @ConditionalOnMissingBean(ObjectMapper.class)
+ static class JacksonMissing {
+
+ }
+
+ }
+
}
diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/GsonMapper.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/GsonMapper.java
similarity index 86%
rename from spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/GsonMapper.java
rename to spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/GsonMapper.java
index 061ddbe11..988742094 100644
--- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/GsonMapper.java
+++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/GsonMapper.java
@@ -13,13 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.cloud.function.web.util;
+package org.springframework.cloud.function.json;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.Gson;
+import org.springframework.cloud.function.json.JsonMapper;
import org.springframework.core.ResolvableType;
/**
@@ -45,4 +46,8 @@ public class GsonMapper implements JsonMapper {
return gson.fromJson(json, type);
}
+ @Override
+ public String toString(Object value) {
+ return gson.toJson(value);
+ }
}
diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/JacksonMapper.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JacksonMapper.java
similarity index 78%
rename from spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/JacksonMapper.java
rename to spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JacksonMapper.java
index 4944dcf44..476b99719 100644
--- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/JacksonMapper.java
+++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JacksonMapper.java
@@ -13,13 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.cloud.function.web.util;
+package org.springframework.cloud.function.json;
import java.util.ArrayList;
import java.util.List;
+import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.cloud.function.json.JsonMapper;
+
/**
* @author Dave Syer
*
@@ -53,4 +56,13 @@ public class JacksonMapper implements JsonMapper {
}
}
+ @Override
+ public String toString(Object value) {
+ try {
+ return mapper.writeValueAsString(value);
+ }
+ catch (JsonProcessingException e) {
+ throw new IllegalArgumentException("Cannot convert to JSON", e);
+ }
+ }
}
diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/JsonMapper.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JsonMapper.java
similarity index 90%
rename from spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/JsonMapper.java
rename to spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JsonMapper.java
index 7319cb2fb..41b465e7c 100644
--- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/JsonMapper.java
+++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JsonMapper.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.cloud.function.web.util;
+package org.springframework.cloud.function.json;
import java.util.List;
@@ -27,4 +27,6 @@ public interface JsonMapper {
T toSingle(String json, Class type);
+ String toString(Object value);
+
}
diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/util/MapperTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/util/JsonMapperTests.java
similarity index 78%
rename from spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/util/MapperTests.java
rename to spring-cloud-function-context/src/test/java/org/springframework/cloud/function/util/JsonMapperTests.java
index cd5c21888..64a7bba6e 100644
--- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/util/MapperTests.java
+++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/util/JsonMapperTests.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.cloud.function.web.util;
+package org.springframework.cloud.function.util;
import java.util.Arrays;
import java.util.List;
@@ -26,6 +26,10 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
+import org.springframework.cloud.function.json.GsonMapper;
+import org.springframework.cloud.function.json.JacksonMapper;
+import org.springframework.cloud.function.json.JsonMapper;
+
import static org.assertj.core.api.Assertions.assertThat;
/**
@@ -33,7 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*
*/
@RunWith(Parameterized.class)
-public class MapperTests {
+public class JsonMapperTests {
private JsonMapper mapper;
@@ -43,16 +47,18 @@ public class MapperTests {
new Object[] { new JacksonMapper(new ObjectMapper()) });
}
- public MapperTests(JsonMapper mapper) {
+ public JsonMapperTests(JsonMapper mapper) {
this.mapper = mapper;
}
@Test
public void vanillaArray() {
- List list = mapper.toList("[{\"value\":\"foo\"}, {\"value\":\"foo\"}]",
+ String json = "[{\"value\":\"foo\"},{\"value\":\"foo\"}]";
+ List list = mapper.toList(json,
Foo.class);
assertThat(list).hasSize(2);
assertThat(list.get(0).getValue()).isEqualTo("foo");
+ assertThat(mapper.toString(list)).isEqualTo(json);
}
@Test
@@ -70,8 +76,10 @@ public class MapperTests {
@Test
public void vanillaObject() {
- Foo foo = mapper.toSingle("{\"value\":\"foo\"}", Foo.class);
+ String json = "{\"value\":\"foo\"}";
+ Foo foo = mapper.toSingle(json, Foo.class);
assertThat(foo.getValue()).isEqualTo("foo");
+ assertThat(mapper.toString(foo)).isEqualTo(json);
}
@Test
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 814c27806..e000ba4a1 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
@@ -19,32 +19,24 @@ package org.springframework.cloud.function.web.flux;
import java.util.ArrayList;
import java.util.List;
-import com.fasterxml.jackson.databind.ObjectMapper;
-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.AutoConfigureAfter;
-import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
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.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.cloud.function.context.FunctionCatalog;
import org.springframework.cloud.function.context.catalog.FunctionInspector;
+import org.springframework.cloud.function.json.JsonMapper;
import org.springframework.cloud.function.web.flux.request.FluxHandlerMethodArgumentResolver;
import org.springframework.cloud.function.web.flux.response.FluxReturnValueHandler;
-import org.springframework.cloud.function.web.util.GsonMapper;
-import org.springframework.cloud.function.web.util.JacksonMapper;
-import org.springframework.cloud.function.web.util.JsonMapper;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.convert.ConversionService;
@@ -71,8 +63,6 @@ public class ReactorAutoConfiguration {
@Autowired
private ApplicationContext context;
- static final String PREFERRED_MAPPER_PROPERTY = "spring.http.converters.preferred-json-mapper";
-
@Bean
public FunctionHandlerMapping functionHandlerMapping(FunctionCatalog catalog,
FunctionController controller) {
@@ -129,44 +119,6 @@ public class ReactorAutoConfiguration {
};
}
- @Configuration
- @ConditionalOnClass(Gson.class)
- @Conditional(PreferGsonOrMissingJacksonCondition.class)
- protected static class GsonConfiguration {
- @Bean
- public GsonMapper jsonMapper(Gson gson) {
- return new GsonMapper(gson);
- }
- }
-
- @Configuration
- @ConditionalOnClass(ObjectMapper.class)
- @ConditionalOnProperty(name = ReactorAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "jackson", matchIfMissing = true)
- protected static class JacksonConfiguration {
- @Bean
- public JacksonMapper jsonMapper(ObjectMapper mapper) {
- return new JacksonMapper(mapper);
- }
- }
-
- private static class PreferGsonOrMissingJacksonCondition extends AnyNestedCondition {
-
- PreferGsonOrMissingJacksonCondition() {
- super(ConfigurationPhase.REGISTER_BEAN);
- }
-
- @ConditionalOnProperty(name = ReactorAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "gson", matchIfMissing = false)
- static class GsonPreferred {
-
- }
-
- @ConditionalOnMissingBean(ObjectMapper.class)
- static class JacksonMissing {
-
- }
-
- }
-
private static class BasicStringConverter implements StringConverter {
private ConversionService conversionService;
diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/request/FluxHandlerMethodArgumentResolver.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/request/FluxHandlerMethodArgumentResolver.java
index b0b18a4b6..386be5b43 100644
--- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/request/FluxHandlerMethodArgumentResolver.java
+++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/request/FluxHandlerMethodArgumentResolver.java
@@ -28,9 +28,9 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.function.context.catalog.FunctionInspector;
import org.springframework.cloud.function.context.message.MessageUtils;
+import org.springframework.cloud.function.json.JsonMapper;
import org.springframework.cloud.function.web.flux.constants.WebRequestConstants;
import org.springframework.cloud.function.web.util.HeaderUtils;
-import org.springframework.cloud.function.web.util.JsonMapper;
import org.springframework.core.MethodParameter;
import org.springframework.core.Ordered;
import org.springframework.http.MediaType;