@ApiOperation(value = "Get the exception stacktrace for a job", tags = { "Jobs" })
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates the requested job was not found and the stacktrace has been returned. The response contains the raw stacktrace and always has a Content-type of text/plain."),
            @ApiResponse(code = 404, message = "Indicates the requested job was not found or the job does not have an exception stacktrace. Status-description contains additional information about the error.")
    })
    @GetMapping("/management/jobs/{jobId}/exception-stacktrace")
    public String getJobStacktrace(@ApiParam(name = "jobId") @PathVariable String jobId, HttpServletResponse response) {
        Job job = getJobById(jobId);

        String stackTrace = managementService.getJobExceptionStacktrace(job.getId());

        if (stackTrace == null) {
            throw new FlowableObjectNotFoundException("Job with id '" + job.getId() + "' does not have an exception stacktrace.", String.class);
        }

        response.setContentType("text/plain");
        return stackTrace;
    }
@Test
    @Deployment(resources = { "org/flowable/rest/service/api/management/JobExceptionStacktraceResourceTest.testTimerProcess.bpmn20.xml" })
    public void testGetJobStacktrace() throws Exception {
        // Start process, forcing error on job-execution
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("timerProcess", Collections.singletonMap("error", (Object) Boolean.TRUE));

        Job timerJob = managementService.createTimerJobQuery().processInstanceId(processInstance.getId()).singleResult();
        assertThat(timerJob).isNotNull();

        // Force execution of job
        Job timerJob2 = managementService.createTimerJobQuery().processInstanceId(processInstance.getId()).timers().singleResult();
        assertThatThrownBy(() -> {
            managementService.moveTimerToExecutableJob(timerJob2.getId());
            managementService.executeJob(timerJob2.getId());
        })
                .isExactlyInstanceOf(FlowableException.class);

        Calendar now = Calendar.getInstance();
        now.set(Calendar.MILLISECOND, 0);
        processEngineConfiguration.getClock().setCurrentTime(now.getTime());

        CloseableHttpResponse response = executeRequest(new HttpGet(
                SERVER_URL_PREFIX + RestUrls.createRelativeResourceUrl(RestUrls.URL_TIMER_JOB_EXCEPTION_STRACKTRACE, timerJob.getId())), HttpStatus.SC_OK);

        String stack = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
        assertThat(stack).isEqualTo(managementService.getTimerJobExceptionStacktrace(timerJob.getId()));

        // Also check content-type
        assertThat(response.getEntity().getContentType().getValue()).isEqualTo("text/plain");
        closeResponse(response);
    }