/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.rest.service.api.runtime;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.test.Deployment;
import org.activiti.rest.service.BaseSpringRestTestCase;
import org.activiti.rest.service.HttpMultipartHelper;
import org.activiti.rest.service.api.RestUrls;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Test for all REST-operations related to a single task variable.
*
* @author Frederik Heremans
*/
public class ProcessInstanceVariableResourceTest extends BaseSpringRestTestCase {
/**
* Test getting a process instance variable. GET
* runtime/process-instances/{processInstanceId}/variables/{variableName}
*/
@Deployment(resources = {"org/activiti/rest/service/api/runtime/ProcessInstanceVariableResourceTest.testProcess.bpmn20.xml"})
public void testGetProcessInstanceVariable() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess");
runtimeService.setVariable(processInstance.getId(), "variable", "processValue");
CloseableHttpResponse response = executeRequest(new HttpGet(SERVER_URL_PREFIX +
RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE, processInstance.getId(), "variable")), HttpStatus.SC_OK);
JsonNode responseNode = objectMapper.readTree(response.getEntity().getContent());
closeResponse(response);
assertNotNull(responseNode);
assertEquals("processValue", responseNode.get("value").asText());
assertEquals("variable", responseNode.get("name").asText());
assertEquals("string", responseNode.get("type").asText());
// Illegal scope
closeResponse(executeRequest(new HttpGet(SERVER_URL_PREFIX +
RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE, processInstance.getId(), "variable") + "?scope=illegal"), HttpStatus.SC_BAD_REQUEST));
// Unexisting process
closeResponse(executeRequest(new HttpGet(SERVER_URL_PREFIX +
RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE, "unexisting", "variable")), HttpStatus.SC_NOT_FOUND));
// Unexisting variable
closeResponse(executeRequest(new HttpGet(SERVER_URL_PREFIX +
RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE, processInstance.getId(), "unexistingVariable")), HttpStatus.SC_NOT_FOUND));
}
/**
* Test getting a process instance variable data.
* GET runtime/process-instances/{processInstanceId}/variables/{variableName}
*/
@Deployment(resources = {"org/activiti/rest/service/api/runtime/ProcessInstanceVariableResourceTest.testProcess.bpmn20.xml"})
public void testGetProcessInstanceVariableData() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess");
runtimeService.setVariableLocal(processInstance.getId(), "var", "This is a binary piece of text".getBytes());
CloseableHttpResponse response = executeRequest(new HttpGet(SERVER_URL_PREFIX +
RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE_DATA, processInstance.getId(), "var")), HttpStatus.SC_OK);
String actualResponseBytesAsText = IOUtils.toString(response.getEntity().getContent());
closeResponse(response);
assertEquals("This is a binary piece of text", actualResponseBytesAsText);
assertEquals("application/octet-stream", response.getEntity().getContentType().getValue());
}
/**
* Test getting a process instance variable data.
* GET runtime/process-instances/{processInstanceId}/variables/{variableName}
*/
@Deployment(resources = {"org/activiti/rest/service/api/runtime/ProcessInstanceVariableResourceTest.testProcess.bpmn20.xml"})
public void testGetProcessInstanceVariableDataSerializable() throws Exception {
TestSerializableVariable originalSerializable = new TestSerializableVariable();
originalSerializable.setSomeField("This is some field");
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess");
runtimeService.setVariableLocal(processInstance.getId(), "var", originalSerializable);
CloseableHttpResponse response = executeRequest(new HttpGet(SERVER_URL_PREFIX +
RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE_DATA, processInstance.getId(), "var")), HttpStatus.SC_OK);
// Read the serializable from the stream
ObjectInputStream stream = new ObjectInputStream(response.getEntity().getContent());
Object readSerializable = stream.readObject();
assertNotNull(readSerializable);
assertTrue(readSerializable instanceof TestSerializableVariable);
assertEquals("This is some field", ((TestSerializableVariable) readSerializable).getSomeField());
assertEquals("application/x-java-serialized-object", response.getEntity().getContentType().getValue());
closeResponse(response);
}
/**
* Test getting a process instance variable, for illegal vars.
* GET runtime/process-instances/{processInstanceId}/variables/{variableName}
*/
@Deployment(resources = {"org/activiti/rest/service/api/runtime/ProcessInstanceVariableResourceTest.testProcess.bpmn20.xml"})
public void testGetProcessInstanceVariableDataForIllegalVariables() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess");
runtimeService.setVariableLocal(processInstance.getId(), "localTaskVariable", "this is a plain string variable");
// Try getting data for non-binary variable
closeResponse(executeRequest(new HttpGet(SERVER_URL_PREFIX +
RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE_DATA, processInstance.getId(), "localTaskVariable")), HttpStatus.SC_NOT_FOUND));
// Try getting data for unexisting property
closeResponse(executeRequest(new HttpGet(SERVER_URL_PREFIX +
RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE_DATA, processInstance.getId(), "unexistingVariable")), HttpStatus.SC_NOT_FOUND));
}
/**
* Test deleting a single process variable in, including "not found" check.
*
* DELETE runtime/process-instances/{processInstanceId}/variables/{variableName}
*/
@Deployment(resources = {"org/activiti/rest/service/api/runtime/ProcessInstanceVariableResourceTest.testProcess.bpmn20.xml"})
public void testDeleteProcessVariable() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess",
Collections.singletonMap("myVariable", (Object) "processValue"));
// Delete variable
closeResponse(executeRequest(new HttpDelete(SERVER_URL_PREFIX +
RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE, processInstance.getId(), "myVariable")), HttpStatus.SC_NO_CONTENT));
assertFalse(runtimeService.hasVariable(processInstance.getId(), "myVariable"));
// Run the same delete again, variable is not there so 404 should be returned
closeResponse(executeRequest(new HttpDelete(SERVER_URL_PREFIX +
RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE, processInstance.getId(), "myVariable")), HttpStatus.SC_NOT_FOUND));
}
/**
* Test updating a single process variable, including "not found" check.
*
* PUT runtime/process-instances/{processInstanceId}/variables/{variableName}
*/
@Deployment(resources = {"org/activiti/rest/service/api/runtime/ProcessInstanceVariableResourceTest.testProcess.bpmn20.xml"})
public void testUpdateProcessVariable() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess",
Collections.singletonMap("overlappingVariable", (Object) "processValue"));
runtimeService.setVariable(processInstance.getId(), "myVar", "value");
// Update variable
ObjectNode requestNode = objectMapper.createObjectNode();
requestNode.put("name", "myVar");
requestNode.put("value", "updatedValue");
requestNode.put("type", "string");
HttpPut httpPut = new HttpPut(SERVER_URL_PREFIX +
RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE, processInstance.getId(), "myVar"));
httpPut.setEntity(new StringEntity(requestNode.toString()));
CloseableHttpResponse response = executeRequest(httpPut, HttpStatus.SC_OK);
JsonNode responseNode = objectMapper.readTree(response.getEntity().getContent());
closeResponse(response);
assertNotNull(responseNode);
assertEquals("updatedValue", responseNode.get("value").asText());
// Try updating with mismatch between URL and body variableName
requestNode.put("name", "unexistingVariable");
httpPut.setEntity(new StringEntity(requestNode.toString()));
closeResponse(executeRequest(httpPut, HttpStatus.SC_BAD_REQUEST));
// Try updating unexisting property
requestNode.put("name", "unexistingVariable");
httpPut = new HttpPut(SERVER_URL_PREFIX +
RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE, processInstance.getId(), "unexistingVariable"));
httpPut.setEntity(new StringEntity(requestNode.toString()));
closeResponse(executeRequest(httpPut, HttpStatus.SC_NOT_FOUND));
}
/**
* Test updating a single process variable using a binary stream.
* PUT runtime/process-instances/{processInstanceId}/variables/{variableName}
*/
@Deployment(resources = {"org/activiti/rest/service/api/runtime/ProcessInstanceVariableResourceTest.testProcess.bpmn20.xml"})
public void testUpdateBinaryProcessVariable() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess",
Collections.singletonMap("overlappingVariable", (Object) "processValue"));
runtimeService.setVariable(processInstance.getId(), "binaryVariable", "Initial binary value".getBytes());
InputStream binaryContent = new ByteArrayInputStream("This is binary content".getBytes());
// Add name and type
Map<String, String> additionalFields = new HashMap<String, String>();
additionalFields.put("name", "binaryVariable");
additionalFields.put("type", "binary");
HttpPut httpPut = new HttpPut(SERVER_URL_PREFIX +
RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE, processInstance.getId(), "binaryVariable"));
httpPut.setEntity(HttpMultipartHelper.getMultiPartEntity("value", "application/octet-stream", binaryContent, additionalFields));
CloseableHttpResponse response = executeBinaryRequest(httpPut, HttpStatus.SC_OK);
JsonNode responseNode = objectMapper.readTree(response.getEntity().getContent());
closeResponse(response);
assertNotNull(responseNode);
assertEquals("binaryVariable", responseNode.get("name").asText());
assertTrue(responseNode.get("value").isNull());
assertEquals("binary", responseNode.get("type").asText());
assertNotNull(responseNode.get("valueUrl").isNull());
assertTrue(responseNode.get("valueUrl").asText()
.endsWith(RestUrls.createRelativeResourceUrl(RestUrls.URL_PROCESS_INSTANCE_VARIABLE_DATA,processInstance.getId(), "binaryVariable")));
// Check actual value of variable in engine
Object variableValue = runtimeService.getVariableLocal(processInstance.getId(), "binaryVariable");
assertNotNull(variableValue);
assertTrue(variableValue instanceof byte[]);
assertEquals("This is binary content", new String((byte[]) variableValue));
}
}