From d1e27b55e2bf4f100abdb5f2e24ff6649ef1b588 Mon Sep 17 00:00:00 2001 From: sokomishalov Date: Tue, 6 Jul 2021 17:00:39 +0300 Subject: [PATCH] Accept JsonProvider upon JsonProjectingMethodInterceptorFactory creation. We now configure explicitly the JsonProvider that is used by JSONPath through JsonProjectingMethodInterceptorFactory to avoid misconfiguration due to JSONPath defaulting attempts. Accepting JsonProvider allows for improved flexibility during configuration. Closes #2403 --- ...sonProjectingMethodInterceptorFactory.java | 38 +++++++++++++------ ...rojectingJackson2HttpMessageConverter.java | 3 +- ...tingMethodInterceptorFactoryUnitTests.java | 5 ++- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/springframework/data/web/JsonProjectingMethodInterceptorFactory.java b/src/main/java/org/springframework/data/web/JsonProjectingMethodInterceptorFactory.java index ffa9bd39a..c718a933a 100644 --- a/src/main/java/org/springframework/data/web/JsonProjectingMethodInterceptorFactory.java +++ b/src/main/java/org/springframework/data/web/JsonProjectingMethodInterceptorFactory.java @@ -38,7 +38,6 @@ import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import com.fasterxml.jackson.databind.ObjectMapper; import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; @@ -47,12 +46,14 @@ import com.jayway.jsonpath.ParseContext; import com.jayway.jsonpath.PathNotFoundException; import com.jayway.jsonpath.TypeRef; import com.jayway.jsonpath.spi.mapper.MappingProvider; +import com.jayway.jsonpath.spi.json.JsonProvider; /** * {@link MethodInterceptorFactory} to create a {@link MethodInterceptor} that will * * @author Oliver Gierke * @author Mark Paluch + * @author Mikhael Sokolov * @soundtrack Jeff Coffin - Fruitcake (The Inside Of The Outside) * @since 1.13 */ @@ -60,21 +61,34 @@ public class JsonProjectingMethodInterceptorFactory implements MethodInterceptor private final ParseContext context; + /** + * Creates a new {@link JsonProjectingMethodInterceptorFactory} using the given {@link MappingProvider} and {@link JsonProvider}. + * + * @param mappingProvider must not be {@literal null}. + * @param jsonProvider must not be {@literal null}. + */ + public JsonProjectingMethodInterceptorFactory(MappingProvider mappingProvider, JsonProvider jsonProvider) { + + Assert.notNull(mappingProvider, "MappingProvider must not be null!"); + Assert.notNull(jsonProvider, "JsonProvider must not be null!"); + + Configuration configuration = Configuration.builder()// + .options(Option.ALWAYS_RETURN_LIST)// + .mappingProvider(mappingProvider)// + .jsonProvider(jsonProvider)// + .build(); + + this.context = JsonPath.using(configuration); + } + /** - * Creates a new {@link JsonProjectingMethodInterceptorFactory} using the given {@link ObjectMapper}. + * Creates a new {@link JsonProjectingMethodInterceptorFactory} using the given {@link MappingProvider}. * - * @param mapper must not be {@literal null}. + * @param mappingProvider must not be {@literal null}. */ + @Deprecated public JsonProjectingMethodInterceptorFactory(MappingProvider mappingProvider) { - - Assert.notNull(mappingProvider, "MappingProvider must not be null!"); - - Configuration build = Configuration.builder()// - .options(Option.ALWAYS_RETURN_LIST)// - .mappingProvider(mappingProvider)// - .build(); - - this.context = JsonPath.using(build); + this(mappingProvider, Configuration.defaultConfiguration().jsonProvider()); } /* diff --git a/src/main/java/org/springframework/data/web/ProjectingJackson2HttpMessageConverter.java b/src/main/java/org/springframework/data/web/ProjectingJackson2HttpMessageConverter.java index 7a67374c3..751158d73 100644 --- a/src/main/java/org/springframework/data/web/ProjectingJackson2HttpMessageConverter.java +++ b/src/main/java/org/springframework/data/web/ProjectingJackson2HttpMessageConverter.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.lang.reflect.Type; import java.util.Map; +import com.jayway.jsonpath.spi.json.JacksonJsonProvider; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanFactory; @@ -85,7 +86,7 @@ public class ProjectingJackson2HttpMessageConverter extends MappingJackson2HttpM SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory(); projectionFactory - .registerMethodInvokerFactory(new JsonProjectingMethodInterceptorFactory(new JacksonMappingProvider(mapper))); + .registerMethodInvokerFactory(new JsonProjectingMethodInterceptorFactory(new JacksonMappingProvider(mapper), new JacksonJsonProvider(mapper))); return projectionFactory; } diff --git a/src/test/java/org/springframework/data/web/JsonProjectingMethodInterceptorFactoryUnitTests.java b/src/test/java/org/springframework/data/web/JsonProjectingMethodInterceptorFactoryUnitTests.java index 44112fea5..f640ed467 100755 --- a/src/test/java/org/springframework/data/web/JsonProjectingMethodInterceptorFactoryUnitTests.java +++ b/src/test/java/org/springframework/data/web/JsonProjectingMethodInterceptorFactoryUnitTests.java @@ -17,6 +17,8 @@ package org.springframework.data.web; import static org.assertj.core.api.Assertions.*; +import com.jayway.jsonpath.spi.json.JacksonJsonProvider; +import com.jayway.jsonpath.spi.json.JsonProvider; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -59,7 +61,8 @@ class JsonProjectingMethodInterceptorFactoryUnitTests { SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory(); MappingProvider mappingProvider = new JacksonMappingProvider(new ObjectMapper()); - projectionFactory.registerMethodInvokerFactory(new JsonProjectingMethodInterceptorFactory(mappingProvider)); + JsonProvider jsonProvider = new JacksonJsonProvider(new ObjectMapper()); + projectionFactory.registerMethodInvokerFactory(new JsonProjectingMethodInterceptorFactory(mappingProvider, jsonProvider)); this.projectionFactory = projectionFactory; this.customer = projectionFactory.createProjection(Customer.class, new ByteArrayInputStream(json.getBytes()));