@POST
  @Path("{noteId}/revision")
  @ZeppelinApi
  public Response checkpointNote(String message,
                                 @PathParam("noteId") String noteId) throws IOException {
    LOGGER.info("Commit note by JSON {}", message);
    CheckpointNoteRequest request = GSON.fromJson(message, CheckpointNoteRequest.class);
    if (request == null || StringUtils.isEmpty(request.getCommitMessage())) {
      LOGGER.warn("Trying to commit notebook {} with empty commitMessage", noteId);
      throw new BadRequestException("commitMessage can not be empty");
    }
    NotebookRepoWithVersionControl.Revision revision = notebookService.checkpointNote(noteId, request.getCommitMessage(), getServiceContext(), new RestServiceCallback<>());
    if (revision == null || StringUtils.isEmpty(revision.id)) {
      return new JsonResponse<>(Status.OK, "Couldn't checkpoint note revision: possibly no changes found or storage doesn't support versioning. "
              + "Please check the logs for more details.").build();
    }
    return new JsonResponse<>(Status.OK, "", revision.id).build();
  }
@Test
  void testCheckpointNote() throws IOException {
    LOG.info("Running testCheckpointNote");
    String note1Id = null;
    try {
      String notePath = "note1";
      note1Id = notebook.createNote(notePath, anonymous);

      //Add a paragraph
      notebook.processNote(note1Id, note -> {
        Paragraph p1 = note.addNewParagraph(anonymous);
        p1.setText("text1");
        notebook.saveNote(note, AuthenticationInfo.ANONYMOUS);
        return null;
      });

      // Call restful api to save a revision and verify
      String commitMessage = "first commit";
      CloseableHttpResponse post = httpPost("/notebook/" + note1Id + "/revision", "{\"commitMessage\" : \"" + commitMessage + "\"}");

      assertThat(post, isAllowed());
      Map<String, Object> resp = gson.fromJson(EntityUtils.toString(post.getEntity(), StandardCharsets.UTF_8),
              new TypeToken<Map<String, Object>>() {
              }.getType());
      assertEquals("OK", resp.get("status"));
      String revisionId = (String) resp.get("body");
      notebook.processNote(note1Id, note -> {
        Note revisionOfNote = notebook.getNoteByRevision(note.getId(), note.getPath(), revisionId, anonymous);
        assertEquals(1, notebook.listRevisionHistory(note.getId(), note.getPath(), anonymous).size());
        assertEquals(1, revisionOfNote.getParagraphs().size());
        assertEquals("text1", revisionOfNote.getParagraph(0).getText());
        return null;
      });
      post.close();
    } finally {
      // cleanup
      if (null != note1Id) {
        notebook.removeNote(note1Id, anonymous);
      }
    }
  }