StateMachineResource { @GET @Path("/{stateMachineName}/states/errored") @Produces(MediaType.APPLICATION_JSON) public Response getErroredStates(@PathParam("stateMachineName") String stateMachineName, @QueryParam("fromTime") String fromTime, @QueryParam("toTime") String toTime) { if (fromTime == null || toTime == null) { return Response.status(Response.Status.BAD_REQUEST).entity("Required params fromTime/toTime are not provided").build(); } Timestamp fromTimestamp = Timestamp.valueOf(fromTime); Timestamp toTimestamp = Timestamp.valueOf(toTime); if (fromTimestamp.after(toTimestamp)) { return Response.status(Response.Status.BAD_REQUEST).entity("fromTime: " + fromTime + " should be before toTime: " + toTime).build(); } return Response.status(200).entity(parallelScatterGatherQueryHelper.findErroredStates(stateMachineName, fromTimestamp, toTimestamp)).build(); } @Inject  StateMachineResource(EventsDAO eventsDAO, StateMachinePersistenceService stateMachinePersistenceService,
                                AuditDAO auditDAO, StateMachinesDAO stateMachinesDAO, StatesDAO statesDAO,
                                WorkFlowExecutionController workFlowExecutionController, MetricsClient metricsClient,
                                ParallelScatterGatherQueryHelper parallelScatterGatherQueryHelper,
                                EventSchedulerRegistry eventSchedulerRegistry,
                                EventProxyConnector eventProxyConnector,
                                @Named("eventProxyForMigration.enabled") String eventProxyEnabled); @POST @Consumes(MediaType.APPLICATION_JSON) @Timed Response createStateMachine(StateMachineDefinition stateMachineDefinition); @POST @Path("/{machineId}/context/events") @Timed Response submitEvent(@PathParam("machineId") String machineId,
                                @QueryParam("searchField") String searchField,
                                @QueryParam("triggerTime") Long triggerTime,
                                EventData eventData
    ); @POST @Path("/{machineId}/context/eventandstatus") @Timed Response submitEvent(@PathParam("machineId") String machineId,
                                EventAndExecutionData eventAndExecutionData
    ); @POST @Path("/{machineId}/context/eventupdate") @Timed Response updateEvent(@PathParam("machineId") String machineId,
                                EventData eventData
    ); boolean validateEventUpdate(List<Object[]> states); @POST @Path("/{machineId}/{stateId}/status") @Timed Response updateStatus(@PathParam("machineId") String machineId,
                                 @PathParam("stateId") Long stateId,
                                 ExecutionUpdateData executionUpdateData
    ); @POST @Path("/{machineId}/{stateId}/retries/inc") @Transactional @SelectDataSource(type = DataSourceType.READ_WRITE, storage = Storage.SHARDED) Response incrementRetry(@PathParam("machineId") String machineId,
                                   @PathParam("stateId") Long stateId
    ); @POST @Produces(MediaType.APPLICATION_JSON) @Path("/redrivetask/{machineId}/taskId/{taskId}") @Timed Response redriveTask(@PathParam("machineId") String machineId, @PathParam("taskId") Long taskId); @GET @Path("/{machineId}/fsmdata") @Produces(MediaType.APPLICATION_JSON) Response getFsmGraphData(@PathParam("machineId") String machineId); @GET @Path("/{stateMachineName}/states/errored") @Produces(MediaType.APPLICATION_JSON) Response getErroredStates(@PathParam("stateMachineName") String stateMachineName,
                                     @QueryParam("fromTime") String fromTime,
                                     @QueryParam("toTime") String toTime); @GET @Path("/{stateMachineName}/states/listbytime") @Produces(MediaType.APPLICATION_JSON) Response getStatesByTime(@PathParam("stateMachineName") String stateMachineName,
                                    @QueryParam("fromTime") String fromTime,
                                    @QueryParam("toTime") String toTime,
                                    @QueryParam("stateName") String stateName,
                                    @QueryParam("statuses") final List<String> statusStrings); @PUT @Path("/{stateMachineId}/{stateId}/unsideline") @Produces(MediaType.APPLICATION_JSON) @Transactional @SelectDataSource(type = DataSourceType.READ_WRITE, storage = Storage.SHARDED) Response unsidelineState(@PathParam("stateMachineId") String stateMachineId, @PathParam("stateId") Long stateId); @PUT @Path("/{stateMachineId}/cancel") @Produces(MediaType.APPLICATION_JSON) @Transactional @SelectDataSource(type = DataSourceType.READ_WRITE, storage = Storage.SHARDED) Response cancelWorkflow(@PathParam("stateMachineId") String stateMachineId,
                                   @QueryParam("searchField") String searchField); @GET @Path("/{stateMachineId}/info") @Produces(MediaType.APPLICATION_JSON) @Transactional @SelectDataSource(type = DataSourceType.READ_WRITE, storage = Storage.SHARDED) Response getStateMachine(@PathParam("stateMachineId") String stateMachineId,
                                    @QueryParam("searchField") String searchField);  }
@Test public void testGetErroredStates() throws Exception { final StateMachine sm = stateMachinePersistenceService.createStateMachine(standardStateMachine, objectMapper.readValue(this.getClass().getClassLoader().getResource("state_machine_definition.json"), StateMachineDefinition.class)); sm.getStates().stream().findFirst().get().setStatus(Status.errored); String firstSmId = "state-machine-1"; sm.getStates().stream().forEach(state -> { state.setStateMachineId(firstSmId); }); Set<State> states = new HashSet<>(); states.addAll(sm.getStates()); Timestamp now = new Timestamp(System.currentTimeMillis() - 10 * 1000); final StateMachine firstSM = stateMachinesDAO.create(firstSmId, new StateMachine(firstSmId, sm.getVersion(), sm.getName(), sm.getDescription(), states, sm.getClientElbId())); final String differentSMName = "state-machine-2"; sm.getStates().stream().forEach(state -> { state.setStateMachineId(differentSMName); }); states.clear(); states.addAll(sm.getStates()); final StateMachine secondSM = stateMachinesDAO.create(differentSMName, new StateMachine( differentSMName, sm.getVersion(), sm.getName(), sm.getDescription(), states, sm.getClientElbId())); Timestamp future = new Timestamp(System.currentTimeMillis() + 3 * 1000); final HttpResponse<String> stringHttpResponse = Unirest.get( STATE_MACHINE_RESOURCE_URL + "/" + "test_state_machine" + "/states/errored?fromTime=" + now.toString().replace(' ', '+') + "&toTime=" + future.toString().replace(' ', '+')).header("Content-Type", "application/json").asString(); assertThat(stringHttpResponse.getStatus()).isEqualTo(200); assertThat(stringHttpResponse.getBody()).isEqualTo("[[\"" + firstSM.getId() + "\"," + firstSM.getStates().stream().filter(e -> Status.errored.equals(e.getStatus())).findFirst().get().getId() + "," + "\"errored\"]," + "[\"" + secondSM.getId() + "\"," + secondSM.getStates().stream().filter(e -> Status.errored.equals(e.getStatus())).findFirst().get().getId() + "," + "\"errored\"]" + "]"); }