Repository: zeppelin Updated Branches: refs/heads/branch-0.7 54eb18f41 -> abdf3352e
[HOTFIX] Forward compatibility of Note class ### What is this PR for? Solving inconsistency issue of Note's dateformat between branch-0.7 and master. It's related to #2272 ### What type of PR is it? [Hot Fix] ### Todos * [x] - Support several dateformat for Note class ### What is the Jira issue? * N/A ### How should this be tested? * Sync with some remote repository ### Screenshots (if appropriate) ### Questions: * Does the licenses files need update? No * Is there breaking changes for older versions? No * Does this needs documentation? No Author: Jongyoul Lee <jongy...@gmail.com> Closes #2591 from jongyoul/hotfix/note-json-forward-compatibility and squashes the following commits: 046a245e [Jongyoul Lee] Fixed style 492e7d30 [Jongyoul Lee] Make test case more concrete 13b9aef5 [Jongyoul Lee] Added one more deserialize option 53add839 [Jongyoul Lee] Hotfix for forward compatibility of Note.class Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/abdf3352 Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/abdf3352 Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/abdf3352 Branch: refs/heads/branch-0.7 Commit: abdf3352e5817e2da0de29f51b72d761cabb4919 Parents: 54eb18f Author: Jongyoul Lee <jongy...@gmail.com> Authored: Mon Sep 18 13:53:44 2017 +0900 Committer: Jongyoul Lee <jongy...@apache.org> Committed: Mon Sep 18 17:01:19 2017 +0900 ---------------------------------------------------------------------- .../java/org/apache/zeppelin/notebook/Note.java | 42 +++++++++++----- .../org/apache/zeppelin/notebook/Notebook.java | 2 +- .../notebook/NotebookImportDeserializer.java | 12 ++--- .../notebook/repo/AzureNotebookRepo.java | 6 +-- .../zeppelin/notebook/repo/S3NotebookRepo.java | 2 +- .../zeppelin/notebook/repo/VFSNotebookRepo.java | 2 +- .../repo/zeppelinhub/ZeppelinHubRepo.java | 4 +- .../apache/zeppelin/notebook/ParagraphTest.java | 50 +++++++++++--------- 8 files changed, 69 insertions(+), 51 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zeppelin/blob/abdf3352/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java ---------------------------------------------------------------------- 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 1964a08..ae0de5d 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 @@ -17,21 +17,37 @@ package org.apache.zeppelin.notebook; -import static java.lang.String.format; - +import com.google.common.base.Preconditions; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import java.io.IOException; import java.io.Serializable; -import java.util.*; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; - import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.apache.zeppelin.conf.ZeppelinConfiguration; import org.apache.zeppelin.display.AngularObject; import org.apache.zeppelin.display.AngularObjectRegistry; import org.apache.zeppelin.display.Input; -import org.apache.zeppelin.interpreter.*; +import org.apache.zeppelin.interpreter.Interpreter; +import org.apache.zeppelin.interpreter.InterpreterException; +import org.apache.zeppelin.interpreter.InterpreterFactory; +import org.apache.zeppelin.interpreter.InterpreterGroup; +import org.apache.zeppelin.interpreter.InterpreterResult; +import org.apache.zeppelin.interpreter.InterpreterResultMessage; +import org.apache.zeppelin.interpreter.InterpreterSetting; +import org.apache.zeppelin.interpreter.InterpreterSettingManager; import org.apache.zeppelin.interpreter.remote.RemoteAngularObjectRegistry; import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion; import org.apache.zeppelin.notebook.repo.NotebookRepo; @@ -42,11 +58,8 @@ import org.apache.zeppelin.scheduler.Job.Status; import org.apache.zeppelin.search.SearchService; import org.apache.zeppelin.user.AuthenticationInfo; import org.apache.zeppelin.user.Credentials; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.google.common.base.Preconditions; -import com.google.gson.Gson; +import static java.lang.String.format; /** * Binded interpreters for a note @@ -59,6 +72,10 @@ public class Note implements Serializable, ParagraphJobListener { private static final ScheduledThreadPoolExecutor delayedPersistThreadPool = new ScheduledThreadPoolExecutor(0); + public static final Gson GSON = new GsonBuilder().setPrettyPrinting() + .setDateFormat("yyyy-MM-dd HH:mm:ss.SSS") + .registerTypeAdapter(Date.class, new NotebookImportDeserializer()).create(); + static { delayedPersistThreadPool.setRemoveOnCancelPolicy(true); } @@ -323,9 +340,8 @@ public class Note implements Serializable, ParagraphJobListener { newParagraph.setTitle(srcParagraph.getTitle()); try { - Gson gson = new Gson(); - String resultJson = gson.toJson(srcParagraph.getReturn()); - InterpreterResult result = gson.fromJson(resultJson, InterpreterResult.class); + 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 @@ -589,7 +605,7 @@ public class Note implements Serializable, ParagraphJobListener { public void run(String paragraphId) { Paragraph p = getParagraph(paragraphId); p.setListener(jobListenerFactory.getParagraphJobListener(this)); - + if (p.isBlankParagraph()) { logger.info("skip to run blank paragraph. {}", p.getId()); p.setStatus(Job.Status.FINISHED); http://git-wip-us.apache.org/repos/asf/zeppelin/blob/abdf3352/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java index 953a73f..e8739f4 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java @@ -211,7 +211,7 @@ public class Notebook implements NoteEventListener { reader.setLenient(true); Note newNote; try { - Note oldNote = gson.fromJson(reader, Note.class); + Note oldNote = Note.GSON.fromJson(reader, Note.class); convertFromSingleResultToMultipleResultsFormat(oldNote); newNote = createNote(subject); if (noteName != null) http://git-wip-us.apache.org/repos/asf/zeppelin/blob/abdf3352/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NotebookImportDeserializer.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NotebookImportDeserializer.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NotebookImportDeserializer.java index 86e0f0b..7211039 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NotebookImportDeserializer.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NotebookImportDeserializer.java @@ -21,7 +21,6 @@ import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; - import java.lang.reflect.Type; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -30,18 +29,19 @@ import java.util.Date; import java.util.Locale; /** - * importNote date format deserializer + * importNote date format deserializer */ public class NotebookImportDeserializer implements JsonDeserializer<Date> { - private static final String[] DATE_FORMATS = new String[] { + private static final String[] DATE_FORMATS = new String[]{ "yyyy-MM-dd'T'HH:mm:ssZ", "MMM d, yyyy h:mm:ss a", - "MMM dd, yyyy HH:mm:ss" + "MMM dd, yyyy HH:mm:ss", + "yyyy-MM-dd HH:mm:ss.SSS" }; @Override public Date deserialize(JsonElement jsonElement, Type typeOF, - JsonDeserializationContext context) throws JsonParseException { + JsonDeserializationContext context) throws JsonParseException { for (String format : DATE_FORMATS) { try { return new SimpleDateFormat(format, Locale.US).parse(jsonElement.getAsString()); @@ -49,6 +49,6 @@ public class NotebookImportDeserializer implements JsonDeserializer<Date> { } } throw new JsonParseException("Unparsable date: \"" + jsonElement.getAsString() - + "\". Supported formats: " + Arrays.toString(DATE_FORMATS)); + + "\". Supported formats: " + Arrays.toString(DATE_FORMATS)); } } http://git-wip-us.apache.org/repos/asf/zeppelin/blob/abdf3352/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/AzureNotebookRepo.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/AzureNotebookRepo.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/AzureNotebookRepo.java index 79f5dd6..1ccc78f 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/AzureNotebookRepo.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/AzureNotebookRepo.java @@ -25,7 +25,6 @@ import java.io.Writer; import java.net.URISyntaxException; import java.security.InvalidKeyException; import java.util.Collections; -import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -35,7 +34,6 @@ import org.apache.commons.lang.StringUtils; import org.apache.zeppelin.conf.ZeppelinConfiguration; import org.apache.zeppelin.notebook.Note; import org.apache.zeppelin.notebook.NoteInfo; -import org.apache.zeppelin.notebook.NotebookImportDeserializer; import org.apache.zeppelin.notebook.Paragraph; import org.apache.zeppelin.scheduler.Job; import org.apache.zeppelin.user.AuthenticationInfo; @@ -135,10 +133,8 @@ public class AzureNotebookRepo implements NotebookRepo { GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.setPrettyPrinting(); - Gson gson = gsonBuilder.registerTypeAdapter(Date.class, new NotebookImportDeserializer()) - .create(); - Note note = gson.fromJson(json, Note.class); + Note note = Note.GSON.fromJson(json, Note.class); for (Paragraph p : note.getParagraphs()) { if (p.getStatus() == Job.Status.PENDING || p.getStatus() == Job.Status.RUNNING) { http://git-wip-us.apache.org/repos/asf/zeppelin/blob/abdf3352/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/S3NotebookRepo.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/S3NotebookRepo.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/S3NotebookRepo.java index 26781b8..314c14e 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/S3NotebookRepo.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/S3NotebookRepo.java @@ -199,7 +199,7 @@ public class S3NotebookRepo implements NotebookRepo { Note note; try (InputStream ins = s3object.getObjectContent()) { String json = IOUtils.toString(ins, conf.getString(ConfVars.ZEPPELIN_ENCODING)); - note = gson.fromJson(json, Note.class); + note = Note.GSON.fromJson(json, Note.class); } for (Paragraph p : note.getParagraphs()) { http://git-wip-us.apache.org/repos/asf/zeppelin/blob/abdf3352/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepo.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepo.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepo.java index 04a7075..aebda97 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepo.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepo.java @@ -175,7 +175,7 @@ public class VFSNotebookRepo implements NotebookRepo { String json = IOUtils.toString(ins, conf.getString(ConfVars.ZEPPELIN_ENCODING)); ins.close(); - Note note = gson.fromJson(json, Note.class); + Note note = Note.GSON.fromJson(json, Note.class); // note.setReplLoader(replLoader); // note.jobListenerFactory = jobListenerFactory; http://git-wip-us.apache.org/repos/asf/zeppelin/blob/abdf3352/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/zeppelinhub/ZeppelinHubRepo.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/zeppelinhub/ZeppelinHubRepo.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/zeppelinhub/ZeppelinHubRepo.java index cd94180..a4e41a8 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/zeppelinhub/ZeppelinHubRepo.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/zeppelinhub/ZeppelinHubRepo.java @@ -186,7 +186,7 @@ public class ZeppelinHubRepo implements NotebookRepo { } String token = getUserToken(subject.getUser()); String response = restApiClient.get(token, noteId); - Note note = GSON.fromJson(response, Note.class); + Note note = Note.GSON.fromJson(response, Note.class); if (note == null) { return EMPTY_NOTE; } @@ -245,7 +245,7 @@ public class ZeppelinHubRepo implements NotebookRepo { String token = getUserToken(subject.getUser()); String response = restApiClient.get(token, endpoint); - Note note = GSON.fromJson(response, Note.class); + Note note = Note.GSON.fromJson(response, Note.class); if (note == null) { return EMPTY_NOTE; } http://git-wip-us.apache.org/repos/asf/zeppelin/blob/abdf3352/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java index 0e77846..c7d2a6a 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java @@ -18,22 +18,16 @@ package org.apache.zeppelin.notebook; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - import com.google.common.collect.Lists; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import org.junit.Test; +import org.mockito.Mockito; + import org.apache.zeppelin.display.AngularObject; import org.apache.zeppelin.display.AngularObjectBuilder; import org.apache.zeppelin.display.AngularObjectRegistry; @@ -41,7 +35,6 @@ import org.apache.zeppelin.display.Input; import org.apache.zeppelin.interpreter.Interpreter; import org.apache.zeppelin.interpreter.Interpreter.FormType; import org.apache.zeppelin.interpreter.InterpreterContext; -import org.apache.zeppelin.interpreter.InterpreterFactory; import org.apache.zeppelin.interpreter.InterpreterGroup; import org.apache.zeppelin.interpreter.InterpreterOption; import org.apache.zeppelin.interpreter.InterpreterResult; @@ -52,15 +45,19 @@ import org.apache.zeppelin.interpreter.InterpreterSetting; import org.apache.zeppelin.interpreter.InterpreterSetting.Status; import org.apache.zeppelin.interpreter.InterpreterSettingManager; import org.apache.zeppelin.resource.ResourcePool; -import org.apache.zeppelin.scheduler.JobListener; import org.apache.zeppelin.user.AuthenticationInfo; import org.apache.zeppelin.user.Credentials; -import org.junit.Test; -import java.util.HashMap; -import java.util.Map; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; public class ParagraphTest { @Test @@ -84,7 +81,7 @@ public class ParagraphTest { assertEquals("md", Paragraph.getRequiredReplName(text)); assertEquals("", Paragraph.getScriptBody(text)); } - + @Test public void replSingleCharName() { String text = "%r a"; @@ -232,4 +229,13 @@ public class ParagraphTest { } + + @Test + public void deserializeParagraphFromDifferentDateFormat() throws ParseException { + String dateString = "2017-09-01 00:01:02.345"; + Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse(dateString); + Paragraph paragraph = Note.GSON + .fromJson("{\"dateUpdated\":\"" + dateString + "\"}", Paragraph.class); + assertEquals(date, paragraph.dateUpdated); + } }