public void run() throws Exception {
    // setup the blank form for the specified patient
    Patient patient = getPatient();
    FormEntrySession session = setupFormEntrySession(patient, getFormName());
    testFormEntrySessionAttribute(session);
    String html = session.getHtmlToDisplay();
    testBlankFormHtml(html);

    // submit some initial data and test it
    Map<String, String> labeledWidgets = getLabeledWidgets(html, widgetLabels());
    MockHttpServletRequest request = new MockHttpServletRequest();
    setupRequest(request, labeledWidgets);
    Patient patientToView = null;
    Encounter encounterToView = null;
    if (request.getParameterMap().size() > 0) {
      SubmissionResults results = doSubmission(session, request);
      testResults(results);
      patientToView = results.getPatient();
      encounterToView = results.getEncounterCreated();
    }

    // view that patient and run tests on it
    Patient overridePatient = getPatientToView();
    boolean doViewPatient = overridePatient != null || doViewPatient();
    if (doViewPatient) {
      if (overridePatient != null) patientToView = overridePatient;
      session = setupFormViewSession(patientToView, null, getFormName());
      testFormViewSessionAttribute(session);
      html = session.getHtmlToDisplay();
      testViewingPatient(patientToView, html);
    }

    // view that encounter and run tests on that
    Encounter override = getEncounterToView();
    boolean doViewEncounter = override != null || doViewEncounter();
    if (doViewEncounter) {
      if (override != null) encounterToView = override;
      session = setupFormViewSession(patientToView, encounterToView, getFormName());
      testFormViewSessionAttribute(session);
      html = session.getHtmlToDisplay();
      testViewingEncounter(encounterToView, html);
    }

    // edit the encounter, and run tests on that
    override = getEncounterToEdit();
    boolean doEditEncounter = override != null || doEditEncounter();

    overridePatient = getPatientToEdit();
    boolean doEditPatient = overridePatient != null || doEditPatient();

    if (doEditEncounter || doEditPatient) {
      Encounter toEdit = encounterToView;
      if (override != null) toEdit = override;

      Patient patientToEdit = patientToView;
      if (overridePatient != null) patientToEdit = overridePatient;

      session = setupFormEditSession(patientToEdit, toEdit, getFormName());
      testFormEditSessionAttribute(session);
      String editHtml = session.getHtmlToDisplay();
      testEditFormHtml(editHtml);

      Map<String, String> labeledWidgetsForEdit =
          getLabeledWidgets(editHtml, widgetLabelsForEdit());
      MockHttpServletRequest editRequest = createEditRequest(editHtml);
      setupEditRequest(editRequest, labeledWidgetsForEdit);
      if (editRequest.getParameterMap().size() > 0) {
        SubmissionResults results = doSubmission(session, editRequest);
        testEditedResults(results);
        results.getEncounterCreated();
        results.getPatient();
      }
    }
  }
  private SubmissionResults doSubmission(FormEntrySession session, HttpServletRequest request)
      throws Exception {
    SubmissionResults results = new SubmissionResults();
    session.prepareForSubmit();
    List<FormSubmissionError> validationErrors =
        session.getSubmissionController().validateSubmission(session.getContext(), request);
    if (validationErrors != null && validationErrors.size() > 0) {
      results.setValidationErrors(validationErrors);
      return results;
    }
    session.getSubmissionController().handleFormSubmission(session, request);

    if (session.getContext().getMode() == Mode.ENTER
        && session.hasEncouterTag()
        && (session.getSubmissionActions().getEncountersToCreate() == null
            || session.getSubmissionActions().getEncountersToCreate().size() == 0))
      throw new IllegalArgumentException("This form is not going to create an encounter");
    session.applyActions();
    results.setPatient(session.getPatient());
    results.setEncounterCreated(getLastEncounter(session.getPatient()));
    return results;
  }
  @RequestMapping(FORM_PATH)
  public ModelAndView handleRequest(HttpServletRequest request) {

    returnUrl = request.getContextPath() + "/module/patientnarratives/patientNarrativesForm.form";

    HtmlFormEntryPortletController htmlFormEntryPortletController;
    FormEntrySession session = null;
    try {
      htmlFormEntryPortletController = new HtmlFormEntryPortletController();
      session = htmlFormEntryPortletController.getFormEntrySession(request);

      List<FormSubmissionError> validationErrors =
          session.getSubmissionController().validateSubmission(session.getContext(), request);
      if (validationErrors != null && validationErrors.size() > 0) {
        // errors.reject("Fix errors");
      }
    } catch (Exception ex) {
      log.error("Exception during form validation", ex);
      // errors.reject("Exception during form validation, see log for more details: " + ex);
    }

    //        if (errors.hasErrors()) {
    //            return new ModelAndView(FORM_PATH, "command", session);
    //        }

    // no form validation errors, proceed with submission

    try {
      session.prepareForSubmit();

      if (session.getContext().getMode() == FormEntryContext.Mode.ENTER
          && session.hasPatientTag()
          && session.getPatient() == null
          && (session.getSubmissionActions().getPersonsToCreate() == null
              || session.getSubmissionActions().getPersonsToCreate().size() == 0))
        throw new IllegalArgumentException("This form is not going to create an Patient");

      if (session.getContext().getMode() == FormEntryContext.Mode.ENTER
          && session.hasEncouterTag()
          && (session.getSubmissionActions().getEncountersToCreate() == null
              || session.getSubmissionActions().getEncountersToCreate().size() == 0))
        throw new IllegalArgumentException("This form is not going to create an encounter");

      session.getSubmissionController().handleFormSubmission(session, request);
      HtmlFormEntryUtil.getService().applyActions(session);
      String successView = session.getReturnUrlWithParameters();

      request
          .getSession()
          .setAttribute(
              WebConstants.OPENMRS_MSG_ATTR, "patientnarratives.module.narrative.save.success");

      if (successView == null)
        successView =
            request.getContextPath() + "/module/patientnarratives/patientNarrativesForm.form";
      if (StringUtils.hasText(request.getParameter("closeAfterSubmission"))) {
        return new ModelAndView(new RedirectView(returnUrl));
        //                return new ModelAndView(closeDialogView, "dialogToClose",
        // request.getParameter("closeAfterSubmission"));
      } else {
        return new ModelAndView(new RedirectView(returnUrl));
        //                return new ModelAndView(new RedirectView(successView));
      }
    } catch (ValidationException ex) {
      log.error("Invalid input:", ex);
      //            errors.reject(ex.getMessage());
    } catch (BadFormDesignException ex) {
      log.error("Bad Form Design:", ex);
      //            errors.reject(ex.getMessage());
    } catch (Exception ex) {
      log.error("Exception trying to submit form", ex);
      StringWriter sw = new StringWriter();
      ex.printStackTrace(new PrintWriter(sw));
      //            errors.reject("Exception! " + ex.getMessage() + "<br/>" + sw.toString());
    }

    //        if ((alert != null) && (alert == true)) {
    //        }
    // if we get here it's because we caught an error trying to submit/apply
    //        return new ModelAndView(returnUrl, "command", session);
    return new ModelAndView(new RedirectView(returnUrl));
  }