Repository: incubator-zeppelin Updated Branches: refs/heads/master 4a1edd525 -> d69a30eec
ZEPPELIN-506 Expand "create notebook" of REST API to have initial paragraphs ### What is this PR for? To provide initial paragraphs when creating new notebook via REST API ### What type of PR is it? Improvement ### Todos * [ ] - ### Is there a relevant Jira issue? https://issues.apache.org/jira/browse/ZEPPELIN-506 ### How should this be tested? 1. Request ```http://<zeppelin host>:<zeppelin port>/api/notebook``` with POST method including JSON payload, ``` { "name": "Test for initial paragraphs2", "paragraphs": [ { "text": "%spark\nvar hello: Int=1" }, { "text": "%spark\nhello = hello + 1" }, { "text": "%spark\nimport java.util.Date\n\nprintln(hello + \", current time is <\" + new Date + \">\")" } ] } ``` 2. Check notebook is made with initial paragraphs via UI or REST API or Web socket. ### Screenshots (if appropriate) ### Questions: * Does the licenses files need update? (No) * Is there breaking changes for older versions? (No, added parameter is optional.) * Does this needs documentation? (Yes, I've updated related doc.) Author: Jungtaek Lim <[email protected]> Closes #536 from HeartSaVioR/ZEPPELIN-506 and squashes the following commits: b009b76 [Jungtaek Lim] ZEPPELIN-506 Add sample json which describes paragraphs is optional d7cd1ed [Jungtaek Lim] ZEPPELIN-506 Expand "create notebook" of REST API to have initial paragraphs Project: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/commit/d69a30ee Tree: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/tree/d69a30ee Diff: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/diff/d69a30ee Branch: refs/heads/master Commit: d69a30eec7d6a22ecb4bc8c4d18b24afeba61e7f Parents: 4a1edd5 Author: Jungtaek Lim <[email protected]> Authored: Wed Dec 16 11:24:08 2015 +0900 Committer: Lee moon soo <[email protected]> Committed: Thu Dec 17 07:38:57 2015 +0900 ---------------------------------------------------------------------- docs/rest-api/rest-notebook.md | 22 +++++++++- .../apache/zeppelin/rest/NotebookRestApi.java | 15 ++++--- .../rest/message/NewNotebookRequest.java | 6 +++ .../rest/message/NewParagraphRequest.java | 41 +++++++++++++++++++ .../zeppelin/rest/ZeppelinRestApiTest.java | 43 ++++++++++++++++++++ 5 files changed, 120 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/d69a30ee/docs/rest-api/rest-notebook.md ---------------------------------------------------------------------- diff --git a/docs/rest-api/rest-notebook.md b/docs/rest-api/rest-notebook.md index 1bb0e53..8293c4f 100644 --- a/docs/rest-api/rest-notebook.md +++ b/docs/rest-api/rest-notebook.md @@ -92,8 +92,26 @@ limitations under the License. <td> 500 </td> </tr> <tr> - <td> sample JSON input </td> - <td><pre>{"name": "name of new notebook"}</pre></td> + <td> sample JSON input (without paragraphs) </td> + <td><pre>{ "name": "name of new notebook" }</pre></td> + </tr> + <tr> + <td> sample JSON input (with initial paragraphs) </td> + <td><pre> +{ + "name": "name of new notebook", + "paragraphs": [ + { + "title": "paragraph title1", + "text": "paragraph text1" + }, + { + "title": "paragraph title2", + "text": "paragraph text2" + } + ] +} + </pre></td> </tr> <tr> <td> sample JSON response </td> http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/d69a30ee/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java index b3f912e..4f1dd01 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java @@ -30,10 +30,7 @@ import org.apache.zeppelin.interpreter.InterpreterSetting; import org.apache.zeppelin.notebook.Note; import org.apache.zeppelin.notebook.Notebook; import org.apache.zeppelin.notebook.Paragraph; -import org.apache.zeppelin.rest.message.CronRequest; -import org.apache.zeppelin.rest.message.InterpreterSettingListForNoteBind; -import org.apache.zeppelin.rest.message.NewInterpreterSettingRequest; -import org.apache.zeppelin.rest.message.NewNotebookRequest; +import org.apache.zeppelin.rest.message.*; import org.apache.zeppelin.server.JsonResponse; import org.apache.zeppelin.server.ZeppelinServer; import org.apache.zeppelin.socket.NotebookServer; @@ -138,7 +135,15 @@ public class NotebookRestApi { NewNotebookRequest request = gson.fromJson(message, NewNotebookRequest.class); Note note = notebook.createNote(); - note.addParagraph(); // it's an empty note. so add one paragraph + List<NewParagraphRequest> initialParagraphs = request.getParagraphs(); + if (initialParagraphs != null) { + for (NewParagraphRequest paragraphRequest : initialParagraphs) { + Paragraph p = note.addParagraph(); + p.setTitle(paragraphRequest.getTitle()); + p.setText(paragraphRequest.getText()); + } + } + note.addParagraph(); // add one paragraph to the last String noteName = request.getName(); if (noteName.isEmpty()) { noteName = "Note " + note.getId(); http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/d69a30ee/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/NewNotebookRequest.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/NewNotebookRequest.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/NewNotebookRequest.java index 8d1b8c0..61ae657 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/NewNotebookRequest.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/NewNotebookRequest.java @@ -17,6 +17,7 @@ package org.apache.zeppelin.rest.message; +import java.util.List; import java.util.Map; import org.apache.zeppelin.interpreter.InterpreterOption; @@ -27,6 +28,7 @@ import org.apache.zeppelin.interpreter.InterpreterOption; */ public class NewNotebookRequest { String name; + List<NewParagraphRequest> paragraphs; public NewNotebookRequest (){ @@ -35,4 +37,8 @@ public class NewNotebookRequest { public String getName() { return name; } + + public List<NewParagraphRequest> getParagraphs() { + return paragraphs; + } } http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/d69a30ee/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/NewParagraphRequest.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/NewParagraphRequest.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/NewParagraphRequest.java new file mode 100644 index 0000000..a1d6556 --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/NewParagraphRequest.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.zeppelin.rest.message; + +/** + * NewParagraphRequest rest api request message + * + * It is used for NewNotebookRequest with initial paragraphs + * + */ +public class NewParagraphRequest { + String title; + String text; + + public NewParagraphRequest() { + + } + + public String getTitle() { + return title; + } + + public String getText() { + return text; + } +} http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/d69a30ee/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java index 0a58fb0..3111807 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java @@ -18,6 +18,7 @@ package org.apache.zeppelin.rest; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -26,10 +27,12 @@ import org.apache.commons.httpclient.methods.DeleteMethod; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.commons.lang3.StringUtils; import org.apache.zeppelin.conf.ZeppelinConfiguration; import org.apache.zeppelin.interpreter.InterpreterSetting; import org.apache.zeppelin.notebook.Note; import org.apache.zeppelin.notebook.Paragraph; +import org.apache.zeppelin.rest.message.NewParagraphRequest; import org.apache.zeppelin.scheduler.Job.Status; import org.apache.zeppelin.server.ZeppelinServer; import org.junit.AfterClass; @@ -201,6 +204,46 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi { testNotebookCreate(""); } + @Test + public void testNotebookCreateWithParagraphs() throws IOException { + // Call Create Notebook REST API + String noteName = "test"; + String jsonRequest = "{\"name\":\"" + noteName + "\", \"paragraphs\": [" + + "{\"title\": \"title1\", \"text\": \"text1\"}," + + "{\"title\": \"title2\", \"text\": \"text2\"}" + + "]}"; + PostMethod post = httpPost("/notebook/", jsonRequest); + LOG.info("testNotebookCreate \n" + post.getResponseBodyAsString()); + assertThat("test notebook create method:", post, isCreated()); + + Map<String, Object> resp = gson.fromJson(post.getResponseBodyAsString(), new TypeToken<Map<String, Object>>() { + }.getType()); + + String newNotebookId = (String) resp.get("body"); + LOG.info("newNotebookId:=" + newNotebookId); + Note newNote = ZeppelinServer.notebook.getNote(newNotebookId); + assertNotNull("Can not find new note by id", newNote); + // This is partial test as newNote is in memory but is not persistent + String newNoteName = newNote.getName(); + LOG.info("new note name is: " + newNoteName); + String expectedNoteName = noteName; + if (noteName.isEmpty()) { + expectedNoteName = "Note " + newNotebookId; + } + assertEquals("compare note name", expectedNoteName, newNoteName); + assertEquals("initial paragraph check failed", 3, newNote.getParagraphs().size()); + for (Paragraph p : newNote.getParagraphs()) { + if (StringUtils.isEmpty(p.getText())) { + continue; + } + assertTrue("paragraph title check failed", p.getTitle().startsWith("title")); + assertTrue("paragraph text check failed", p.getText().startsWith("text")); + } + // cleanup + ZeppelinServer.notebook.removeNote(newNotebookId); + post.releaseConnection(); + } + private void testNotebookCreate(String noteName) throws IOException { // Call Create Notebook REST API String jsonRequest = "{\"name\":\"" + noteName + "\"}";
