提交 9ac989ae 编写于 作者: J Joram Barrez

Merge branch 'master' of github.com:Activiti/Activiti

......@@ -19,9 +19,23 @@ import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.impl.DefaultComponent;
/**
* This class has been modified to be consistent with the changes to CamelBehavior and its implementations. The set of changes
* significantly increases the flexibility of our Camel integration, as you can either choose one of three "out-of-the-box" modes,
* or you can choose to create your own. Please reference the comments for the "CamelBehavior" class for more information on the
* out-of-the-box implementation class options.
*
* @author Ryan Johnston (@rjfsu), Tijs Rademakers
*/
public class ActivitiComponent extends DefaultComponent {
private RuntimeService runtimeService;
private boolean copyVariablesToProperties;
private boolean copyVariablesToBodyAsMap;
private boolean copyCamelBodyToBody;
public ActivitiComponent() {}
......@@ -43,6 +57,33 @@ public class ActivitiComponent extends DefaultComponent {
@Override
protected Endpoint createEndpoint(String s, String s1, Map<String, Object> stringObjectMap) throws Exception {
ActivitiEndpoint ae = new ActivitiEndpoint(s, getCamelContext(), runtimeService);
ae.setCopyVariablesToProperties(this.copyVariablesToProperties);
ae.setCopyVariablesToBodyAsMap(this.copyVariablesToBodyAsMap);
ae.setCopyCamelBodyToBody(this.copyCamelBodyToBody);
return ae;
}
public boolean isCopyVariablesToProperties() {
return copyVariablesToProperties;
}
public void setCopyVariablesToProperties(boolean copyVariablesToProperties) {
this.copyVariablesToProperties = copyVariablesToProperties;
}
public boolean isCopyCamelBodyToBody() {
return copyCamelBodyToBody;
}
public void setCopyCamelBodyToBody(boolean copyCamelBodyToBody) {
this.copyCamelBodyToBody = copyCamelBodyToBody;
}
public boolean isCopyVariablesToBodyAsMap() {
return copyVariablesToBodyAsMap;
}
public void setCopyVariablesToBodyAsMap(boolean copyVariablesToBodyAsMap) {
this.copyVariablesToBodyAsMap = copyVariablesToBodyAsMap;
}
}
......@@ -17,17 +17,27 @@ import org.activiti.engine.RuntimeService;
import org.apache.camel.*;
import org.apache.camel.impl.DefaultEndpoint;
/**
* This class has been modified to be consistent with the changes to CamelBehavior and its implementations. The set of changes
* significantly increases the flexibility of our Camel integration, as you can either choose one of three "out-of-the-box" modes,
* or you can choose to create your own. Please reference the comments for the "CamelBehavior" class for more information on the
* out-of-the-box implementation class options.
*
* @author Ryan Johnston (@rjfsu), Tijs Rademakers
*/
public class ActivitiEndpoint extends DefaultEndpoint {
private RuntimeService runtimeService;
private ActivitiConsumer activitiConsumer;
private boolean copyVariablesToProperties = true;
private boolean copyVariablesToProperties;
private boolean copyVariablesToBody = false;
private boolean copyVariablesToBodyAsMap;
private boolean copyVariablesFromProperties = false;
private boolean copyCamelBodyToBody;
private boolean copyVariablesFromProperties;
public ActivitiEndpoint(String uri, CamelContext camelContext, RuntimeService runtimeService) {
super();
......@@ -48,10 +58,8 @@ public class ActivitiEndpoint extends DefaultEndpoint {
throw new RuntimeException("Activiti consumer not defined for " + getEndpointUri());
}
activitiConsumer.getProcessor().process(ex);
}
public Producer createProducer() throws Exception {
return new ActivitiProducer(this, runtimeService);
}
......@@ -72,14 +80,22 @@ public class ActivitiEndpoint extends DefaultEndpoint {
this.copyVariablesToProperties = copyVariablesToProperties;
}
public boolean isCopyVariablesToBody() {
return copyVariablesToBody;
public boolean isCopyCamelBodyToBody() {
return copyCamelBodyToBody;
}
public void setCopyVariablesToBody(boolean copyVariablesToBody) {
this.copyVariablesToBody = copyVariablesToBody;
public void setCopyCamelBodyToBody(boolean copyCamelBodyToBody) {
this.copyCamelBodyToBody = copyCamelBodyToBody;
}
public boolean isCopyVariablesToBodyAsMap() {
return copyVariablesToBodyAsMap;
}
public void setCopyVariablesToBodyAsMap(boolean copyVariablesToBodyAsMap) {
this.copyVariablesToBodyAsMap = copyVariablesToBodyAsMap;
}
public boolean isCopyVariablesFromProperties() {
return copyVariablesFromProperties;
}
......
......@@ -31,39 +31,61 @@ import org.apache.camel.Exchange;
import org.apache.camel.impl.DefaultExchange;
import org.apache.commons.lang.StringUtils;
public class CamelBehavior extends BpmnActivityBehavior implements ActivityBehavior {
/**
* This abstract class takes the place of the now-deprecated CamelBehaviour class (which can still be used for legacy compatibility)
* and significantly improves on its flexibility. Additional implementations can be created that change the way in which Activiti
* interacts with Camel per your specific needs.
*
* Three out-of-the-box implementations of CamelBehavior are provided:
* (1) CamelBehaviorDefaultImpl: Works just like CamelBehaviour does; copies variables into and out of Camel as or from properties.
* (2) CamelBehaviorBodyAsMapImpl: Works by copying variables into and out of Camel using a Map<String,Object> object in the body.
* (3) CamelBehaviorCamelBodyImpl: Works by copying a single variable value into Camel as a String body and copying the Camel
* body into that same Activiti variable. The variable in Activiti must be named "camelBody".
*
* The chosen implementation should be set within your ProcessEngineConfiguration. To specify the implementation using Spring, include
* the following line in your configuration file as part of the properties for "org.activiti.spring.SpringProcessEngineConfiguration":
*
* <property name="camelBehaviorClass" value="org.activiti.camel.impl.CamelBehaviorCamelBodyImpl"/>
*
* Note also that the manner in which variables are copied to Activiti from Camel has changed. It will always copy Camel
* properties to the Activiti variable set; they can safely be ignored, of course, if not required. It will conditionally
* copy the Camel body to the "camelBody" variable if it is of type java.lang.String, OR it will copy the Camel body to
* individual variables within Activiti if it is of type Map<String,Object>.
*
* @author Ryan Johnston (@rjfsu), Tijs Rademakers
* @version 5.12
*/
public abstract class CamelBehavior extends BpmnActivityBehavior implements ActivityBehavior {
private static final long serialVersionUID = 1L;
protected Expression camelContext;
protected CamelContext camelContextObj;
protected SpringProcessEngineConfiguration springConfiguration;
protected abstract void modifyActivitiComponent(ActivitiComponent component);
protected abstract void copyVariables(Map<String, Object> variables, Exchange exchange, ActivitiEndpoint endpoint);
public void execute(ActivityExecution execution) throws Exception {
ProcessEngineConfiguration engineConfiguration = Context.getProcessEngineConfiguration();
if (engineConfiguration instanceof SpringProcessEngineConfiguration == false) {
throw new ActivitiException("Expecting a Spring process engine configuration for the Activiti Camel module");
}
SpringProcessEngineConfiguration springConfiguration = (SpringProcessEngineConfiguration) engineConfiguration;
String camelContextValue = getStringFromField(camelContext, execution);
if (StringUtils.isEmpty(camelContextValue)) {
camelContextValue = springConfiguration.getDefaultCamelContext();
}
setAppropriateCamelContext(execution);
//Retrieve the ActivitiComponent object.
ActivitiComponent component = camelContextObj.getComponent("activiti", ActivitiComponent.class);
modifyActivitiComponent(component);
ActivitiEndpoint endpoint = createEndpoint(execution, springConfiguration, camelContextValue);
Exchange exchange = createExchange(execution, endpoint, springConfiguration, camelContextValue);
ActivitiEndpoint endpoint = createEndpoint(execution);
Exchange exchange = createExchange(execution, endpoint);
endpoint.process(exchange);
execution.setVariables(ExchangeUtils.prepareVariables(exchange, endpoint));
performDefaultOutgoingBehavior(execution);
}
private ActivitiEndpoint createEndpoint(ActivityExecution execution, SpringProcessEngineConfiguration springConfiguration, String camelContext) {
protected ActivitiEndpoint createEndpoint(ActivityExecution execution) {
String uri = "activiti://" + getProcessDefinitionKey(execution) + ":" + execution.getActivity().getId();
return getEndpoint(getContext(springConfiguration, camelContext), uri);
return getEndpoint(uri);
}
private ActivitiEndpoint getEndpoint(CamelContext ctx, String key) {
for (Endpoint e : ctx.getEndpoints()) {
protected ActivitiEndpoint getEndpoint(String key) {
for (Endpoint e : camelContextObj.getEndpoints()) {
if (e.getEndpointKey().equals(key) && (e instanceof ActivitiEndpoint)) {
return (ActivitiEndpoint) e;
}
......@@ -71,37 +93,72 @@ public class CamelBehavior extends BpmnActivityBehavior implements ActivityBehav
throw new RuntimeException("Activiti endpoint not defined for " + key);
}
private CamelContext getContext(SpringProcessEngineConfiguration springConfiguration, String camelContext) {
Object ctx = springConfiguration.getApplicationContext().getBean(camelContext);
if (ctx == null || ctx instanceof CamelContext == false) {
throw new RuntimeException("Could not find camel context " + camelContext);
}
return (CamelContext) ctx;
}
private Exchange createExchange(ActivityExecution activityExecution, ActivitiEndpoint endpoint,
SpringProcessEngineConfiguration springConfiguration, String camelContext) {
Exchange ex = new DefaultExchange(getContext(springConfiguration, camelContext));
protected Exchange createExchange(ActivityExecution activityExecution, ActivitiEndpoint endpoint) {
Exchange ex = new DefaultExchange(camelContextObj);
ex.setProperty(ActivitiProducer.PROCESS_ID_PROPERTY, activityExecution.getProcessInstanceId());
Map<String, Object> variables = activityExecution.getVariables();
if (endpoint.isCopyVariablesToProperties()) {
for (Map.Entry<String, Object> var : variables.entrySet()) {
ex.setProperty(var.getKey(), var.getValue());
}
copyVariables(variables, ex, endpoint);
return ex;
}
protected void copyVariablesToProperties(Map<String, Object> variables, Exchange exchange) {
for (Map.Entry<String, Object> var : variables.entrySet()) {
exchange.setProperty(var.getKey(), var.getValue());
}
if (endpoint.isCopyVariablesToBody()) {
ex.getIn().setBody(new HashMap<String,Object>(variables));
}
protected void copyVariablesToBodyAsMap(Map<String, Object> variables, Exchange exchange) {
exchange.getIn().setBody(new HashMap<String,Object>(variables));
}
protected void copyVariablesToBody(Map<String, Object> variables, Exchange exchange) {
Object camelBody = variables.get("camelBody");
if(camelBody != null) {
exchange.getIn().setBody(camelBody);
}
return ex;
}
private String getProcessDefinitionKey(ActivityExecution execution) {
protected String getProcessDefinitionKey(ActivityExecution execution) {
String id = execution.getActivity().getProcessDefinition().getId();
return id.substring(0, id.indexOf(":"));
}
protected void setAppropriateCamelContext(ActivityExecution execution) {
//Check to see if the springConfiguration has been set. If not, set it.
if (springConfiguration == null) {
//Get the ProcessEngineConfiguration object.
ProcessEngineConfiguration engineConfiguration = Context.getProcessEngineConfiguration();
//Convert it to a SpringProcessEngineConfiguration. If this doesn't work, throw a RuntimeException.
// (ActivitiException extends RuntimeException.)
try {
springConfiguration = (SpringProcessEngineConfiguration) engineConfiguration;
} catch (Exception e) {
throw new ActivitiException("Expecting a SpringProcessEngineConfiguration for the Activiti Camel module.", e);
}
}
//Get the appropriate String representation of the CamelContext object from ActivityExecution (if available).
String camelContextValue = getStringFromField(camelContext, execution);
//If the String representation of the CamelContext object from ActivityExecution is empty, use the default.
if (StringUtils.isEmpty(camelContextValue) && camelContextObj != null) {
//No processing required. No custom CamelContext & the default is already set.
}
else {
if (StringUtils.isEmpty(camelContextValue) && camelContextObj == null) {
camelContextValue = springConfiguration.getDefaultCamelContext();
}
//Get the CamelContext object and set the super's member variable.
Object ctx = springConfiguration.getApplicationContext().getBean(camelContextValue);
if (ctx == null || ctx instanceof CamelContext == false) {
throw new ActivitiException("Could not find CamelContext named " + camelContextValue + ".");
}
camelContextObj = (CamelContext)ctx;
}
}
protected String getStringFromField(Expression expression, DelegateExecution execution) {
if (expression != null) {
Object value = expression.getValue(execution);
......
......@@ -25,8 +25,11 @@ import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.impl.DefaultExchange;
@Deprecated
public class CamelBehaviour extends BpmnActivityBehavior implements ActivityBehavior {
private static final long serialVersionUID = 1L;
private Collection<ContextProvider> contextProviders;
public CamelBehaviour(Collection<ContextProvider> camelContext) {
......@@ -76,7 +79,7 @@ public class CamelBehaviour extends BpmnActivityBehavior implements ActivityBeha
ex.setProperty(var.getKey(), var.getValue());
}
}
if (endpoint.isCopyVariablesToBody()) {
if (endpoint.isCopyVariablesToBodyAsMap()) {
ex.getIn().setBody(new HashMap<String,Object>(variables));
}
return ex;
......
......@@ -12,24 +12,52 @@
*/
package org.activiti.camel;
import org.apache.camel.Exchange;
import java.util.HashMap;
import java.util.Map;
import org.apache.camel.Exchange;
/**
* This class contains one method - prepareVariables - that is used to copy variables from Camel into Activiti.
*
* @author Ryan Johnston (@rjfsu), Tijs Rademakers
*/
public class ExchangeUtils {
static Map<String, Object> prepareVariables(Exchange exchange, ActivitiEndpoint activitiEndpoint) {
Map<String, Object> ret = new HashMap<String, Object>();
/**
* Copies variables from Camel into Activiti.
*
* This method will conditionally copy the Camel body to the "camelBody" variable if it is of type java.lang.String, OR it will copy the Camel body to
* individual variables within Activiti if it is of type Map<String,Object>.
* If the copyVariablesFromProperties parameter is set on the endpoint, the properties are copied instead
*
* @param exchange The Camel Exchange object
* @param activitiEndpoint The ActivitiEndpoint implementation
* @return A Map<String,Object> containing all of the variables to be used in Activiti
*/
public static Map<String, Object> prepareVariables(Exchange exchange, ActivitiEndpoint activitiEndpoint) {
boolean shouldReadFromProperties = activitiEndpoint.isCopyVariablesFromProperties();
Map<?, ?> m = shouldReadFromProperties ? exchange.getProperties() : exchange.getIn().getBody(Map.class);
if (m != null) {
for (Map.Entry e : m.entrySet()) {
if (e.getKey() instanceof String) {
ret.put((String) e.getKey(), e.getValue());
Map<String, Object> camelVarMap = null;
if (shouldReadFromProperties) {
camelVarMap = exchange.getProperties();
} else {
camelVarMap = new HashMap<String, Object>();
Object camelBody = exchange.getIn().getBody();
if(camelBody instanceof String) {
camelVarMap.put("camelBody", camelBody);
}
else if(camelBody instanceof Map<?,?>) {
Map<?,?> camelBodyMap = (Map<?,?>)camelBody;
for (@SuppressWarnings("rawtypes") Map.Entry e : camelBodyMap.entrySet()) {
if (e.getKey() instanceof String) {
camelVarMap.put((String) e.getKey(), e.getValue());
}
}
}
}
return ret;
return camelVarMap;
}
}
/* 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.camel.impl;
import java.util.Map;
import org.activiti.camel.ActivitiComponent;
import org.activiti.camel.ActivitiEndpoint;
import org.activiti.camel.CamelBehavior;
import org.apache.camel.Exchange;
/**
* This implementation of the CamelBehavior abstract class works by copying variables into Camel using a
* Map<String,Object> object in the Camel Exchange body.
*
* @author Ryan Johnston (@rjfsu), Tijs Rademakers
*/
public class CamelBehaviorBodyAsMapImpl extends CamelBehavior {
private static final long serialVersionUID = 1L;
@Override
protected void modifyActivitiComponent(ActivitiComponent component) {
//Set the copy method for new endpoints created using this component.
component.setCopyVariablesToProperties(false);
component.setCopyVariablesToBodyAsMap(true);
component.setCopyCamelBodyToBody(false);
}
@Override
protected void copyVariables(Map<String, Object> variables, Exchange exchange, ActivitiEndpoint endpoint) {
if (endpoint.isCopyVariablesToProperties()) {
copyVariablesToBody(variables, exchange);
} else if (endpoint.isCopyVariablesToProperties()) {
copyVariablesToProperties(variables, exchange);
} else {
copyVariablesToBodyAsMap(variables, exchange);
}
}
}
/* 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.camel.impl;
import java.util.Map;
import org.activiti.camel.ActivitiComponent;
import org.activiti.camel.ActivitiEndpoint;
import org.activiti.camel.CamelBehavior;
import org.apache.camel.Exchange;
/**
* This implementation of the CamelBehavior abstract class works by copying a single variable value into the Camel
* Exchange body. The variable must be named "camelBody" to be copied into the Camel Exchange body on the producer
* side of the transfer (i.e. when handing control from Activiti to Camel).
*
* @author Ryan Johnston (@rjfsu), Tijs Rademakers
*/
public class CamelBehaviorCamelBodyImpl extends CamelBehavior {
private static final long serialVersionUID = 1L;
@Override
protected void modifyActivitiComponent(ActivitiComponent component) {
//Set the copy method for new endpoints created using this component.
component.setCopyVariablesToProperties(false);
component.setCopyVariablesToBodyAsMap(false);
component.setCopyCamelBodyToBody(true);
}
@Override
protected void copyVariables(Map<String, Object> variables, Exchange exchange, ActivitiEndpoint endpoint) {
if (endpoint.isCopyVariablesToBodyAsMap()) {
copyVariablesToBodyAsMap(variables, exchange);
} else if (endpoint.isCopyVariablesToProperties()) {
copyVariablesToProperties(variables, exchange);
} else {
copyVariablesToBody(variables, exchange);
}
}
}
/* 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.camel.impl;
import java.util.Map;
import org.activiti.camel.ActivitiComponent;
import org.activiti.camel.ActivitiEndpoint;
import org.activiti.camel.CamelBehavior;
import org.apache.camel.Exchange;
/**
* This implementation of the CamelBehavior abstract class works just like CamelBehaviour does; it copies variables
* into Camel as properties.
*
* @author Ryan Johnston (@rjfsu), Tijs Rademakers
*/
public class CamelBehaviorDefaultImpl extends CamelBehavior {
private static final long serialVersionUID = 003L;
@Override
protected void modifyActivitiComponent(ActivitiComponent component) {
//Set the copy method for new endpoints created using this component.
component.setCopyVariablesToProperties(true);
component.setCopyVariablesToBodyAsMap(false);
component.setCopyCamelBodyToBody(false);
}
@Override
protected void copyVariables(Map<String, Object> variables, Exchange exchange, ActivitiEndpoint endpoint) {
if (endpoint.isCopyVariablesToBodyAsMap()) {
copyVariablesToBodyAsMap(variables, exchange);
} else if (endpoint.isCopyCamelBodyToBody()) {
copyVariablesToBody(variables, exchange);
} else {
copyVariablesToProperties(variables, exchange);
}
}
}
package org.activiti.camel;
import java.util.HashMap;
import java.util.Map;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.Deployment;
import org.activiti.spring.impl.test.SpringActivitiTestCase;
import org.apache.camel.CamelContext;
import org.apache.camel.component.mock.MockEndpoint;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration("classpath:camel-activiti-context.xml")
public class CamelVariableBodyMapTest extends SpringActivitiTestCase {
MockEndpoint service1;
public void setUp() {
CamelContext ctx = applicationContext.getBean(CamelContext.class);
service1 = (MockEndpoint) ctx.getEndpoint("mock:serviceBehavior");
service1.reset();
}
@Deployment(resources = {"process/HelloCamelBodyMap.bpmn20.xml"})
public void testCamelBody() throws Exception {
Map<String, Object> varMap = new HashMap<String, Object>();
varMap.put("camelBody", "hello world");
service1.expectedBodiesReceived(varMap);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("HelloCamel", varMap);
//Ensure that the variable is equal to the expected value.
assertEquals("hello world", runtimeService.getVariable(processInstance.getId(), "camelBody"));
service1.assertIsSatisfied();
Task task = taskService.createTaskQuery().singleResult();
//Ensure that the name of the task is correct.
assertEquals("Hello Task", task.getName());
//Complete the task.
taskService.complete(task.getId());
}
}
package org.activiti.camel;
import java.util.HashMap;
import java.util.Map;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.Deployment;
import org.activiti.spring.impl.test.SpringActivitiTestCase;
import org.apache.camel.CamelContext;
import org.apache.camel.component.mock.MockEndpoint;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration("classpath:camel-activiti-context.xml")
public class CamelVariableBodyTest extends SpringActivitiTestCase {
MockEndpoint service1;
public void setUp() {
CamelContext ctx = applicationContext.getBean(CamelContext.class);
service1 = (MockEndpoint) ctx.getEndpoint("mock:serviceBehavior");
service1.reset();
}
@Deployment(resources = {"process/HelloCamelBody.bpmn20.xml"})
public void testCamelBody() throws Exception {
service1.expectedBodiesReceived("hello world");
Map<String, Object> varMap = new HashMap<String, Object>();
varMap.put("camelBody", "hello world");
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("HelloCamel", varMap);
//Ensure that the variable is equal to the expected value.
assertEquals("hello world", runtimeService.getVariable(processInstance.getId(), "camelBody"));
service1.assertIsSatisfied();
Task task = taskService.createTaskQuery().singleResult();
//Ensure that the name of the task is correct.
assertEquals("Hello Task", task.getName());
//Complete the task.
taskService.complete(task.getId());
}
}
......@@ -47,7 +47,6 @@ public class SimpleProcessTest extends SpringActivitiTestCase {
String instanceId = (String) tpl.requestBody("direct:start", Collections.singletonMap("var1", "ala"));
tpl.sendBodyAndProperty("direct:receive", null, ActivitiProducer.PROCESS_ID_PROPERTY, instanceId);
assertProcessEnded(instanceId);
......@@ -67,7 +66,6 @@ public class SimpleProcessTest extends SpringActivitiTestCase {
MockEndpoint me = (MockEndpoint) ctx.getEndpoint("mock:service1");
me.expectedBodiesReceived("ala");
tpl.sendBodyAndProperty("direct:start", Collections.singletonMap("var1", "ala"), ActivitiProducer.PROCESS_KEY_PROPERTY, "key1");
String instanceId = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey("key1")
......
......@@ -7,7 +7,7 @@ public class TestJoinDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) throws Exception {
System.out.println("testing join delegate");
// dummy task
}
}
......@@ -20,10 +20,10 @@ public class AsyncCamelRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
from("activiti:asyncCamelProcess:serviceTaskAsync1?copyVariablesToProperties=true").setHeader("destination", constant("activiti:asyncCamelProcess:receive1")).to("seda:asyncQueue");
from("activiti:asyncCamelProcess:serviceTaskAsync1").setHeader("destination", constant("activiti:asyncCamelProcess:receive1")).to("seda:asyncQueue");
from("seda:asyncQueue").to("bean:sleepBean?method=sleep").to("seda:receiveQueue");
from("activiti:asyncCamelProcess:serviceTaskAsync2?copyVariablesToProperties=true").setHeader("destination", constant("activiti:asyncCamelProcess:receive2")).to("seda:asyncQueue2");
from("activiti:asyncCamelProcess:serviceTaskAsync2").setHeader("destination", constant("activiti:asyncCamelProcess:receive2")).to("seda:asyncQueue2");
from("seda:asyncQueue2").to("bean:sleepBean?method=sleep").to("seda:receiveQueue");
from("seda:receiveQueue").recipientList(header("destination"));
......
package org.activiti.camel.route;
import org.apache.camel.LoggingLevel;
import org.apache.camel.spring.SpringRouteBuilder;
import org.springframework.stereotype.Component;
@Component
public class CamelBehaviorRoute extends SpringRouteBuilder {
public void configure() {
from("activiti:HelloCamel:serviceTask1")
.log(LoggingLevel.INFO,"Received message on service task")
.to("mock:serviceBehavior");
}
}
......@@ -24,7 +24,7 @@ public class SampleCamelRoute extends RouteBuilder {
.to("mock:service1").setProperty("var2").constant("var2")
.setBody().properties();
from("activiti:camelProcess:serviceTask2?copyVariablesToBody=true")
from("activiti:camelProcess:serviceTask2?copyVariablesToBodyAsMap=true")
.to("mock:service2");
......
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="HelloCamel" name="Hello Camel">
<startEvent id="startevent1" name="Start"></startEvent>
<serviceTask id="serviceTask1" name="Camel" activiti:type="camel">
<extensionElements>
<activiti:field name="camelBehaviorClass" stringValue="org.activiti.camel.impl.CamelBehaviorCamelBodyImpl" />
</extensionElements>
</serviceTask>
<userTask id="userTask1" name="Hello Task" activiti:assignee="kermit"></userTask>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow2" name="" sourceRef="serviceTask1" targetRef="userTask1"></sequenceFlow>
<sequenceFlow id="flow3" name="" sourceRef="userTask1" targetRef="endevent1"></sequenceFlow>
<sequenceFlow id="flow4" name="" sourceRef="startevent1" targetRef="serviceTask1"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_HelloCamel">
<bpmndi:BPMNPlane bpmnElement="HelloCamel" id="BPMNPlane_HelloCamel">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35" width="35" x="60" y="170"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="serviceTask1" id="BPMNShape_serviceTask1">
<omgdc:Bounds height="55" width="105" x="180" y="160"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="userTask1" id="BPMNShape_userTask1">
<omgdc:Bounds height="55" width="105" x="380" y="160"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35" width="35" x="580" y="170"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="285" y="187"></omgdi:waypoint>
<omgdi:waypoint x="380" y="187"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="485" y="187"></omgdi:waypoint>
<omgdi:waypoint x="580" y="187"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="95" y="187"></omgdi:waypoint>
<omgdi:waypoint x="180" y="187"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="HelloCamel" name="Hello Camel">
<startEvent id="startevent1" name="Start"></startEvent>
<serviceTask id="serviceTask1" name="Camel" activiti:type="camel">
<extensionElements>
<activiti:field name="camelBehaviorClass" stringValue="org.activiti.camel.impl.CamelBehaviorBodyAsMapImpl" />
</extensionElements>
</serviceTask>
<userTask id="userTask1" name="Hello Task" activiti:assignee="kermit"></userTask>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow2" name="" sourceRef="serviceTask1" targetRef="userTask1"></sequenceFlow>
<sequenceFlow id="flow3" name="" sourceRef="userTask1" targetRef="endevent1"></sequenceFlow>
<sequenceFlow id="flow4" name="" sourceRef="startevent1" targetRef="serviceTask1"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_HelloCamel">
<bpmndi:BPMNPlane bpmnElement="HelloCamel" id="BPMNPlane_HelloCamel">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35" width="35" x="60" y="170"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="serviceTask1" id="BPMNShape_serviceTask1">
<omgdc:Bounds height="55" width="105" x="180" y="160"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="userTask1" id="BPMNShape_userTask1">
<omgdc:Bounds height="55" width="105" x="380" y="160"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35" width="35" x="580" y="170"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="285" y="187"></omgdi:waypoint>
<omgdi:waypoint x="380" y="187"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="485" y="187"></omgdi:waypoint>
<omgdi:waypoint x="580" y="187"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="95" y="187"></omgdi:waypoint>
<omgdi:waypoint x="180" y="187"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
\ No newline at end of file
......@@ -51,7 +51,7 @@
</setBody>
</route>
<route id="incomingRoute2">
<from uri="activiti:camelProcess:serviceTask2?copyVariablesToBody=true" />
<from uri="activiti:camelProcess:serviceTask2?copyVariablesToBodyAsMap=true" />
<to uri="mock:service2" />
</route>
<route id="startRoute">
......
......@@ -198,8 +198,25 @@ public class DefaultActivityBehaviorFactory extends AbstractBehaviorFactory impl
protected ActivityBehavior createCamelActivityBehavior(Task task, List<FieldExtension> fieldExtensions, BpmnModel bpmnModel) {
try {
Class< ? > theClass = Class.forName("org.activiti.camel.CamelBehavior");
Class< ? > theClass = null;
FieldExtension behaviorExtension = null;
for (FieldExtension fieldExtension : fieldExtensions) {
if ("camelBehaviorClass".equals(fieldExtension.getFieldName()) && StringUtils.isNotEmpty(fieldExtension.getStringValue())) {
theClass = Class.forName(fieldExtension.getStringValue());
behaviorExtension = fieldExtension;
break;
}
}
if (behaviorExtension != null) {
fieldExtensions.remove(behaviorExtension);
}
if (theClass == null) {
// Default Camel behavior class
theClass = Class.forName("org.activiti.camel.impl.CamelBehaviorDefaultImpl");
}
List<FieldDeclaration> fieldDeclarations = createFieldDeclarations(fieldExtensions);
return (ActivityBehavior) ClassDelegate.instantiateDelegate(theClass, fieldDeclarations);
......
......@@ -152,6 +152,10 @@ public class AdminCompletedInstancesPanel extends DetailPanel {
} else {
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
if (definition == null) {
// this process has a missing definition - skip
continue;
}
managementDefinition = new ManagementProcessDefinition();
managementDefinition.processDefinition = definition;
managementDefinition.runningInstances = new ArrayList<HistoricProcessInstance>();
......
......@@ -154,6 +154,10 @@ public class AdminRunningInstancesPanel extends DetailPanel {
} else {
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
if (definition == null) {
// this process has a missing definition - skip
continue;
}
managementDefinition = new ManagementProcessDefinition();
managementDefinition.processDefinition = definition;
managementDefinition.runningInstances = new ArrayList<HistoricProcessInstance>();
......
......@@ -4210,11 +4210,12 @@ public class AsyncCamelRoute extends RouteBuilder {
}</programlisting>
Note the from endpoint definition &quot;activiti:asyncCamelProcess:serviceTaskAsync1&quot; where activiti relates to the Activiti Camel component. asyncCamelProcess refers to the process definition
key of the process definition. And serviceTaskAsync1 relates to the identifier of the Camel task. The process variables can be copied to the body or the properties of the Camel payload.
In this example the variables are copied as message properties. copyVariablesToBody will copy the variables to the body of the Camel message.
In this example the variables are copied as message properties (the default). copyVariablesToBodyAsMap=true will copy the variables to the body of the Camel message in a Map instance.
copyCamelBodyToBody=true will copy the camelBody process variable to the body of the Camel message
In this example you can also see that a Camel message can be sent to a receive task of an Activiti process instance. In this example a bit of additional Camel logic is used to send the Camel message
to the receive task that's defined in the message header destination property. But eventually the message will be sent to the receive1 or receive2 receive tasks.
By default the message body of the Camel message is expected as a Map and all Map entries will be copied to the Activiti execution. When defining the copyVariablesToProperties=true option the message properties are
copied to the Activiti execution.
By default the message body of the Camel message is expected as a Map (all Map entries will be copied to the Activiti execution) or as a String that will be copied to the camelBody process variable.
When defining the copyVariablesToProperties=true option the message properties are copied to the Activiti execution.
</para>
<para>
......@@ -4230,6 +4231,19 @@ public class AsyncCamelRoute extends RouteBuilder {
&lt;extensionElements&gt;
&lt;activiti:field name="camelContext" stringValue="customCamelContext" /&gt;
&lt;/extensionElements&gt;
&lt;/serviceTask&gt;</programlisting>
</para>
<para>
You can also override the default Camel behavior class (org.activiti.camel.impl.CamelBehaviorDefaultImpl). This can be handy to customize the Camel logic or to change the default behavior of copying the process
variables to something else. The Activiti Camel module provide two additional Camel behavior classes, CamelBehaviorBodyAsMapImpl and CamelBehaviorCamelBodyImpl. CamelBehaviorBodyAsMapImpl copies the process variables
to a Map instance in the Camel message body by default (remember that you can override this on the endpoint using for example copyVariablesToProperties=true). CamelBehaviorCamelBodyImpl expects a camelBody process variable
and copies it to the Camel message body. The default Camel behavior class can be overriden by using the following field definition:
<programlisting>
&lt;serviceTask id="serviceTask1" activiti:type="camel"&gt;
&lt;extensionElements&gt;
&lt;activiti:field name="camelBehaviorClass" stringValue="org.activiti.camel.impl.CamelBehaviorCamelBodyImpl" /&gt;
&lt;/extensionElements&gt;
&lt;/serviceTask&gt;</programlisting>
</para>
</section>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册