This is an automated email from the ASF dual-hosted git repository.

xiangfu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 4c4800b  Support HTTP POST/PUT JSON schema (#4639)
4c4800b is described below

commit 4c4800bf65413105ecf0fde7c189f3378dfa0d3a
Author: Xiang Fu <[email protected]>
AuthorDate: Tue Sep 24 23:50:02 2019 -0700

    Support HTTP POST/PUT JSON schema (#4639)
    
    * Support HTTP POST JSON schema
    
    * address comments
---
 .../api/resources/PinotSchemaRestletResource.java  | 51 +++++++++++++++++++++-
 .../api/PinotSchemaRestletResourceTest.java        | 30 +++++++++++++
 .../pinot/controller/helix/ControllerTest.java     | 11 +++++
 3 files changed, 90 insertions(+), 2 deletions(-)

diff --git 
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotSchemaRestletResource.java
 
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotSchemaRestletResource.java
index 82a4841..8f3c221 100644
--- 
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotSchemaRestletResource.java
+++ 
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotSchemaRestletResource.java
@@ -30,6 +30,7 @@ import java.util.List;
 import java.util.Map;
 import javax.annotation.Nullable;
 import javax.inject.Inject;
+import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
@@ -120,16 +121,38 @@ public class PinotSchemaRestletResource {
     return addOrUpdateSchema(schemaName, multiPart);
   }
 
+  @PUT
+  @Produces(MediaType.APPLICATION_JSON)
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Path("/schemas/{schemaName}")
+  @ApiOperation(value = "Update a schema", notes = "Updates a schema")
+  @ApiResponses(value = {@ApiResponse(code = 200, message = "Successfully 
updated schema"), @ApiResponse(code = 404, message = "Schema not found"), 
@ApiResponse(code = 400, message = "Missing or invalid request body"), 
@ApiResponse(code = 500, message = "Internal error")})
+  public SuccessResponse updateSchema(@ApiParam(value = "Name of the schema", 
required = true) @PathParam("schemaName") String schemaName,
+      Schema schema) {
+    return addOrUpdateSchema(schemaName, schema);
+  }
+
   // TODO: This should not update if the schema already exists
   @POST
   @Produces(MediaType.APPLICATION_JSON)
   @Path("/schemas")
   @ApiOperation(value = "Add a new schema", notes = "Adds a new schema")
-  @ApiResponses(value = {@ApiResponse(code = 200, message = "Successfully 
deleted schema"), @ApiResponse(code = 404, message = "Schema not found"), 
@ApiResponse(code = 400, message = "Missing or invalid request body"), 
@ApiResponse(code = 500, message = "Internal error")})
+  @ApiResponses(value = {@ApiResponse(code = 200, message = "Successfully 
created schema"), @ApiResponse(code = 404, message = "Schema not found"), 
@ApiResponse(code = 400, message = "Missing or invalid request body"), 
@ApiResponse(code = 500, message = "Internal error")})
   public SuccessResponse addSchema(FormDataMultiPart multiPart) {
     return addOrUpdateSchema(null, multiPart);
   }
 
+  // TODO: This should not update if the schema already exists
+  @POST
+  @Produces(MediaType.APPLICATION_JSON)
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Path("/schemas")
+  @ApiOperation(value = "Add a new schema", notes = "Adds a new schema")
+  @ApiResponses(value = {@ApiResponse(code = 200, message = "Successfully 
created schema"), @ApiResponse(code = 404, message = "Schema not found"), 
@ApiResponse(code = 400, message = "Missing or invalid request body"), 
@ApiResponse(code = 500, message = "Internal error")})
+  public SuccessResponse addSchema(Schema schema) {
+    return addOrUpdateSchema(null, schema);
+  }
+
   @POST
   @Produces(MediaType.APPLICATION_JSON)
   @Path("/schemas/validate")
@@ -145,6 +168,21 @@ public class PinotSchemaRestletResource {
     return schema.toPrettyJsonString();
   }
 
+  @POST
+  @Produces(MediaType.APPLICATION_JSON)
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Path("/schemas/validate")
+  @ApiOperation(value = "Validate schema", notes = "This API returns the 
schema that matches the one you get "
+      + "from 'GET /schema/{schemaName}'. This allows us to validate schema 
before apply.")
+  @ApiResponses(value = {@ApiResponse(code = 200, message = "Successfully 
validated schema"), @ApiResponse(code = 400, message = "Missing or invalid 
request body"), @ApiResponse(code = 500, message = "Internal error")})
+  public String validateSchema(Schema schema) {
+    if (!schema.validate(LOGGER)) {
+      throw new ControllerApplicationException(LOGGER, "Invalid schema. Check 
controller logs",
+          Response.Status.BAD_REQUEST);
+    }
+    return schema.toPrettyJsonString();
+  }
+
   /**
    * Internal method to add or update schema
    * @param schemaName null value indicates new schema (POST request) where 
schemaName is
@@ -152,8 +190,17 @@ public class PinotSchemaRestletResource {
    * @return
    */
   private SuccessResponse addOrUpdateSchema(@Nullable String schemaName, 
FormDataMultiPart multiPart) {
+    return addOrUpdateSchema(schemaName, getSchemaFromMultiPart(multiPart));
+  }
+
+  /**
+   * Internal method to add or update schema
+   * @param schemaName null value indicates new schema (POST request) where 
schemaName is
+   *                   not part of URI
+   * @return
+   */
+  private SuccessResponse addOrUpdateSchema(@Nullable String schemaName, 
Schema schema) {
     final String schemaNameForLogging = (schemaName == null) ? "new schema" : 
schemaName + " schema";
-    Schema schema = getSchemaFromMultiPart(multiPart);
     if (!schema.validate(LOGGER)) {
       LOGGER.info("Invalid schema during create/update of {}", 
schemaNameForLogging);
       throw new ControllerApplicationException(LOGGER, "Invalid schema", 
Response.Status.BAD_REQUEST);
diff --git 
a/pinot-controller/src/test/java/org/apache/pinot/controller/api/PinotSchemaRestletResourceTest.java
 
b/pinot-controller/src/test/java/org/apache/pinot/controller/api/PinotSchemaRestletResourceTest.java
index 745ce81..5f1979b 100644
--- 
a/pinot-controller/src/test/java/org/apache/pinot/controller/api/PinotSchemaRestletResourceTest.java
+++ 
b/pinot-controller/src/test/java/org/apache/pinot/controller/api/PinotSchemaRestletResourceTest.java
@@ -19,6 +19,8 @@
 package org.apache.pinot.controller.api;
 
 import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.commons.httpclient.methods.PostMethod;
 import org.apache.commons.httpclient.methods.PutMethod;
 import org.apache.pinot.common.data.DimensionFieldSpec;
@@ -54,6 +56,34 @@ public class PinotSchemaRestletResourceTest extends 
ControllerTest {
   }
 
   @Test
+  public void testPostJson() {
+    String schemaString = "{\n" + "  \"schemaName\" : \"transcript\",\n" + "  
\"dimensionFieldSpecs\" : [ {\n"
+        + "    \"name\" : \"studentID\",\n" + "    \"dataType\" : 
\"STRING\"\n" + "  }, {\n"
+        + "    \"name\" : \"firstName\",\n" + "    \"dataType\" : 
\"STRING\"\n" + "  }, {\n"
+        + "    \"name\" : \"lastName\",\n" + "    \"dataType\" : \"STRING\"\n" 
+ "  }, {\n"
+        + "    \"name\" : \"gender\",\n" + "    \"dataType\" : \"STRING\"\n" + 
"  }, {\n"
+        + "    \"name\" : \"subject\",\n" + "    \"dataType\" : \"STRING\"\n" 
+ "  } ],\n"
+        + "  \"metricFieldSpecs\" : [ {\n" + "    \"name\" : \"score\",\n" + " 
   \"dataType\" : \"FLOAT\"\n"
+        + "  } ]}";
+    try {
+      Map<String, String> header = new HashMap<>();
+      sendPostRequest(_controllerRequestURLBuilder.forSchemaCreate(), 
schemaString, header);
+    } catch (IOException e) {
+      Assert.assertTrue(e.getMessage().startsWith("Server returned HTTP 
response code: 415"), e.getMessage());
+    }
+
+    try {
+      Map<String, String> header = new HashMap<>();
+      header.put("Content-Type", "application/json");
+      final String response = 
sendPostRequest(_controllerRequestURLBuilder.forSchemaCreate(), schemaString, 
header);
+      Assert.assertEquals(response, "{\"status\":\"transcript successfully 
added\"}");
+    } catch (IOException e) {
+      // should not reach here
+      Assert.fail("Shouldn't have caught an exception");
+    }
+  }
+
+  @Test
   public void testCreateUpdateSchema()
       throws IOException {
     String schemaName = "testSchema";
diff --git 
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/ControllerTest.java
 
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/ControllerTest.java
index 069c7bd..4ce7ce1 100644
--- 
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/ControllerTest.java
+++ 
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/ControllerTest.java
@@ -33,6 +33,7 @@ import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.methods.PostMethod;
 import org.apache.commons.httpclient.methods.PutMethod;
@@ -466,8 +467,18 @@ public abstract class ControllerTest {
 
   public static String sendPostRequest(String urlString, String payload)
       throws IOException {
+    return sendPostRequest(urlString, payload, Collections.EMPTY_MAP);
+  }
+
+  public static String sendPostRequest(String urlString, String payload, 
Map<String, String> headers)
+      throws IOException {
     HttpURLConnection httpConnection = (HttpURLConnection) new 
URL(urlString).openConnection();
     httpConnection.setRequestMethod("POST");
+    if (headers != null) {
+      for (String key : headers.keySet()) {
+        httpConnection.setRequestProperty(key, headers.get(key));
+      }
+    }
 
     if (payload != null && !payload.isEmpty()) {
       httpConnection.setDoOutput(true);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to