@ApiOperation(value = "Get form data", tags = { "Forms" }, notes = "")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates that form data could be queried."),
            @ApiResponse(code = 404, message = "Indicates that form data could not be found.") })
    @GetMapping(value = "/form/form-data", produces = "application/json")
    public FormDataResponse getFormData(@RequestParam(value = "taskId", required = false) String taskId,
            @RequestParam(value = "processDefinitionId", required = false) String processDefinitionId) {

        if (taskId == null && processDefinitionId == null) {
            throw new FlowableIllegalArgumentException("The taskId or processDefinitionId parameter has to be provided");
        }

        if (taskId != null && processDefinitionId != null) {
            throw new FlowableIllegalArgumentException("Not both a taskId and a processDefinitionId parameter can be provided");
        }

        FormData formData = null;
        String id = null;
        if (taskId != null) {
            formData = formService.getTaskFormData(taskId);
            id = taskId;
        } else {
            formData = formService.getStartFormData(processDefinitionId);
            id = processDefinitionId;
        }

        if (formData == null) {
            throw new FlowableObjectNotFoundException("Could not find a form data with id '" + id + "'.", FormData.class);
        }
        
        if (restApiInterceptor != null) {
            restApiInterceptor.accessFormData(formData);
        }

        return restResponseFactory.createFormDataResponse(formData);
    }
@Test
    @Deployment
    public void testGetFormData() throws Exception {
        Map<String, Object> variableMap = new HashMap<>();
        variableMap.put("SpeakerName", "John Doe");
        Address address = new Address();
        variableMap.put("address", address);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess", variableMap);
        Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();

        CloseableHttpResponse response = executeRequest(
                new HttpGet(SERVER_URL_PREFIX + RestUrls.createRelativeResourceUrl(RestUrls.URL_FORM_DATA) + "?taskId=" + task.getId()), HttpStatus.SC_OK);

        // Check resulting task
        JsonNode responseNode = objectMapper.readTree(response.getEntity().getContent());
        closeResponse(response);

        assertThatJson(responseNode)
                .when(Option.IGNORING_EXTRA_FIELDS, Option.IGNORING_ARRAY_ORDER)
                .isEqualTo("{"
                        + "formProperties: [ {"
                        + "  id: 'room',"
                        + "  name: null,"
                        + "  type: null,"
                        + "  value: null,"
                        + "  readable: true,"
                        + "  writable: true,"
                        + "  required: false"
                        + "},"
                        + "{"
                        + "  id: 'duration',"
                        + "  name: null,"
                        + "  type: 'long',"
                        + "  value: null,"
                        + "  readable: true,"
                        + "  writable: true,"
                        + "  required: false"
                        + "},"
                        + "{"
                        + "  id: 'speaker',"
                        + "  name: null,"
                        + "  type: null,"
                        + "  value: 'John Doe',"
                        + "  readable: true,"
                        + "  writable: false,"
                        + "  required: false"
                        + "},"
                        + "{"
                        + "  id: 'street',"
                        + "  name: null,"
                        + "  type: null,"
                        + "  value: null,"
                        + "  readable: true,"
                        + "  writable: true,"
                        + "  required: true"
                        + "},"
                        + "{"
                        + "  id: 'start',"
                        + "  name: null,"
                        + "  type: 'date',"
                        + "  value: null,"
                        + "  readable: true,"
                        + "  writable: true,"
                        + "  required: false,"
                        + "  datePattern: 'dd-MMM-yyyy'"
                        + "},"
                        + "{"
                        + "  id: 'end',"
                        + "  name: 'End',"
                        + "  type: 'date',"
                        + "  value: null,"
                        + "  readable: true,"
                        + "  writable: true,"
                        + "  required: false,"
                        + "  datePattern: 'dd/MM/yyyy'"
                        + "},"
                        + "{"
                        + "id: 'direction',"
                        + "  name: null,"
                        + "  type: 'enum',"
                        + "  value: null,"
                        + "  readable: true,"
                        + "  writable: true,"
                        + "  required: false,"
                        + "  datePattern: null,"
                        + "  enumValues: [ {"
                        + "    id: 'left',"
                        + "    name: 'Go Left'"
                        + "  },"
                        + "  {"
                        + "    id: 'right',"
                        + "    name: 'Go Right'"
                        + "  },"
                        + "  {"
                        + "    id: 'up',"
                        + "    name: 'Go Up'"
                        + "  },"
                        + "  {"
                        + "    id: 'down',"
                        + "    name: 'Go Down'"
                        + "   } ]"
                        + "} ]"
                        + "}"
                );

        response = executeRequest(new HttpGet(
                        SERVER_URL_PREFIX + RestUrls.createRelativeResourceUrl(RestUrls.URL_FORM_DATA) + "?processDefinitionId=" + processInstance
                                .getProcessDefinitionId()),
                HttpStatus.SC_OK);

        // Check resulting task
        responseNode = objectMapper.readTree(response.getEntity().getContent());
        closeResponse(response);

        assertThatJson(responseNode)
                .when(Option.IGNORING_EXTRA_FIELDS, Option.IGNORING_ARRAY_ORDER)
                .isEqualTo("{"
                        + "formProperties: [ {"
                        + "  id: 'number',"
                        + "  name: 'Number',"
                        + "  type: 'long',"
                        + "  value: null,"
                        + "  readable: true,"
                        + "  writable: true,"
                        + "  required: false"
                        + "},"
                        + "{"
                        + "  id: 'description',"
                        + "  name: 'Description',"
                        + "  type: null,"
                        + "  value: null,"
                        + "  readable: true,"
                        + "  writable: true,"
                        + "  required: false"
                        + "} ]"
                        + "}"
                );

        closeResponse(executeRequest(new HttpGet(SERVER_URL_PREFIX + RestUrls.createRelativeResourceUrl(RestUrls.URL_FORM_DATA) + "?processDefinitionId=123"),
                HttpStatus.SC_NOT_FOUND));

        closeResponse(executeRequest(new HttpGet(SERVER_URL_PREFIX + RestUrls.createRelativeResourceUrl(RestUrls.URL_FORM_DATA) + "?processDefinitionId2=123"),
                HttpStatus.SC_BAD_REQUEST));
    }