提交 a4c43a7f 编写于 作者: A aschrijver

Added feature that allows a Camel header to be used for setting the

Initiator on the workflow instance.
上级 a349dcfa
......@@ -14,6 +14,7 @@ package org.activiti.camel;
import java.util.Map;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
......@@ -25,10 +26,12 @@ import org.apache.camel.impl.DefaultComponent;
* 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
* @author Ryan Johnston (@rjfsu), Tijs Rademakers, Arnold Schrijver
*/
public class ActivitiComponent extends DefaultComponent {
private IdentityService identityService;
private RuntimeService runtimeService;
private boolean copyVariablesToProperties;
......@@ -42,6 +45,7 @@ public class ActivitiComponent extends DefaultComponent {
@Override
public void setCamelContext(CamelContext context) {
super.setCamelContext(context);
identityService = getByType(context, IdentityService.class);
runtimeService = getByType(context, RuntimeService.class);
}
......@@ -57,6 +61,7 @@ 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.setIdentityService(identityService);
ae.setCopyVariablesToProperties(this.copyVariablesToProperties);
ae.setCopyVariablesToBodyAsMap(this.copyVariablesToBodyAsMap);
ae.setCopyCamelBodyToBody(this.copyCamelBodyToBody);
......
......@@ -13,6 +13,7 @@
package org.activiti.camel;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.apache.camel.CamelContext;
import org.apache.camel.Consumer;
......@@ -20,6 +21,7 @@ import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.impl.DefaultEndpoint;
import org.springframework.util.StringUtils;
/**
* This class has been modified to be consistent with the changes to CamelBehavior and its implementations. The set of changes
......@@ -27,10 +29,11 @@ import org.apache.camel.impl.DefaultEndpoint;
* 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
* @author Ryan Johnston (@rjfsu), Tijs Rademakers, Arnold Schrijver
*/
public class ActivitiEndpoint extends DefaultEndpoint {
private IdentityService identityService;
private RuntimeService runtimeService;
......@@ -48,6 +51,8 @@ public class ActivitiEndpoint extends DefaultEndpoint {
private boolean copyCamelBodyToBodyAsString;
private String processInitiatorHeaderName;
private long timeout = 5000;
private int timeResolution = 100;
......@@ -59,9 +64,13 @@ public class ActivitiEndpoint extends DefaultEndpoint {
this.runtimeService = runtimeService;
}
public void setIdentityService(IdentityService identityService) {
this.identityService = identityService;
}
void addConsumer(ActivitiConsumer consumer) {
if (activitiConsumer != null) {
throw new RuntimeException("Activit consumer already defined for " + getEndpointUri() + "!");
throw new RuntimeException("Activiti consumer already defined for " + getEndpointUri() + "!");
}
activitiConsumer = consumer;
}
......@@ -78,7 +87,11 @@ public class ActivitiEndpoint extends DefaultEndpoint {
}
public Producer createProducer() throws Exception {
return new ActivitiProducer(this, runtimeService, getTimeout(), getTimeResolution());
ActivitiProducer producer = new ActivitiProducer(this, runtimeService, getTimeout(), getTimeResolution());
if (isSetProcessInitiator()) {
producer.setIdentityService(identityService);
}
return producer;
}
public Consumer createConsumer(Processor processor) throws Exception {
......@@ -137,6 +150,18 @@ public class ActivitiEndpoint extends DefaultEndpoint {
this.copyCamelBodyToBodyAsString = copyCamelBodyToBodyAsString;
}
public boolean isSetProcessInitiator() {
return StringUtils.hasText(getProcessInitiatorHeaderName());
}
public String getProcessInitiatorHeaderName() {
return processInitiatorHeaderName;
}
public void setProcessInitiatorHeaderName(String processInitiatorHeaderName) {
this.processInitiatorHeaderName = processInitiatorHeaderName;
}
@Override
public boolean isLenientProperties() {
return true;
......
......@@ -15,8 +15,10 @@ package org.activiti.camel;
/**
* @author Saeid Mirzaei
* @author Maciej Próchniak
* @author Arnold Schrijver
*/
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
......@@ -25,6 +27,8 @@ import org.apache.camel.impl.DefaultProducer;
public class ActivitiProducer extends DefaultProducer {
private IdentityService identityService;
private RuntimeService runtimeService;
public static final String PROCESS_KEY_PROPERTY = "PROCESS_KEY_PROPERTY";
......@@ -51,6 +55,10 @@ public class ActivitiProducer extends DefaultProducer {
this.timeResolution = timeResolution;
}
public void setIdentityService(IdentityService identityService) {
this.identityService = identityService;
}
public void process(Exchange exchange) throws Exception {
if (shouldStartProcess()) {
ProcessInstance pi = startProcess(exchange);
......@@ -112,14 +120,31 @@ public class ActivitiProducer extends DefaultProducer {
private ProcessInstance startProcess(Exchange exchange) {
ActivitiEndpoint endpoint = getActivitiEndpoint();
String key = exchange.getProperty(PROCESS_KEY_PROPERTY, String.class);
if (key == null) {
return runtimeService.startProcessInstanceByKey(processKey, ExchangeUtils.prepareVariables(exchange, getActivitiEndpoint()));
} else {
return runtimeService.startProcessInstanceByKey(processKey, key, ExchangeUtils.prepareVariables(exchange, getActivitiEndpoint()));
try {
if (endpoint.isSetProcessInitiator()) {
setProcessInitiator(ExchangeUtils.prepareInitiator(exchange, endpoint));
}
if (key == null) {
return runtimeService.startProcessInstanceByKey(processKey, ExchangeUtils.prepareVariables(exchange, endpoint));
} else {
return runtimeService.startProcessInstanceByKey(processKey, key, ExchangeUtils.prepareVariables(exchange, endpoint));
}
} finally {
if (endpoint.isSetProcessInitiator()) {
setProcessInitiator(null);
}
}
}
private void setProcessInitiator(String processInitiator) {
if (identityService == null) {
throw new RuntimeException("IdentityService is missing and must be provided to set process initiator.");
}
identityService.setAuthenticatedUserId(processInitiator);
}
protected ActivitiEndpoint getActivitiEndpoint() {
return (ActivitiEndpoint) getEndpoint();
......
......@@ -15,12 +15,15 @@ package org.activiti.camel;
import java.util.HashMap;
import java.util.Map;
import org.activiti.engine.ActivitiException;
import org.apache.camel.Exchange;
import org.apache.camel.TypeConversionException;
import org.springframework.util.StringUtils;
/**
* This class contains one method - prepareVariables - that is used to copy variables from Camel into Activiti.
*
* @author Ryan Johnston (@rjfsu), Tijs Rademakers
* @author Ryan Johnston (@rjfsu), Tijs Rademakers, Arnold Schrijver
*/
public class ExchangeUtils {
......@@ -83,7 +86,12 @@ public class ExchangeUtils {
}
if(activitiEndpoint.isCopyVariablesFromHeader()) {
boolean isSetProcessInitiator = activitiEndpoint.isSetProcessInitiator();
for(Map.Entry<String, Object> header : exchange.getIn().getHeaders().entrySet()) {
// Don't pass the process initiator header as a variable.
if (isSetProcessInitiator && activitiEndpoint.getProcessInitiatorHeaderName().equals(header.getKey())) {
continue;
}
camelVarMap.put(header.getKey(), header.getValue());
}
}
......@@ -91,4 +99,32 @@ public class ExchangeUtils {
return camelVarMap;
}
/**
* Gets the value of the Camel header that contains the userId to be set as the process initiator.
* Returns null if no header name was specified on the Camel route.
*
* @param exchange The Camel Exchange object
* @param activitiEndpoint The ActivitiEndpoint implementation
* @return The userId of the user to be set as the process initiator
*/
public static String prepareInitiator(Exchange exchange, ActivitiEndpoint activitiEndpoint) {
String initiator = null;
if (activitiEndpoint.isSetProcessInitiator()) {
try {
initiator = exchange.getIn().getHeader(activitiEndpoint.getProcessInitiatorHeaderName(), String.class);
}
catch (TypeConversionException e) {
throw new ActivitiException("Initiator header '" +
activitiEndpoint.getProcessInitiatorHeaderName() + "': Value must be of type String.", e);
}
if (!StringUtils.hasText(initiator)) {
throw new RuntimeException("Initiator header '" +
activitiEndpoint.getProcessInitiatorHeaderName() + "': Value must be provided");
}
}
return initiator;
}
}
/* 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.examples.initiatorCamelCall;
import org.apache.camel.builder.RouteBuilder;
public class InitiatorCamelCallRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
from("direct:startWithInitiatorHeader")
.setHeader("CamelProcessInitiatorHeader", constant("kermit"))
.to("activiti:InitiatorCamelCallProcess?processInitiatorHeaderName=CamelProcessInitiatorHeader");
}
}
/* 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.examples.initiatorCamelCall;
import org.activiti.engine.test.Deployment;
import org.activiti.spring.impl.test.SpringActivitiTestCase;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration("classpath:camel-activiti-context.xml")
public class InitiatorCamelCallTest extends SpringActivitiTestCase {
@Deployment
public void testInitiatorCamelCall() throws Exception {
CamelContext ctx = applicationContext.getBean(CamelContext.class);
ProducerTemplate tpl = ctx.createProducerTemplate();
String body = "body text";
String instanceId = (String) tpl.requestBody("direct:startWithInitiatorHeader", body);
String initiator = (String) runtimeService.getVariable(instanceId, "initiator");
assertEquals("kermit", initiator);
Object camelInitiatorHeader = runtimeService.getVariable(instanceId, "CamelProcessInitiatorHeader");
assertNull(camelInitiatorHeader);
}
}
......@@ -34,6 +34,8 @@
<property name="processEngineConfiguration" ref="processEngineConfiguration"/>
</bean>
<bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService"/>
<bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring">
......
<?xml version="1.0" encoding="UTF-8"?>
<definitions id="definitions"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.omg.org/spec/BPMN/20100524/MODEL http://www.omg.org/spec/BPMN/2.0/20100501/BPMN20.xsd">
<process id="InitiatorCamelCallProcess">
<startEvent id="start" activiti:initiator="initiator"/>
<sequenceFlow id="flow1" sourceRef="start" targetRef="simpleTask"/>
<userTask id="simpleTask" name="Simple Task" activiti:assignee="kermit"/>
<sequenceFlow id="flow2" sourceRef="simpleTask" targetRef="end"/>
<endEvent id="end"/>
</process>
</definitions>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册