@Override protected void render(Block html) {
    String jid = $(JOB_ID);
    if (jid.isEmpty()) {
      html.
        p().__("Sorry, can't do anything without a JobID.").__();
      return;
    }
    JobId jobID = MRApps.toJobID(jid);
    Job j = appContext.getJob(jobID);
    if (j == null) {
      html.p().__("Sorry, ", jid, " not found.").__();
      return;
    }
    if(j instanceof UnparsedJob) {
      final int taskCount = j.getTotalMaps() + j.getTotalReduces();
      UnparsedJob oversizedJob = (UnparsedJob) j;
      html.p().__("The job has a total of " + taskCount + " tasks. ")
          .__("Any job larger than " + oversizedJob.getMaxTasksAllowed() +
              " will not be loaded.").__();
      html.p().__("You can either use the CLI tool: 'mapred job -history'"
          + " to view large jobs or adjust the property " +
          JHAdminConfig.MR_HS_LOADED_JOBS_TASKS_MAX + ".").__();
      return;
    }
    List<AMInfo> amInfos = j.getAMInfos();
    JobInfo job = new JobInfo(j);
    ResponseInfo infoBlock = info("Job Overview").
        __("Job Name:", job.getName()).
        __("User Name:", job.getUserName()).
        __("Queue:", job.getQueueName()).
        __("State:", job.getState()).
        __("Uberized:", job.isUber()).
        __("Submitted:", new Date(job.getSubmitTime())).
        __("Started:", job.getStartTimeStr()).
        __("Finished:", new Date(job.getFinishTime())).
        __("Elapsed:", StringUtils.formatTime(
            Times.elapsed(job.getStartTime(), job.getFinishTime(), false)));
    
    String amString =
        amInfos.size() == 1 ? "ApplicationMaster" : "ApplicationMasters"; 
    
    // todo - switch to use JobInfo
    List<String> diagnostics = j.getDiagnostics();
    if(diagnostics != null && !diagnostics.isEmpty()) {
      StringBuilder b = new StringBuilder();
      for(String diag: diagnostics) {
        b.append(addTaskLinks(diag));
      }
      infoBlock._r("Diagnostics:", b.toString());
    }

    if(job.getNumMaps() > 0) {
      infoBlock.__("Average Map Time", StringUtils.formatTime(job.getAvgMapTime()));
    }
    if(job.getNumReduces() > 0) {
      infoBlock.__("Average Shuffle Time", StringUtils.formatTime(job.getAvgShuffleTime()));
      infoBlock.__("Average Merge Time", StringUtils.formatTime(job.getAvgMergeTime()));
      infoBlock.__("Average Reduce Time", StringUtils.formatTime(job.getAvgReduceTime()));
    }

    for (ConfEntryInfo entry : job.getAcls()) {
      infoBlock.__("ACL "+entry.getName()+":", entry.getValue());
    }
    DIV<Hamlet> div = html.
        __(InfoBlock.class).
      div(_INFO_WRAP);
    
      // MRAppMasters Table
        TABLE<DIV<Hamlet>> table = div.table("#job");
        table.
          tr().
            th(amString).
            __().
          tr().
            th(_TH, "Attempt Number").
            th(_TH, "Start Time").
            th(_TH, "Node").
            th(_TH, "Logs").
            __();
        boolean odd = false;
          for (AMInfo amInfo : amInfos) {
            AMAttemptInfo attempt = new AMAttemptInfo(amInfo,
                job.getId(), job.getUserName(), "", "");
            table.tr((odd = !odd) ? _ODD : _EVEN).
              td(String.valueOf(attempt.getAttemptId())).
              td(new Date(attempt.getStartTime()).toString()).
              td().a(".nodelink", url(MRWebAppUtil.getYARNWebappScheme(),
                  attempt.getNodeHttpAddress()),
                  attempt.getNodeHttpAddress()).__().
              td().a(".logslink", url(attempt.getLogsLink()),
                      "logs").__().
                __();
          }
          table.__();
          div.__();
          
        
        html.div(_INFO_WRAP).        
      
      // Tasks table
        table("#job").
          tr().
            th(_TH, "Task Type").
            th(_TH, "Total").
            th(_TH, "Complete").__().
          tr(_ODD).
            th().
              a(url("tasks", jid, "m"), "Map").__().
            td(String.valueOf(String.valueOf(job.getMapsTotal()))).
            td(String.valueOf(String.valueOf(job.getMapsCompleted()))).__().
          tr(_EVEN).
            th().
              a(url("tasks", jid, "r"), "Reduce").__().
            td(String.valueOf(String.valueOf(job.getReducesTotal()))).
            td(String.valueOf(String.valueOf(job.getReducesCompleted()))).__()
          .__().

        // Attempts table
        table("#job").
        tr().
          th(_TH, "Attempt Type").
          th(_TH, "Failed").
          th(_TH, "Killed").
          th(_TH, "Successful").__().
        tr(_ODD).
          th("Maps").
          td().a(url("attempts", jid, "m",
              TaskAttemptStateUI.FAILED.toString()), 
              String.valueOf(job.getFailedMapAttempts())).__().
          td().a(url("attempts", jid, "m",
              TaskAttemptStateUI.KILLED.toString()), 
              String.valueOf(job.getKilledMapAttempts())).__().
          td().a(url("attempts", jid, "m",
              TaskAttemptStateUI.SUCCESSFUL.toString()), 
              String.valueOf(job.getSuccessfulMapAttempts())).__().
            __().
        tr(_EVEN).
          th("Reduces").
          td().a(url("attempts", jid, "r",
              TaskAttemptStateUI.FAILED.toString()), 
              String.valueOf(job.getFailedReduceAttempts())).__().
          td().a(url("attempts", jid, "r",
              TaskAttemptStateUI.KILLED.toString()), 
              String.valueOf(job.getKilledReduceAttempts())).__().
          td().a(url("attempts", jid, "r",
              TaskAttemptStateUI.SUCCESSFUL.toString()), 
              String.valueOf(job.getSuccessfulReduceAttempts())).__().
            __().
            __().
            __();
  }
@Test
  public void testHsJobBlockForNormalSizeJobShouldNotDisplayWarningMessage() {

    Configuration config = new Configuration();
    config.setInt(JHAdminConfig.MR_HS_LOADED_JOBS_TASKS_MAX, -1);

    JobHistory jobHistory = new JobHitoryStubWithAllNormalSizeJobs();
    jobHistory.init(config);

    HsJobBlock jobBlock = new HsJobBlock(jobHistory) {
      // override this so that the job block can fetch a job id.
      @Override
      public Map<String, String> moreParams() {
        Map<String, String> map = new HashMap<>();
        map.put(AMParams.JOB_ID, "job_0000_0001");
        return map;
      }

      // override this to avoid view context lookup in render()
      @Override
      public ResponseInfo info(String about) {
        return new ResponseInfo().about(about);
      }

      // override this to avoid view context lookup in render()
      @Override
      public String url(String... parts) {
        return StringHelper.ujoin("", parts);
      }
    };

    // set up the test block to render HsJobBLock to
    OutputStream outputStream = new ByteArrayOutputStream();
    HtmlBlock.Block block = createBlockToCreateTo(outputStream);

    jobBlock.render(block);

    block.getWriter().flush();
    String out = outputStream.toString();

    Assert.assertTrue("Should display job overview for the job.",
        out.contains("ApplicationMaster"));
  }