public static Result restFlowGraphData(String flowDefId) {
    JsonArray datasets = new JsonArray();
    if (flowDefId == null || flowDefId.isEmpty()) {
      return ok(new Gson().toJson(datasets));
    }

    // Fetch available flow executions with latest JOB_HISTORY_LIMIT mr jobs.
    List<AppResult> results = getRestFlowAppResults(flowDefId);

    if (results.size() == 0) {
      logger.info("No results for Job url");
    }
    Map<IdUrlPair, List<AppResult>> flowExecIdToJobsMap =
        ControllerUtil.limitHistoryResults(ControllerUtil.groupJobs(results, ControllerUtil.GroupBy.FLOW_EXECUTION_ID), results.size(), MAX_HISTORY_LIMIT);

    // Compute the graph data starting from the earliest available execution to latest
    List<IdUrlPair> keyList = new ArrayList<IdUrlPair>(flowExecIdToJobsMap.keySet());
    for (int i = keyList.size() - 1; i >= 0; i--) {
      IdUrlPair flowExecPair = keyList.get(i);
      int flowPerfScore = 0;
      JsonArray jobScores = new JsonArray();
      List<AppResult> mrJobsList = Lists.reverse(flowExecIdToJobsMap.get(flowExecPair));
      Map<IdUrlPair, List<AppResult>> jobDefIdToJobsMap = ControllerUtil.groupJobs(mrJobsList, ControllerUtil.GroupBy.JOB_DEFINITION_ID);

      // Compute the execution records. Note that each entry in the jobDefIdToJobsMap will have at least one AppResult
      for (IdUrlPair jobDefPair : jobDefIdToJobsMap.keySet()) {
        // Compute job perf score
        int jobPerfScore = 0;
        for (AppResult job : jobDefIdToJobsMap.get(jobDefPair)) {
          jobPerfScore += job.score;
        }

        // A job in jobscores list
        JsonObject jobScore = new JsonObject();
        jobScore.addProperty("jobscore", jobPerfScore);
        jobScore.addProperty("jobdefurl", jobDefPair.getUrl());
        jobScore.addProperty("jobexecurl", jobDefIdToJobsMap.get(jobDefPair).get(0).jobExecUrl);

        jobScores.add(jobScore);
        flowPerfScore += jobPerfScore;
      }

      // Execution record
      JsonObject dataset = new JsonObject();
      dataset.addProperty("flowtime", Utils.getFlowTime(mrJobsList.get(mrJobsList.size() - 1)));
      dataset.addProperty("score", flowPerfScore);
      dataset.add("jobscores", jobScores);

      datasets.add(dataset);
    }

    JsonArray sortedDatasets = Utils.sortJsonArray(datasets);

    return ok(new Gson().toJson(sortedDatasets));
  }
The data for plotting the flow history graph

<pre>
{@code
  [
    {
      "flowtime": <Last job's finish time>,
      "score": 1000,
      "jobscores": [
        {
          "jobdefurl:" "url",
          "jobexecurl:" "url",
          "jobscore": 500
        },
        {
          "jobdefurl:" "url",
          "jobexecurl:" "url",
          "jobscore": 500
        }
      ]
    },
    {
      "flowtime": <Last job's finish time>,
      "score": 700,
      "jobscores": [
        {
          "jobdefurl:" "url",
          "jobexecurl:" "url",
          "jobscore": 0
        },
        {
          "jobdefurl:" "url",
          "jobexecurl:" "url",
          "jobscore": 700
        }
      ]
    }
  ]
}
</pre>
app/controllers/Application.java