diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/scheduler/Job.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/scheduler/Job.java index 00df966de96..2dc1719ebac 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/scheduler/Job.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/scheduler/Job.java @@ -255,7 +255,7 @@ public Date getDateFinished() { return dateFinished; } - protected void setResult(Object result) { + public void setResult(Object result) { this.result = result; } } diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java index 01d625abe00..08231e54722 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java @@ -207,17 +207,23 @@ public void addCloneParagraph(Paragraph srcParagraph) { Map config = new HashMap<>(srcParagraph.getConfig()); Map param = new HashMap<>(srcParagraph.settings.getParams()); Map form = new HashMap<>(srcParagraph.settings.getForms()); - Gson gson = new Gson(); - InterpreterResult result = gson.fromJson( - gson.toJson(srcParagraph.getReturn()), - InterpreterResult.class); newParagraph.setConfig(config); newParagraph.settings.setParams(param); newParagraph.settings.setForms(form); newParagraph.setText(srcParagraph.getText()); newParagraph.setTitle(srcParagraph.getTitle()); - newParagraph.setReturn(result, null); + + try { + Gson gson = new Gson(); + String resultJson = gson.toJson(srcParagraph.getReturn()); + InterpreterResult result = gson.fromJson(resultJson, InterpreterResult.class); + newParagraph.setReturn(result, null); + } catch (Exception e) { + // 'result' part of Note consists of exception, instead of actual interpreter results + logger.warn("Paragraph " + srcParagraph.getId() + " has a result with exception. " + + e.getMessage()); + } synchronized (paragraphs) { paragraphs.add(newParagraph); diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java index 53749d1ddea..d4e59970d01 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java @@ -43,7 +43,6 @@ import org.apache.zeppelin.resource.ResourcePoolUtils; import org.apache.zeppelin.scheduler.Job; import org.apache.zeppelin.scheduler.Job.Status; -import org.apache.zeppelin.scheduler.JobListener; import org.apache.zeppelin.scheduler.SchedulerFactory; import org.apache.zeppelin.search.SearchService; import org.apache.zeppelin.user.Credentials; @@ -316,6 +315,33 @@ public void testAutoRestartInterpreterAfterSchedule() throws InterruptedExceptio notebook.refreshCron(note.id()); } + @Test + public void testExportAndImportNote() throws IOException, CloneNotSupportedException, + InterruptedException { + Note note = notebook.createNote(); + note.getNoteReplLoader().setInterpreters(factory.getDefaultInterpreterSettingList()); + + final Paragraph p = note.addParagraph(); + String simpleText = "hello world"; + p.setText(simpleText); + + note.runAll(); + while (p.isTerminated() == false || p.getResult() == null) { + Thread.yield(); + } + + String exportedNoteJson = notebook.exportNote(note.getId()); + + Note importedNote = notebook.importNote(exportedNoteJson, "Title"); + + Paragraph p2 = importedNote.getParagraphs().get(0); + + // Test + assertEquals(p.getId(), p2.getId()); + assertEquals(p.text, p2.text); + assertEquals(p.getResult().message(), p2.getResult().message()); + } + @Test public void testCloneNote() throws IOException, CloneNotSupportedException, InterruptedException { @@ -338,6 +364,30 @@ public void testCloneNote() throws IOException, CloneNotSupportedException, assertEquals(cp.getResult().message(), p.getResult().message()); } + @Test + public void testCloneNoteWithExceptionResult() throws IOException, CloneNotSupportedException, + InterruptedException { + Note note = notebook.createNote(); + note.getNoteReplLoader().setInterpreters(factory.getDefaultInterpreterSettingList()); + + final Paragraph p = note.addParagraph(); + p.setText("hello world"); + note.runAll(); + while (p.isTerminated() == false || p.getResult() == null) { + Thread.yield(); + } + // Force paragraph to have String type object + p.setResult("Exception"); + + Note cloneNote = notebook.cloneNote(note.getId(), "clone note with Exception result"); + Paragraph cp = cloneNote.paragraphs.get(0); + + // Keep same ParagraphID + assertEquals(cp.getId(), p.getId()); + assertEquals(cp.text, p.text); + assertNull(cp.getResult()); + } + @Test public void testResourceRemovealOnParagraphNoteRemove() throws IOException { Note note = notebook.createNote();