This is an automated email from the ASF dual-hosted git repository. jensdeppe pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push: new d8b8344 GEODE-6506: Don't return JSONy objects when converting from json to Object arrays (#3289) d8b8344 is described below commit d8b834457d028b3888d5818df5751e3fe495f3a7 Author: Jens Deppe <jde...@pivotal.io> AuthorDate: Thu Mar 14 07:28:27 2019 -0700 GEODE-6506: Don't return JSONy objects when converting from json to Object arrays (#3289) --- ...mentFunction.java => EchoArgumentFunction.java} | 39 +++++++++++--------- .../web/controllers/RestAccessControllerTest.java | 41 +++++++++++++++++----- .../web/controllers/AbstractBaseController.java | 6 ++-- 3 files changed, 59 insertions(+), 27 deletions(-) diff --git a/geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/NoArgumentFunction.java b/geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/EchoArgumentFunction.java similarity index 80% rename from geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/NoArgumentFunction.java rename to geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/EchoArgumentFunction.java index fff60ba..63cb88b 100644 --- a/geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/NoArgumentFunction.java +++ b/geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/EchoArgumentFunction.java @@ -17,6 +17,8 @@ package org.apache.geode.rest.internal.web.controllers; import java.util.Set; +import com.fasterxml.jackson.databind.ObjectMapper; + import org.apache.geode.cache.Region; import org.apache.geode.cache.execute.Execution; import org.apache.geode.cache.execute.Function; @@ -26,7 +28,7 @@ import org.apache.geode.cache.execute.FunctionService; import org.apache.geode.cache.execute.RegionFunctionContext; import org.apache.geode.cache.execute.ResultCollector; -public class NoArgumentFunction implements Function { +public class EchoArgumentFunction implements Function { /** * Specifies whether the function sends results while executing. The method returns false if no * result is expected.<br> @@ -40,12 +42,11 @@ public class NoArgumentFunction implements Function { * </p> * * @return whether this function returns a Result back to the caller. - * * @since GemFire 6.0 */ @Override public boolean hasResult() { - return false; + return true; } /** @@ -56,46 +57,53 @@ public class NoArgumentFunction implements Function { * in parameter is instance of {@link RegionFunctionContext}. * * @param context as created by {@link Execution} - * * @since GemFire 6.0 */ @Override public void execute(final FunctionContext context) { - // do nothing + Object args = context.getArguments(); + + // Echo the arguments back to the caller for assertion + if (args != null && args.getClass().isAssignableFrom(Object.class)) { + // Object is not serializable + context.getResultSender().lastResult(new ObjectMapper().createObjectNode()); + } else { + context.getResultSender().lastResult(args); + } } /** - * Return a unique function identifier, used to register the function with {@link FunctionService} + * Return a unique function identifier, used to register the function with {@link + * FunctionService} * * @return string identifying this function - * * @since GemFire 6.0 */ @Override public String getId() { - return "NoArgumentFunction"; + return "EchoArgumentFunction"; } /** * <p> * Return true to indicate to GemFire the method requires optimization for writing the targeted - * {@link FunctionService#onRegion(Region)} and any associated - * {@linkplain Execution#withFilter(Set) routing objects}. + * {@link FunctionService#onRegion(Region)} and any associated {@linkplain + * Execution#withFilter(Set) routing objects}. * </p> * * <p> - * Returning false will optimize for read behavior on the targeted - * {@link FunctionService#onRegion(Region)} and any associated - * {@linkplain Execution#withFilter(Set) routing objects}. + * Returning false will optimize for read behavior on the targeted {@link + * FunctionService#onRegion(Region)} and any associated {@linkplain Execution#withFilter(Set) + * routing objects}. * </p> * * <p> * This method is only consulted when Region passed to - * FunctionService#onRegion(org.apache.geode.cache.Region) is a partitioned region + * FunctionService#onRegion(org.apache.geode.cache.Region) + * is a partitioned region * </p> * * @return false if the function is read only, otherwise returns true - * * @see FunctionService * @since GemFire 6.0 */ @@ -108,7 +116,6 @@ public class NoArgumentFunction implements Function { * Specifies whether the function is eligible for re-execution (in case of failure). * * @return whether the function is eligible for re-execution. - * * @see RegionFunctionContext#isPossibleDuplicate() * @since GemFire 6.5 */ diff --git a/geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/RestAccessControllerTest.java b/geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/RestAccessControllerTest.java index 0392240..9721f18 100644 --- a/geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/RestAccessControllerTest.java +++ b/geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/RestAccessControllerTest.java @@ -135,7 +135,7 @@ public class RestAccessControllerTest { RestAgent.createParameterizedQueryRegion(); FunctionService.registerFunction(new AddFreeItemToOrders()); - FunctionService.registerFunction(new NoArgumentFunction()); + FunctionService.registerFunction(new EchoArgumentFunction()); rule.createRegion(RegionShortcut.REPLICATE_PROXY, "empty", f -> f.setCacheLoader(new SimpleCacheLoader()).setCacheWriter(new SimpleCacheWriter())); @@ -810,7 +810,7 @@ public class RestAccessControllerTest { mockMvc.perform(get("/v1/functions")) .andExpect(status().isOk()) .andExpect(jsonPath("$.functions", - containsInAnyOrder("AddFreeItemToOrders", "NoArgumentFunction"))); + containsInAnyOrder("AddFreeItemToOrders", "EchoArgumentFunction"))); } @Test @@ -837,16 +837,41 @@ public class RestAccessControllerTest { @Test @WithMockUser - public void executeNoArgFunction() throws Exception { - mockMvc.perform(post("/v1/functions/NoArgumentFunction") - .content("{ }") + public void executeNoArgFunctionWithInvalidArg() throws Exception { + mockMvc.perform(post("/v1/functions/EchoArgumentFunction") + .content("{\"type\": \"int\"}") .with(POST_PROCESSOR)) - .andExpect(status().isOk()); + .andExpect(status().isOk()) + .andExpect(content().json("[{}]")); + } - mockMvc.perform(post("/v1/functions/NoArgumentFunction") + @Test + @WithMockUser + public void executeNoArgFunctionWithEmptyObject() throws Exception { + mockMvc.perform(post("/v1/functions/EchoArgumentFunction") .content("[{ }]") .with(POST_PROCESSOR)) - .andExpect(status().isOk()); + .andExpect(status().isOk()) + .andExpect(content().json("[{}]")); + } + + @Test + @WithMockUser + public void executeNoArgFunctionWithEmptyArray() throws Exception { + mockMvc.perform(post("/v1/functions/EchoArgumentFunction") + .content("[]") + .with(POST_PROCESSOR)) + .andExpect(status().isOk()) + .andExpect(content().json("[[]]")); + } + + @Test + @WithMockUser + public void executeNoArgFunctionWithNoContent() throws Exception { + mockMvc.perform(post("/v1/functions/EchoArgumentFunction") + .with(POST_PROCESSOR)) + .andExpect(status().isOk()) + .andExpect(content().json("[null]")); } @Test diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java index ccb8172..340d6b0 100644 --- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java +++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java @@ -699,7 +699,7 @@ public abstract class AbstractBaseController implements InitializingBean { } else { final String typeValue = (String) rawDataBinding.get(TYPE_META_DATA_PROPERTY); if (typeValue == null) { - return (T) objectMapper.createObjectNode(); + return (T) new Object(); } // Added for the primitive types put. Not supporting primitive types if (NumberUtils.isPrimitiveOrObject(typeValue)) { @@ -712,12 +712,12 @@ public abstract class AbstractBaseController implements InitializingBean { } } else { Assert.state( - ClassUtils.isPresent(String.valueOf(typeValue), + ClassUtils.isPresent(typeValue, Thread.currentThread().getContextClassLoader()), String.format("Class (%1$s) could not be found!", typeValue)); return (T) objectMapper.convertValue(rawDataBinding, ClassUtils.resolveClassName( - String.valueOf(typeValue), Thread.currentThread().getContextClassLoader())); + typeValue, Thread.currentThread().getContextClassLoader())); } } }