public <T> T execute(Command<T> command) { ClientRequest restRequest = new ClientRequest(url); try { restRequest.body(MediaType.APPLICATION_XML, new JaxbCommandsRequest(deploymentId, command)); ClientResponse<Object> response = restRequest.post(Object.class); if (response.getResponseStatus() == Status.OK) { JaxbCommandsResponse commandResponse = response.getEntity(JaxbCommandsResponse.class); List<JaxbCommandResponse<?>> responses = commandResponse.getResponses(); if (responses.size() == 0) { return null; } else if (responses.size() == 1) { JaxbCommandResponse<?> responseObject = responses.get(0); if (responseObject instanceof JaxbExceptionResponse) { JaxbExceptionResponse exceptionResponse = (JaxbExceptionResponse) responseObject; String causeMessage = exceptionResponse.getCauseMessage(); throw new RuntimeException( exceptionResponse.getMessage() + (causeMessage == null ? "" : " Caused by: " + causeMessage)); } else { return (T) responseObject.getResult(); } } else { throw new RuntimeException("Unexpected number of results: " + responses.size()); } } else { // TODO error handling throw new RuntimeException("REST request error code " + response.getResponseStatus()); } } catch (Exception e) { throw new RuntimeException("Unable to execute REST request: " + e.getMessage(), e); } }
/** * Method to communicate with the backend via REST. * * @param command The {@link Command} object to be executed. * @return The result of the {@link Command} object execution. */ private <T> T executeRestCommand(Command command) { String cmdName = command.getClass().getSimpleName(); JaxbCommandsRequest jaxbRequest = prepareCommandRequest( command, config.getUserName(), config.getDeploymentId(), config.getProcessInstanceId(), config.getCorrelationProperties()); KieRemoteHttpRequest httpRequest = config.createHttpRequest().relativeRequest("/execute"); // necessary for deserialization String deploymentId = config.getDeploymentId(); if (!emptyDeploymentId(deploymentId)) { httpRequest.header(JaxbSerializationProvider.EXECUTE_DEPLOYMENT_ID_HEADER, deploymentId); } String jaxbRequestString = config.getJaxbSerializationProvider().serialize(jaxbRequest); if (logger.isTraceEnabled()) { try { logger.trace( "Sending {} via POST to {}", command.getClass().getSimpleName(), httpRequest.getUri()); } catch (Exception e) { // do nothing because this should never happen.. } logger.trace("Serialized JaxbCommandsRequest:\n {}", jaxbRequestString); } KieRemoteHttpResponse httpResponse = null; try { logger.debug( "Sending POST request with " + command.getClass().getSimpleName() + " to " + httpRequest.getUri()); httpRequest.contentType(MediaType.APPLICATION_XML); httpRequest.accept(MediaType.APPLICATION_XML); httpRequest.body(jaxbRequestString); httpRequest.post(); httpResponse = httpRequest.response(); } catch (Exception e) { httpRequest.disconnect(); throw new RemoteCommunicationException("Unable to send HTTP POST request", e); } // Get response boolean htmlException = false; JaxbExceptionResponse exceptionResponse = null; JaxbCommandsResponse cmdResponse = null; int responseStatus; try { responseStatus = httpResponse.code(); String content = httpResponse.body(); if (responseStatus < 300) { cmdResponse = deserializeResponseContent(content, JaxbCommandsResponse.class); // check version String version = cmdResponse.getVersion(); if (version == null) { version = "pre-6.0.3"; } if (!version.equals(VERSION)) { logger.info( "Response received from server version [{}] while client is version [{}]! This may cause problems.", version, VERSION); } } else { String contentType = httpResponse.contentType(); if (contentType.equals(MediaType.APPLICATION_XML)) { Object response = deserializeResponseContent(content, JaxbExceptionResponse.class); if (response instanceof JaxbRestRequestException) { JaxbRestRequestException exception = (JaxbRestRequestException) response; exceptionResponse = new JaxbExceptionResponse( exception.getUrl(), exception.getCause(), exception.getStatus()); exceptionResponse.setCommandName(cmdName); exceptionResponse.setIndex(0); exceptionResponse.setMessage(exception.getMessage()); } else if (response instanceof JaxbExceptionResponse) { exceptionResponse = (JaxbExceptionResponse) response; } } else if (contentType.startsWith(MediaType.TEXT_HTML)) { htmlException = true; exceptionResponse = new JaxbExceptionResponse(); Document doc = Jsoup.parse(content); String body = doc.body().text(); exceptionResponse.setMessage(body); exceptionResponse.setUrl(httpRequest.getUri().toString()); exceptionResponse.setStackTrace(""); } else { throw new RemoteCommunicationException( "Unable to deserialize response with content type '" + contentType + "'"); } } } catch (Exception e) { logger.error( "Unable to retrieve response content from request with status {}: {}", e.getMessage(), e); throw new RemoteCommunicationException("Unable to retrieve content from response", e); } finally { httpRequest.disconnect(); } if (cmdResponse != null) { List<JaxbCommandResponse<?>> responses = cmdResponse.getResponses(); if (responses.size() == 0) { return null; } else if (responses.size() == 1) { // The type information *should* come from the Command class -- but it's a jaxb-gen class, // which means that it has lost it's type information.. // TODO: fix this? JaxbCommandResponse<T> responseObject = (JaxbCommandResponse<T>) responses.get(0); if (responseObject instanceof JaxbExceptionResponse) { exceptionResponse = (JaxbExceptionResponse) responseObject; } else { return responseObject.getResult(); } } else { throw new RemoteCommunicationException( "Unexpected number of results from " + command.getClass().getSimpleName() + ":" + responses.size() + " results instead of only 1"); } } logger.error("Response with status {} returned.", responseStatus); // Process exception response switch (responseStatus) { case 409: throw new RemoteTaskException( exceptionResponse.getMessage(), exceptionResponse.getStackTrace()); default: if (exceptionResponse != null) { if (!htmlException) { throw new RemoteApiException( exceptionResponse.getMessage(), exceptionResponse.getStackTrace()); } else { throw new RemoteCommunicationException( exceptionResponse.getMessage(), exceptionResponse.getStackTrace()); } } else { throw new RemoteCommunicationException( "Unable to communicate with remote API via URL " + "'" + httpRequest.getUri().toString() + "'"); } } }
@Test @Ignore("JMS isn't working.. :/") public void testJmsStartProcess() throws Exception { // send cmd Command<?> cmd = new StartProcessCommand("org.jbpm.humantask"); JaxbCommandsRequest req = new JaxbCommandsRequest(DEPLOYMENT_ID, cmd); JaxbCommandsResponse response = sendJmsJaxbCommandsRequest(TASK_QUEUE_NAME, req); // check response assertNotNull("response was null.", response); assertTrue( "response did not contain any command responses", response.getResponses() != null && response.getResponses().size() > 0); JaxbCommandResponse<?> cmdResponse = response.getResponses().get(0); assertTrue( "response is not the proper class type : " + cmdResponse.getClass().getSimpleName(), cmdResponse instanceof JaxbProcessInstanceResponse); ProcessInstance procInst = (ProcessInstance) cmdResponse; long procInstId = procInst.getId(); // send cmd cmd = new GetTasksByProcessInstanceIdCommand(procInstId); req = new JaxbCommandsRequest(DEPLOYMENT_ID, cmd); response = sendJmsJaxbCommandsRequest(TASK_QUEUE_NAME, req); // check response assertNotNull("response was null.", response); assertTrue( "response did not contain any command responses", response.getResponses() != null && response.getResponses().size() > 0); cmdResponse = response.getResponses().get(0); assertTrue( "response is not the proper class type : " + cmdResponse.getClass().getSimpleName(), cmdResponse instanceof JaxbLongListResponse); long taskId = ((JaxbLongListResponse) cmdResponse).getResult().get(0); // send cmd cmd = new StartTaskCommand(taskId, USER_ID); req = new JaxbCommandsRequest(DEPLOYMENT_ID, cmd); req.getCommands().add(new CompleteTaskCommand(taskId, USER_ID, null)); response = sendJmsJaxbCommandsRequest(TASK_QUEUE_NAME, req); // check response assertNotNull("response was null.", response); assertTrue("response list was not empty", response.getResponses().size() == 0); // send cmd cmd = new GetTasksOwnedCommand(USER_ID, "en-UK"); req = new JaxbCommandsRequest(DEPLOYMENT_ID, cmd); req.getCommands().add(new GetTasksOwnedCommand("bob", "fr-CA")); req.getCommands().add(new GetProcessInstanceCommand(procInstId)); response = sendJmsJaxbCommandsRequest(TASK_QUEUE_NAME, req); assertNotNull("response was null.", response); assertTrue( "response did not contain any command responses", response.getResponses() != null && response.getResponses().size() > 0); cmdResponse = response.getResponses().get(0); assertTrue( "response is not the proper class type : " + cmdResponse.getClass().getSimpleName(), cmdResponse instanceof JaxbTaskSummaryListResponse); List<TaskSummary> taskSummaries = ((JaxbTaskSummaryListResponse) cmdResponse).getResult(); assertTrue("task summary list is empty", taskSummaries.size() > 0); for (TaskSummary taskSum : taskSummaries) { if (taskSum.getId() == taskId) { assertTrue( "Task " + taskId + " should have completed.", taskSum.getStatus().equals(Status.Completed)); } } cmdResponse = response.getResponses().get(1); assertTrue( "response is not the proper class type : " + cmdResponse.getClass().getSimpleName(), cmdResponse instanceof JaxbTaskSummaryListResponse); taskSummaries = ((JaxbTaskSummaryListResponse) cmdResponse).getResult(); assertTrue( "task summary list should be empty, but has " + taskSummaries.size() + " elements", taskSummaries.size() == 0); cmdResponse = response.getResponses().get(2); assertNotNull(cmdResponse); }