@POST
  @Path("run/{noteId}/{paragraphId}")
  @ZeppelinApi
  public Response runParagraphSynchronously(@PathParam("noteId") String noteId,
                                            @PathParam("paragraphId") String paragraphId,
                                            @QueryParam("sessionId") String sessionId,
                                            String message)
      throws IOException, IllegalArgumentException {
    LOGGER.info("Run paragraph synchronously {} {} {}", noteId, paragraphId, message);

    return notebook.processNote(noteId,
      note -> {
        checkIfNoteIsNotNull(note, noteId);
        Paragraph paragraph = note.getParagraph(paragraphId);
        checkIfParagraphIsNotNull(paragraph, paragraphId);

        Map<String, Object> params = new HashMap<>();
        if (!StringUtils.isEmpty(message)) {
          ParametersRequest request = GSON.fromJson(message, ParametersRequest.class);
          params = request.getParams();
        }

        if (notebookService.runParagraph(note, paragraphId, paragraph.getTitle(),
                paragraph.getText(), params,
                new HashMap<>(), sessionId, false, true, getServiceContext(), new RestServiceCallback<>())) {
          return notebookService.getNote(noteId, getServiceContext(), new RestServiceCallback<>(),
            noteRun -> {
              Paragraph p = noteRun.getParagraph(paragraphId);
              InterpreterResult result = p.getReturn();
              return new JsonResponse<>(Status.OK, result).build();
            });
        } else {
          return new JsonResponse<>(Status.INTERNAL_SERVER_ERROR, "Fail to run paragraph").build();
        }
      });
  }
@Test
  void testRunParagraphSynchronously() throws IOException {
    LOG.info("Running testRunParagraphSynchronously");
    String note1Id = null;
    try {
      note1Id = notebook.createNote("note1", anonymous);
      Paragraph p = notebook.processNote(note1Id,
        note1 -> {
          return note1.addNewParagraph(AuthenticationInfo.ANONYMOUS);
        });

      // run non-blank paragraph
      String title = "title";
      String text = "%sh\n sleep 1";
      p.setTitle(title);
      p.setText(text);

      CloseableHttpResponse post = httpPost("/notebook/run/" + note1Id + "/" + p.getId(), "");
      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"));
      post.close();
      assertNotEquals(Job.Status.READY, p.getStatus());

      // Check if the paragraph is emptied
      assertEquals(title, p.getTitle());
      assertEquals(text, p.getText());

      // run invalid code
      text = "%sh\n invalid_cmd";
      p.setTitle(title);
      p.setText(text);

      post = httpPost("/notebook/run/" + note1Id + "/" + p.getId(), "");
      assertEquals(200, post.getStatusLine().getStatusCode());
      resp = gson.fromJson(EntityUtils.toString(post.getEntity(), StandardCharsets.UTF_8),
              new TypeToken<Map<String, Object>>() {}.getType());
      assertEquals("OK", resp.get("status"));
      Map stringMap = (Map) resp.get("body");
      assertEquals("ERROR", stringMap.get("code"));
      List<Map> interpreterResults = (List<Map>) stringMap.get("msg");
      assertTrue(interpreterResults.get(0).get("data").toString()
          .contains("invalid_cmd: "), interpreterResults.get(0).toString());
      post.close();
      assertNotEquals(Job.Status.READY, p.getStatus());

      // Check if the paragraph is emptied
      assertEquals(title, p.getTitle());
      assertEquals(text, p.getText());
    } finally {
      // cleanup
      if (null != note1Id) {
        notebook.removeNote(note1Id, anonymous);
      }
    }
  }