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 4b0854a  GEODE-5016: Replace org.json with Jackson in geode-web-api 
(#3267)
4b0854a is described below

commit 4b0854ac478c713c45b8927fc9dfdcaf909cfc16
Author: Jens Deppe <[email protected]>
AuthorDate: Fri Mar 8 05:48:03 2019 -0800

    GEODE-5016: Replace org.json with Jackson in geode-web-api (#3267)
---
 .../web/controllers/RestAccessControllerTest.java  | 49 +++++++++--
 .../internal/web/controllers/order1-array.json     | 30 +++++++
 .../web/controllers/AbstractBaseController.java    | 97 ++++++++++++----------
 .../web/controllers/CommonCrudController.java      | 12 +--
 .../web/controllers/FunctionAccessController.java  | 14 +---
 .../geode/rest/internal/web/util/JSONUtils.java    |  3 +-
 6 files changed, 136 insertions(+), 69 deletions(-)

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 023a41f..0392240 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
@@ -15,6 +15,7 @@
 package org.apache.geode.rest.internal.web.controllers;
 
 import static org.apache.geode.test.matchers.JsonEquivalence.jsonEquals;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.is;
 import static 
org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
@@ -65,6 +66,7 @@ import org.apache.geode.cache.CacheWriterException;
 import org.apache.geode.cache.Declarable;
 import org.apache.geode.cache.EntryEvent;
 import org.apache.geode.cache.LoaderHelper;
+import org.apache.geode.cache.Region;
 import org.apache.geode.cache.RegionDestroyedException;
 import org.apache.geode.cache.RegionEvent;
 import org.apache.geode.cache.RegionShortcut;
@@ -72,6 +74,7 @@ import org.apache.geode.cache.TimeoutException;
 import org.apache.geode.cache.execute.FunctionService;
 import org.apache.geode.internal.cache.HttpService;
 import org.apache.geode.management.internal.RestAgent;
+import org.apache.geode.pdx.PdxInstance;
 import org.apache.geode.test.junit.rules.ServerStarterRule;
 
 @RunWith(SpringJUnit4ClassRunner.class)
@@ -83,6 +86,7 @@ public class RestAccessControllerTest {
   private static final String BASE_URL = "http://localhost/v1";;
 
   private static final String ORDER1_JSON = "order1.json";
+  private static final String ORDER1_ARRAY_JSON = "order1-array.json";
   private static final String ORDER1_NO_TYPE_JSON = "order1-no-type.json";
   private static final String ORDER2_JSON = "order2.json";
   private static final String ORDER2_UPDATED_JSON = "order2-updated.json";
@@ -100,6 +104,9 @@ public class RestAccessControllerTest {
 
   private MockMvc mockMvc;
 
+  private static Region<?, ?> orderRegion;
+  private static Region<?, ?> customerRegion;
+
   @ClassRule
   public static ServerStarterRule rule = new ServerStarterRule()
       .withProperty("log-level", "warn")
@@ -113,6 +120,7 @@ public class RestAccessControllerTest {
   @BeforeClass
   public static void setupCClass() throws Exception {
     loadResource(ORDER1_JSON);
+    loadResource(ORDER1_ARRAY_JSON);
     loadResource(ORDER1_NO_TYPE_JSON);
     loadResource(ORDER2_JSON);
     loadResource(MALFORMED_JSON);
@@ -131,6 +139,9 @@ public class RestAccessControllerTest {
 
     rule.createRegion(RegionShortcut.REPLICATE_PROXY, "empty",
         f -> f.setCacheLoader(new SimpleCacheLoader()).setCacheWriter(new 
SimpleCacheWriter()));
+
+    customerRegion = rule.getCache().getRegion("customers");
+    orderRegion = rule.getCache().getRegion("orders");
   }
 
   private static void loadResource(String name) throws Exception {
@@ -142,8 +153,8 @@ public class RestAccessControllerTest {
   public void setup() {
     mockMvc = 
MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
 
-    rule.getCache().getRegion("customers").clear();
-    rule.getCache().getRegion("orders").clear();
+    customerRegion.clear();
+    orderRegion.clear();
   }
 
   @Test
@@ -159,6 +170,28 @@ public class RestAccessControllerTest {
         .content(jsonResources.get(ORDER1_JSON))
         .with(POST_PROCESSOR))
         .andExpect(status().isConflict());
+
+    Order order = (Order) ((PdxInstance) orderRegion.get("1")).getObject();
+    assertThat(order).as("order should not be null").isNotNull();
+  }
+
+  @Test
+  @WithMockUser
+  public void postEntryWithJsonArrayOfOrders() throws Exception {
+    mockMvc.perform(post("/v1/orders?key=1")
+        .content(jsonResources.get(ORDER1_ARRAY_JSON))
+        .with(POST_PROCESSOR))
+        .andExpect(status().isCreated())
+        .andExpect(header().string("Location", BASE_URL + "/orders/1"));
+
+    mockMvc.perform(post("/v1/orders?key=1")
+        .content(jsonResources.get(ORDER1_ARRAY_JSON))
+        .with(POST_PROCESSOR))
+        .andExpect(status().isConflict());
+
+    List<PdxInstance> entries = (List<PdxInstance>) orderRegion.get("1");
+    Order order = (Order) entries.get(0).getObject();
+    assertThat(order).as("order should not be null").isNotNull();
   }
 
   @Test
@@ -168,7 +201,8 @@ public class RestAccessControllerTest {
         .content(jsonResources.get(MALFORMED_JSON))
         .with(POST_PROCESSOR))
         .andExpect(status().isBadRequest())
-        .andExpect(jsonPath("$.cause", is("JSON document specified in the 
request is incorrect")));
+        .andExpect(
+            jsonPath("$.cause", is("Json doc specified is either not supported 
or invalid!")));
   }
 
   @Test
@@ -238,7 +272,8 @@ public class RestAccessControllerTest {
         .content(jsonResources.get(MALFORMED_JSON))
         .with(POST_PROCESSOR))
         .andExpect(status().isBadRequest())
-        .andExpect(jsonPath("$.cause", is("JSON document specified in the 
request is incorrect")));
+        .andExpect(
+            jsonPath("$.cause", is("Json doc specified is either not supported 
or invalid!")));
   }
 
   @Test
@@ -349,7 +384,8 @@ public class RestAccessControllerTest {
         .content(jsonResources.get(MALFORMED_JSON))
         .with(POST_PROCESSOR))
         .andExpect(status().isBadRequest())
-        .andExpect(jsonPath("$.cause", is("JSON document specified in the 
request is incorrect")));
+        .andExpect(
+            jsonPath("$.cause", is("Json doc specified is either not supported 
or invalid!")));
   }
 
   @Test
@@ -436,7 +472,8 @@ public class RestAccessControllerTest {
         .content(jsonResources.get(MALFORMED_JSON))
         .with(POST_PROCESSOR))
         .andExpect(status().isBadRequest())
-        .andExpect(jsonPath("$.cause", is("JSON document specified in the 
request is incorrect")));
+        .andExpect(
+            jsonPath("$.cause", is("Json doc specified in request body is 
invalid!")));
   }
 
   @Test
diff --git 
a/geode-web-api/src/integrationTest/resources/org/apache/geode/rest/internal/web/controllers/order1-array.json
 
b/geode-web-api/src/integrationTest/resources/org/apache/geode/rest/internal/web/controllers/order1-array.json
new file mode 100644
index 0000000..f7c2ab2
--- /dev/null
+++ 
b/geode-web-api/src/integrationTest/resources/org/apache/geode/rest/internal/web/controllers/order1-array.json
@@ -0,0 +1,30 @@
+[
+  {
+    "@type": "org.apache.geode.rest.internal.web.controllers.Order",
+    "purchaseOrderNo": 111,
+    "customerId": 101,
+    "description": "Purchase order for company - A",
+    "orderDate": "01/10/2014",
+    "deliveryDate": "01/20/2014",
+    "contact": "Nilkanthkumar N Patel",
+    "email": "[email protected]",
+    "phone": "020-2048096",
+    "totalPrice": 205,
+    "items": [
+      {
+        "itemNo": 1,
+        "description": "Product-1",
+        "quantity": 5,
+        "unitPrice": 10,
+        "totalPrice": 50
+      },
+      {
+        "itemNo": 1,
+        "description": "Product-2",
+        "quantity": 10,
+        "unitPrice": 15.5,
+        "totalPrice": 155
+      }
+    ]
+  }
+]
\ No newline at end of file
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 2466430..ccb8172 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
@@ -28,15 +28,16 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 
+import com.fasterxml.jackson.core.JsonFactory;
 import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.JsonToken;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.logging.log4j.Logger;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONTokener;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpHeaders;
@@ -176,21 +177,24 @@ public abstract class AbstractBaseController implements 
InitializingBean {
 
   @SuppressWarnings("unchecked")
   private <T> T casValue(String regionNamePath, String key, String jsonData) {
-    JSONObject jsonObject;
     try {
-      jsonObject = new JSONObject(jsonData);
-      String oldValue = jsonObject.get("@old").toString();
-      String newValue = jsonObject.get("@new").toString();
+      JsonNode jsonObject = objectMapper.readTree(jsonData);
+      JsonNode oldValue = jsonObject.get("@old");
+      JsonNode newValue = jsonObject.get("@new");
 
-      return (T) casValue(regionNamePath, key, convert(oldValue), 
convert(newValue));
+      if (oldValue == null || newValue == null) {
+        throw new MalformedJsonException("Json doc specified in request body 
is invalid!");
+      }
+
+      return (T) casValue(regionNamePath, key, convert(oldValue.toString()),
+          convert(newValue.toString()));
 
-    } catch (JSONException je) {
+    } catch (IOException je) {
       throw new MalformedJsonException("Json doc specified in request body is 
invalid!", je);
     }
   }
 
-  ResponseEntity<String> processQueryResponse(Query query, Object args[], 
Object queryResult)
-      throws JSONException {
+  ResponseEntity<String> processQueryResponse(Query query, Object args[], 
Object queryResult) {
     if (queryResult instanceof Collection<?>) {
       Collection processedResults = new ArrayList(((Collection) 
queryResult).size());
       for (Object result : (Collection) queryResult) {
@@ -208,23 +212,25 @@ public abstract class AbstractBaseController implements 
InitializingBean {
   }
 
   Collection<PdxInstance> convertJsonArrayIntoPdxCollection(final String 
jsonArray) {
-    JSONArray jsonArr = null;
     try {
-      jsonArr = new JSONArray(jsonArray);
-      Collection<PdxInstance> pdxInstances = new ArrayList<PdxInstance>();
+      JsonNode array = objectMapper.readTree(jsonArray);
+      if (!array.isArray()) {
+        throw new MalformedJsonException(
+            "Json document specified in request body is not an array!");
+      }
+
+      Collection<PdxInstance> pdxInstances = new ArrayList<>();
 
-      for (int index = 0; index < jsonArr.length(); index++) {
-        // String element = jsonArr.getJSONObject(i).toString();
-        // String element = jsonArr.getString(i);
-        Object object = jsonArr.get(index);
-        String element = object.toString();
+      for (int index = 0; index < array.size(); index++) {
+        JsonNode object = array.get(index);
+        String element = objectMapper.writeValueAsString(object);
 
         PdxInstance pi = convert(element);
         pdxInstances.add(pi);
       }
       return pdxInstances;
 
-    } catch (JSONException je) {
+    } catch (IOException je) {
       throw new MalformedJsonException("Json document specified in request 
body is not valid!", je);
     }
   }
@@ -692,8 +698,9 @@ public abstract class AbstractBaseController implements 
InitializingBean {
         return (T) rawDataBinding;
       } else {
         final String typeValue = (String) 
rawDataBinding.get(TYPE_META_DATA_PROPERTY);
-        if (typeValue == null)
-          return (T) new JSONObject();
+        if (typeValue == null) {
+          return (T) objectMapper.createObjectNode();
+        }
         // Added for the primitive types put. Not supporting primitive types
         if (NumberUtils.isPrimitiveOrObject(typeValue)) {
           final Object primitiveValue = rawDataBinding.get("@value");
@@ -749,20 +756,25 @@ public abstract class AbstractBaseController implements 
InitializingBean {
   }
 
   Object[] jsonToObjectArray(final String arguments) {
-    final JSONTypes jsonType = validateJsonAndFindType(arguments);
-    if (JSONTypes.JSON_ARRAY.equals(jsonType)) {
+    JsonNode node;
+    try {
+      node = objectMapper.readTree(arguments);
+    } catch (IOException e) {
+      throw new MalformedJsonException("Json document specified in request 
body is not valid!");
+    }
+
+    if (node.isArray()) {
       try {
-        JSONArray jsonArray = new JSONArray(arguments);
-        Object[] args = new Object[jsonArray.length()];
-        for (int index = 0; index < jsonArray.length(); index++) {
-          args[index] = jsonToObject(jsonArray.get(index).toString());
+        Object[] args = new Object[node.size()];
+        for (int index = 0; index < node.size(); index++) {
+          args[index] = 
jsonToObject(objectMapper.writeValueAsString(node.get(index)));
         }
         return args;
-      } catch (JSONException je) {
+      } catch (JsonProcessingException je) {
         throw new MalformedJsonException("Json document specified in request 
body is not valid!",
             je);
       }
-    } else if (JSONTypes.JSON_OBJECT.equals(jsonType)) {
+    } else if (node.isObject()) {
       return new Object[] {jsonToObject(arguments)};
     } else {
       throw new MalformedJsonException("Json document specified in request 
body is not valid!");
@@ -807,14 +819,14 @@ public abstract class AbstractBaseController implements 
InitializingBean {
   ResponseEntity<String> updateMultipleKeys(final String region, final 
String[] keys,
       final String json) {
 
-    JSONArray jsonArr = null;
+    JsonNode jsonArr;
     try {
-      jsonArr = new JSONArray(json);
-    } catch (JSONException e) {
+      jsonArr = objectMapper.readTree(json);
+    } catch (IOException e) {
       throw new MalformedJsonException("JSON document specified in the request 
is incorrect", e);
     }
 
-    if (jsonArr.length() != keys.length) {
+    if (!jsonArr.isArray() || jsonArr.size() != keys.length) {
       throw new MalformedJsonException(
           "Each key must have corresponding value (JSON document) specified in 
the request");
     }
@@ -827,9 +839,9 @@ public abstract class AbstractBaseController implements 
InitializingBean {
       }
 
       try {
-        PdxInstance pdxObj = convert(jsonArr.getJSONObject(i).toString());
+        PdxInstance pdxObj = 
convert(objectMapper.writeValueAsString(jsonArr.get(i)));
         map.put(keys[i], pdxObj);
-      } catch (JSONException e) {
+      } catch (JsonProcessingException e) {
         throw new MalformedJsonException(
             String.format("JSON document at index (%1$s) in the request body 
is incorrect", i), e);
       }
@@ -841,21 +853,22 @@ public abstract class AbstractBaseController implements 
InitializingBean {
 
     HttpHeaders headers = new HttpHeaders();
     headers.setLocation(toUri(region, 
StringUtils.arrayToCommaDelimitedString(keys)));
-    return new ResponseEntity<String>(headers, HttpStatus.OK);
+    return new ResponseEntity<>(headers, HttpStatus.OK);
   }
 
   JSONTypes validateJsonAndFindType(String json) {
     try {
-      Object jsonObj = new JSONTokener(json).nextValue();
+      JsonParser jp = new JsonFactory().createParser(json);
+      JsonToken token = jp.nextToken();
 
-      if (jsonObj instanceof JSONObject) {
+      if (token == JsonToken.START_OBJECT) {
         return JSONTypes.JSON_OBJECT;
-      } else if (jsonObj instanceof JSONArray) {
+      } else if (token == JsonToken.START_ARRAY) {
         return JSONTypes.JSON_ARRAY;
       } else {
         return JSONTypes.UNRECOGNIZED_JSON;
       }
-    } catch (JSONException je) {
+    } catch (IOException je) {
       throw new MalformedJsonException("JSON document specified in the request 
is incorrect", je);
     }
   }
diff --git 
a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/CommonCrudController.java
 
b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/CommonCrudController.java
index 6ffd726..ed411f0 100644
--- 
a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/CommonCrudController.java
+++ 
b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/CommonCrudController.java
@@ -23,7 +23,6 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
 import org.apache.logging.log4j.Logger;
-import org.json.JSONException;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
@@ -203,14 +202,9 @@ public abstract class CommonCrudController extends 
AbstractBaseController {
       if (functionResult instanceof List<?>) {
         final HttpHeaders headers = new HttpHeaders();
         headers.setLocation(toUri("servers"));
-        try {
-          String functionResultAsJson =
-              JSONUtils.convertCollectionToJson((ArrayList<Object>) 
functionResult);
-          return new ResponseEntity<>(functionResultAsJson, headers, 
HttpStatus.OK);
-        } catch (JSONException e) {
-          throw new GemfireRestException(
-              "Could not convert function results into Restful (JSON) 
format!", e);
-        }
+        String functionResultAsJson =
+            JSONUtils.convertCollectionToJson((ArrayList<Object>) 
functionResult);
+        return new ResponseEntity<>(functionResultAsJson, headers, 
HttpStatus.OK);
       } else {
         throw new GemfireRestException(
             "Function has returned results that could not be converted into 
Restful (JSON) format!");
diff --git 
a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java
 
b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java
index ed93ff2..18c2f51 100644
--- 
a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java
+++ 
b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java
@@ -25,7 +25,6 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
 import org.apache.logging.log4j.Logger;
-import org.json.JSONException;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
@@ -254,15 +253,10 @@ public class FunctionAccessController extends 
AbstractBaseController {
       functionResult = results.getResult();
 
       if (functionResult instanceof List<?>) {
-        try {
-          @SuppressWarnings("unchecked")
-          String functionResultAsJson =
-              JSONUtils.convertCollectionToJson((ArrayList<Object>) 
functionResult);
-          return new ResponseEntity<>(functionResultAsJson, headers, 
HttpStatus.OK);
-        } catch (JSONException e) {
-          throw new GemfireRestException(
-              "Could not convert function results into Restful (JSON) 
format!", e);
-        }
+        @SuppressWarnings("unchecked")
+        String functionResultAsJson =
+            JSONUtils.convertCollectionToJson((ArrayList<Object>) 
functionResult);
+        return new ResponseEntity<>(functionResultAsJson, headers, 
HttpStatus.OK);
       } else {
         throw new GemfireRestException(
             "Function has returned results that could not be converted into 
Restful (JSON) format!");
diff --git 
a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/util/JSONUtils.java
 
b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/util/JSONUtils.java
index 8094d3f..7a1c2e4 100644
--- 
a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/util/JSONUtils.java
+++ 
b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/util/JSONUtils.java
@@ -26,7 +26,6 @@ import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonGenerator.Feature;
 import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import org.json.JSONException;
 import org.springframework.util.Assert;
 
 import org.apache.geode.cache.Region;
@@ -151,7 +150,7 @@ public abstract class JSONUtils {
     }
   }
 
-  public static String convertCollectionToJson(Collection<Object> collection) 
throws JSONException {
+  public static String convertCollectionToJson(Collection<Object> collection) {
     HeapDataOutputStream outputStream =
         new HeapDataOutputStream(org.apache.geode.internal.Version.CURRENT);
 

Reply via email to