提交 6ee939d2 编写于 作者: F falko.menge

ACT-374 Added Send Task for Web Services

上级 682a0dfd
......@@ -22,6 +22,7 @@ import org.activiti.engine.impl.pvm.delegate.ActivityExecution;
* Implementation of the BPMN 2.0 'ioSpecification'
*
* @author Esteban Robles Luna
* @author Falko Menge
*/
public class IOSpecification {
......@@ -79,6 +80,10 @@ public class IOSpecification {
}
public String getFirstDataOutputName() {
return this.dataOutputs.get(0).getName();
if (this.dataOutputs != null && !this.dataOutputs.isEmpty()) {
return this.dataOutputs.get(0).getName();
} else {
return null;
}
}
}
......@@ -22,6 +22,7 @@ import org.activiti.engine.impl.pvm.delegate.ActivityExecution;
* An activity behavior that allows calling Web services
*
* @author Esteban Robles Luna
* @author Falko Menge
*/
public class WebServiceActivityBehavior implements ActivityBehavior {
......@@ -72,8 +73,11 @@ public class WebServiceActivityBehavior implements ActivityBehavior {
execution.setVariable(CURRENT_MESSAGE, receivedMessage);
if (ioSpecification != null) {
ItemInstance outputItem = (ItemInstance) execution.getVariable(this.ioSpecification.getFirstDataOutputName());
outputItem.getStructureInstance().loadFrom(receivedMessage.getStructureInstance().toArray());
String firstDataOutputName = this.ioSpecification.getFirstDataOutputName();
if (firstDataOutputName != null) {
ItemInstance outputItem = (ItemInstance) execution.getVariable(firstDataOutputName);
outputItem.getStructureInstance().loadFrom(receivedMessage.getStructureInstance().toArray());
}
}
this.returnMessage(receivedMessage, execution);
......
......@@ -63,7 +63,6 @@ import org.activiti.engine.impl.bpmn.TaskActivity;
import org.activiti.engine.impl.bpmn.TransformationDataOutputAssociation;
import org.activiti.engine.impl.bpmn.UserTaskActivity;
import org.activiti.engine.impl.bpmn.WebServiceActivityBehavior;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.el.Expression;
import org.activiti.engine.impl.el.ExpressionManager;
import org.activiti.engine.impl.el.FixedValue;
......@@ -97,6 +96,7 @@ import org.activiti.engine.impl.variable.VariableDeclaration;
* @author Joram Barrez
* @author Christian Stettler
* @author Frederik Heremans
* @author Falko Menge
*/
public class BpmnParse extends Parse {
......@@ -650,6 +650,8 @@ public class BpmnParse extends Parse {
parseManualTask(activityElement, scopeElement);
} else if (activityElement.getTagName().equals("userTask")) {
parseUserTask(activityElement, scopeElement);
} else if (activityElement.getTagName().equals("sendTask")) {
parseSendTask(activityElement, scopeElement);
} else if (activityElement.getTagName().equals("receiveTask")) {
parseReceiveTask(activityElement, scopeElement);
} else if (activityElement.getTagName().equals("subProcess")) {
......@@ -821,7 +823,7 @@ public class BpmnParse extends Parse {
activity.setActivityBehavior(webServiceActivityBehavior);
}
} else {
addError("'class', 'delegateExpression', type', or 'expression' attribute is mandatory on serviceTask", serviceTaskElement);
addError("One of the attributes 'class', 'delegateExpression', 'type', 'operation', or 'expression' is mandatory on serviceTask.", serviceTaskElement);
}
parseExecutionListenersOnScope(serviceTaskElement, activity);
......@@ -831,6 +833,64 @@ public class BpmnParse extends Parse {
}
}
/**
* Parses a sendTask declaration.
*/
public void parseSendTask(Element sendTaskElement, ScopeImpl scope) {
ActivityImpl activity = parseAndCreateActivityOnScopeElement(sendTaskElement, scope);
// for e-mail
String type = null; //sendTaskElement.attributeNS(BpmnParser.ACTIVITI_BPMN_EXTENSIONS_NS, "type");
// for web service
String implementation = sendTaskElement.attribute("implementation");
String operationRef = this.resolveName(sendTaskElement.attribute("operationRef"));
// for e-mail
if (type != null) {
// if (type.equalsIgnoreCase("mail")) {
// parseEmailServiceTask(activity, sendTaskElement, parseFieldDeclarations(sendTaskElement));
// } else {
// addError("Invalid usage of type attribute: '" + type + "'", sendTaskElement);
// }
// for web service
} else if (implementation != null && operationRef != null && implementation.equalsIgnoreCase("##WebService")) {
if (!this.operations.containsKey(operationRef)) {
addError(operationRef + " does not exist" , sendTaskElement);
} else {
Operation operation = this.operations.get(operationRef);
WebServiceActivityBehavior webServiceActivityBehavior = new WebServiceActivityBehavior(operation);
Element ioSpecificationElement = sendTaskElement.element("ioSpecification");
if (ioSpecificationElement != null) {
IOSpecification ioSpecification = this.parseIOSpecification(ioSpecificationElement);
webServiceActivityBehavior.setIoSpecification(ioSpecification);
}
for (Element dataAssociationElement : sendTaskElement.elements("dataInputAssociation")) {
AbstractDataInputAssociation dataAssociation = this.parseDataInputAssociation(dataAssociationElement);
webServiceActivityBehavior.addDataInputAssociation(dataAssociation);
}
for (Element dataAssociationElement : sendTaskElement.elements("dataOutputAssociation")) {
AbstractDataOutputAssociation dataAssociation = this.parseDataOutputAssociation(dataAssociationElement);
webServiceActivityBehavior.addDataOutputAssociation(dataAssociation);
}
activity.setActivityBehavior(webServiceActivityBehavior);
}
} else {
addError("One of the attributes 'type' or 'operation' is mandatory on sendTask.", sendTaskElement);
}
parseExecutionListenersOnScope(sendTaskElement, activity);
for (BpmnParseListener parseListener: parseListeners) {
parseListener.parseSendTask(sendTaskElement, scope, activity);
}
}
private AbstractDataOutputAssociation parseDataOutputAssociation(Element dataAssociationElement) {
String targetRef = dataAssociationElement.element("targetRef").getText();
......
......@@ -23,6 +23,7 @@ import org.activiti.engine.impl.variable.VariableDeclaration;
/**
* @author Tom Baeyens
* @author Falko Menge
*/
public interface BpmnParseListener {
......@@ -41,5 +42,6 @@ public interface BpmnParseListener {
void parseCallActivity(Element callActivityElement, ScopeImpl scope, ActivityImpl activity);
void parseProperty(Element propertyElement, VariableDeclaration variableDeclaration, ActivityImpl activity);
void parseSequenceFlow(Element sequenceFlowElement, ScopeImpl scopeElement, TransitionImpl transition);
void parseSendTask(Element sendTaskElement, ScopeImpl scope, ActivityImpl activity);
}
......@@ -31,6 +31,7 @@ import org.activiti.engine.impl.variable.VariableDeclaration;
/**
* @author Tom Baeyens
* @author Joram Barrez
* @author Falko Menge
*/
public class HistoryParseListener implements BpmnParseListener {
......@@ -137,5 +138,9 @@ public class HistoryParseListener implements BpmnParseListener {
}
return configurationhistoryLevel;
}
public void parseSendTask(Element sendTaskElement, ScopeImpl scope, ActivityImpl activity) {
addActivityHandlers(sendTaskElement, activity);
}
}
/* 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.engine.test.bpmn.sendtask;
import java.util.HashMap;
import java.util.Map;
import org.activiti.engine.test.bpmn.servicetask.AbstractWebServiceTaskTest;
import org.activiti.test.mule.Counter;
import org.mule.component.DefaultJavaComponent;
/**
* @author Esteban Robles Luna
* @author Falko Menge
*/
public class WebServiceSimplisticTest extends AbstractWebServiceTaskTest {
protected boolean isValidating() {
return false;
}
public void testAsyncInvocationWithSimplisticDataFlow() throws Exception {
Counter counter = (Counter) ((DefaultJavaComponent) context.getRegistry().lookupService("counterService").getComponent())
.getObjectFactory().getInstance();
assertEquals(-1, counter.getCount());
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("NewCounterValueVariable", 23);
processEngine.getRuntimeService().startProcessInstanceByKey("asyncWebServiceInvocationWithSimplisticDataFlow", variables);
waitForJobExecutorToProcessAllJobs(10000L, 250L);
assertEquals(23, counter.getCount());
}
}
/* 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.engine.test.bpmn.sendtask;
import org.activiti.engine.test.bpmn.servicetask.AbstractWebServiceTaskTest;
import org.activiti.test.mule.Counter;
import org.mule.component.DefaultJavaComponent;
/**
* @author Esteban Robles Luna
* @author Falko Menge
*/
public class WebServiceTest extends AbstractWebServiceTaskTest {
public void testAsyncInvocationWithoutDataFlow() throws Exception {
Counter counter = (Counter) ((DefaultJavaComponent) context.getRegistry().lookupService("counterService").getComponent())
.getObjectFactory().getInstance();
assertEquals(-1, counter.getCount());
processEngine.getRuntimeService().startProcessInstanceByKey("asyncWebServiceInvocationWithoutDataFlow");
waitForJobExecutorToProcessAllJobs(10000L, 250L);
assertEquals(0, counter.getCount());
}
}
/* 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.engine.test.bpmn.sendtask;
import java.util.HashMap;
import java.util.Map;
import org.activiti.engine.impl.bpmn.FieldBaseStructureInstance;
import org.activiti.engine.impl.bpmn.ItemDefinition;
import org.activiti.engine.impl.bpmn.ItemInstance;
import org.activiti.engine.impl.cfg.RepositorySession;
import org.activiti.engine.impl.db.DbRepositorySessionFactory;
import org.activiti.engine.impl.repository.ProcessDefinitionEntity;
import org.activiti.engine.test.bpmn.servicetask.AbstractWebServiceTaskTest;
import org.activiti.test.mule.Counter;
import org.mule.component.DefaultJavaComponent;
/**
* @author Esteban Robles Luna
* @author Falko Menge
*/
public class WebServiceUELTest extends AbstractWebServiceTaskTest {
public void testAsyncInvocationWithDataFlowUEL() throws Exception {
Counter counter = (Counter) ((DefaultJavaComponent) context.getRegistry().lookupService("counterService").getComponent())
.getObjectFactory().getInstance();
assertEquals(-1, counter.getCount());
DbRepositorySessionFactory dbRepositorySessionFactory = (DbRepositorySessionFactory)
this.processEngineConfiguration.getSessionFactories().get(RepositorySession.class);
ProcessDefinitionEntity processDefinition = dbRepositorySessionFactory.getProcessDefinitionCache().get("asyncWebServiceInvocationWithDataFlowUEL:1");
ItemDefinition itemDefinition = processDefinition.getIoSpecification().getDataInputs().get(0).getDefinition();
ItemInstance itemInstance = itemDefinition.createInstance();
FieldBaseStructureInstance structureInstance = (FieldBaseStructureInstance) itemInstance.getStructureInstance();
structureInstance.setFieldValue("newCounterValue", 23);
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("dataInputOfProcess", itemInstance);
processEngine.getRuntimeService().startProcessInstanceByKey("asyncWebServiceInvocationWithDataFlowUEL", variables);
waitForJobExecutorToProcessAllJobs(10000L, 250L);
assertEquals(23, counter.getCount());
}
}
......@@ -13,12 +13,9 @@
package org.activiti.engine.test.bpmn.servicetask;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.engine.impl.repository.DeploymentBuilderImpl;
import org.activiti.engine.impl.repository.ResourceEntity;
import org.activiti.engine.impl.test.PluggableActivitiTestCase;
import org.activiti.engine.impl.test.TestHelper;
import org.activiti.engine.impl.util.ClassNameUtil;
......
<?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"
typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://java.sun.com/products/jsp/"
targetNamespace="org.activiti.engine.test.bpmn.servicetask"
xmlns:tns="org.activiti.engine.test.bpmn.servicetask"
xmlns:counter="http://webservice.activiti.org/">
<!--
XML Schema is used as type language for the model whereas the Java
Unified Expression Language serves as language for Expressions.
-->
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="http://localhost:63081/counter?wsdl"
namespace="http://webservice.activiti.org/" />
<process id="asyncWebServiceInvocationWithSimplisticDataFlow">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="webService" />
<sendTask id="webService"
name="Web service invocation"
implementation="##WebService"
operationRef="tns:setToOperation">
<!--
Warning: The following code abuses the syntax of Data Associations
for a radical shortcut.
-->
<dataInputAssociation>
<sourceRef>NewCounterValueVariable</sourceRef><!-- name of an Activiti variable -->
<targetRef>value</targetRef><!-- name of an element of the input message -->
</dataInputAssociation>
</sendTask>
<sequenceFlow id="flow2" sourceRef="webService" targetRef="waitState" />
<receiveTask id="waitState" />
<sequenceFlow id="flow3" sourceRef="waitState" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
<!-- Interface: implementationRef = QName of WSDL Port Type -->
<interface name="Counter Interface" implementationRef="counter:Counter">
<!-- Operation: implementationRef = QName of WSDL Operation -->
<operation id="setToOperation" name="setTo Operation" implementationRef="counter:setTo">
<inMessageRef>tns:setToRequestMessage</inMessageRef>
</operation>
</interface>
<message id="setToRequestMessage" itemRef="tns:setToRequestItem" />
<itemDefinition id="setToRequestItem" structureRef="counter:setTo" /><!-- QName of input element -->
</definitions>
\ No newline at end of file
<?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="org.activiti.engine.test.bpmn.servicetask"
xmlns:tns="org.activiti.engine.test.bpmn.servicetask"
xmlns:counter="http://webservice.activiti.org/">
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="http://localhost:63081/counter?wsdl"
namespace="http://webservice.activiti.org/" />
<process id="asyncWebServiceInvocationWithoutDataFlow">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="webService" />
<sendTask id="webService"
name="Web service invocation"
implementation="##WebService"
operationRef="tns:incOperation" />
<sequenceFlow id="flow2" sourceRef="webService" targetRef="waitState" />
<receiveTask id="waitState" />
<sequenceFlow id="flow3" sourceRef="waitState" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
<!-- Interface: implementationRef = QName of WSDL Port Type -->
<interface name="Counter Interface" implementationRef="counter:Counter"> <!-- NEEDED FOR THE PORT -->
<!-- Operation: implementationRef = QName of WSDL Operation -->
<operation id="incOperation" name="Increase Operation" implementationRef="counter:inc"> <!-- NEEDED FOR THE OPERATION NAME -->
<inMessageRef>tns:incRequestMessage</inMessageRef>
</operation>
</interface>
<message id="incRequestMessage" itemRef="tns:incRequestItem" />
<itemDefinition id="incRequestItem" structureRef="counter:inc" /><!-- QName of input element --> <!-- NEEDED FOR THE ARGUMENTS -->
</definitions>
\ No newline at end of file
<?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"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://java.sun.com/products/jsp/"
targetNamespace="org.activiti.engine.test.bpmn.servicetask"
xmlns:tns="org.activiti.engine.test.bpmn.servicetask"
xmlns:counter="http://webservice.activiti.org/">
<!--
XML Schema is used as type language for the model whereas the Java
Unified Expression Language serves as language for Expressions.
-->
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="http://localhost:63081/counter?wsdl"
namespace="http://webservice.activiti.org/" />
<process id="asyncWebServiceInvocationWithDataFlowUEL">
<!--
The Data Inputs and Outputs of a Process have to be explicitly
declared with their type to be valid BPMN 2.0
-->
<ioSpecification>
<dataInput id="dataInputOfProcess" itemSubjectRef="tns:setToRequestItem" />
<inputSet>
<dataInputRefs>dataInputOfProcess</dataInputRefs>
</inputSet>
<outputSet />
</ioSpecification>
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="webService" />
<sendTask id="webService"
name="Web service invocation"
implementation="##WebService"
operationRef="tns:setToOperation">
<!-- The BPMN 2.0 Meta Model requires an Input/Output Specification -->
<ioSpecification>
<dataInput itemSubjectRef="tns:setToRequestItem" id="dataInputOfServiceTask" />
<inputSet>
<dataInputRefs>dataInputOfServiceTask</dataInputRefs>
</inputSet>
<outputSet />
</ioSpecification>
<dataInputAssociation>
<sourceRef>dataInputOfProcess</sourceRef>
<targetRef>dataInputOfServiceTask</targetRef>
<assignment>
<from>${dataInputOfProcess.newCounterValue}</from>
<to>${dataInputOfServiceTask.value}</to>
</assignment>
</dataInputAssociation>
</sendTask>
<sequenceFlow id="flow2" sourceRef="webService" targetRef="waitState" />
<receiveTask id="waitState" />
<sequenceFlow id="flow3" sourceRef="waitState" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
<!-- Interface: implementationRef = QName of WSDL Port Type -->
<interface name="Counter Interface" implementationRef="counter:Counter">
<!-- Operation: implementationRef = QName of WSDL Operation -->
<operation id="setToOperation" name="setTo Operation" implementationRef="counter:setTo">
<inMessageRef>tns:setToRequestMessage</inMessageRef>
</operation>
</interface>
<message id="setToRequestMessage" itemRef="tns:setToRequestItem" />
<itemDefinition id="setToRequestItem" structureRef="counter:setTo" /><!-- QName of input element -->
</definitions>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册