/**
* Copyright 2007-2011 非也
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation。
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses. *
*/
package org.fireflow.service.java;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.namespace.QName;
import junit.framework.Assert;
import org.dom4j.io.DOMWriter;
import org.dom4j.io.SAXReader;
import org.fireflow.client.WorkflowQuery;
import org.fireflow.client.WorkflowSession;
import org.fireflow.client.WorkflowSessionFactory;
import org.fireflow.client.impl.WorkflowSessionLocalImpl;
import org.fireflow.client.query.Restrictions;
import org.fireflow.engine.context.RuntimeContext;
import org.fireflow.engine.entity.runtime.ActivityInstance;
import org.fireflow.engine.entity.runtime.ProcessInstance;
import org.fireflow.engine.entity.runtime.Variable;
import org.fireflow.engine.entity.runtime.VariableProperty;
import org.fireflow.engine.exception.InvalidOperationException;
import org.fireflow.engine.exception.ServiceInvocationException;
import org.fireflow.engine.invocation.ServiceInvoker;
import org.fireflow.engine.modules.ousystem.impl.FireWorkflowSystem;
import org.fireflow.model.binding.Assignment;
import org.fireflow.model.binding.impl.AssignmentImpl;
import org.fireflow.model.binding.impl.InputAssignmentImpl;
import org.fireflow.model.binding.impl.OutputAssignmentImpl;
import org.fireflow.model.binding.impl.ServiceBindingImpl;
import org.fireflow.model.data.Input;
import org.fireflow.model.data.Output;
import org.fireflow.model.data.impl.ExpressionImpl;
import org.fireflow.model.servicedef.InterfaceDef;
import org.fireflow.model.servicedef.OperationDef;
import org.fireflow.model.servicedef.ServiceDef;
import org.fireflow.model.servicedef.impl.JavaInterfaceDef;
import org.fireflow.service.AbsTestContext;
import org.fireflow.service.java.mock.Operand;
import org.fireflow.service.java.mock.Result;
import org.fireflow.service.mock.ActivityMock;
import org.firesoa.common.schema.NameSpaces;
import org.junit.Test;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
/**
*
* @author 非也 www.firesoa.com
*
*
*/
@SuppressWarnings("unused")
//hibernate
@ContextConfiguration(locations = { "classpath:/applicationContext.xml",
"classpath:/org/fireflow/service/java/JavaInvokerTest-context.xml"
})
public class JavaInvokerTest extends AbsTestContext {
WorkflowSession session = null;
ProcessInstance procInst = null;
ActivityInstance actInst = null;
/**
* Test method for {@link org.firesoa.service.modules.java.JavaInvoker#invoke(org.firesoa.common.context.RuntimeContext, org.firesoa.ServiceDef.def.Service, java.lang.String, java.util.List, Object)}.
*/
@Test
public void testInvoke() {
final ServiceDef service = this.buildService1();
//检验interface解析是否正确
InterfaceDef _interface = service.getInterface();
final List<OperationDef> operations = _interface.getOperations();
Assert.assertNotNull(operations);
Assert.assertEquals(1, operations.size());
Assert.assertEquals("calculate",operations.get(0).getOperationName());
List<Input> inputs = operations.get(0).getInputs();
Assert.assertNotNull(inputs);
Assert.assertEquals(3, inputs.size());
Assert.assertEquals(new QName(NameSpaces.JAVA.getUri(),"org.fireflow.service.java.mock.MathsAction"),inputs.get(0).getDataType());
Assert.assertEquals(new QName(NameSpaces.JAVA.getUri(),"org.fireflow.service.java.mock.Operand"),inputs.get(1).getDataType());
Assert.assertEquals(new QName(NameSpaces.JAVA.getUri(),"int"),inputs.get(2).getDataType());
List<Output> outputs = operations.get(0).getOutputs();
Assert.assertNotNull(outputs);
Assert.assertEquals(1, outputs.size());
Assert.assertEquals(new QName(NameSpaces.JAVA.getUri(),"org.fireflow.service.java.mock.Result"), outputs.get(0).getDataType());
//
TransactionTemplate transactionTemplate = (TransactionTemplate)this.applicationContext.getBean("transactionTemplate");
transactionTemplate.execute(new TransactionCallback(){
public Object doInTransaction(TransactionStatus arg0) {
//测试invoker
String invokerClassName = service.getInvokerClassName();
Class clz;
try {
clz = Class.forName(invokerClassName);
ServiceInvoker invoker = (ServiceInvoker)clz.newInstance();
RuntimeContext runtimeContext = (RuntimeContext)applicationContext.getBean("runtimeContext");
session = WorkflowSessionFactory.createWorkflowSession(runtimeContext, FireWorkflowSystem.getInstance());
//构造processInstance
procInst = createProcessInstance(session, runtimeContext);
((WorkflowSessionLocalImpl)session).setCurrentProcessInstance(procInst);
procInst.setVariableValue(session, "operand", new Operand(2,3));
procInst.setVariableValue(session, "action", org.fireflow.service.java.mock.MathsAction.ADD);
//构造activityInstance
actInst = createActivityInstance(runtimeContext, procInst);
((WorkflowSessionLocalImpl)session).setCurrentActivityInstance(actInst);
//构造service binding
ServiceBindingImpl serviceBinding = new ServiceBindingImpl();
serviceBinding.setServiceId(service.getId());
serviceBinding.setOperationName("calculate");
//构造输入映射
List<Assignment> inputAssignments = new ArrayList<Assignment>();
//arg0
AssignmentImpl inputAssignment = new AssignmentImpl();
String jsBody = "importClass(org.fireflow.service.java.mock.MathsAction);var action=org.fireflow.service.java.mock.MathsAction.MULTIPLY; action;";
// String jsBody = "processVars.get(\"action\");";
ExpressionImpl exp = new ExpressionImpl();
exp.setBody(jsBody);
exp.setLanguage("JavaScript");
exp.setName("from1");
inputAssignment.setFrom(exp);//
ExpressionImpl toExpression = new ExpressionImpl();
toExpression.setLanguage("xpath");
toExpression.setBody("/inputs/arg0");
toExpression.setName("arg0");
toExpression.setDisplayName("arg0");
toExpression.setDataType(operations.get(0).getInputs().get(0).getDataType());
inputAssignment.setTo(toExpression);
inputAssignments.add(inputAssignment);
//arg1
inputAssignment = new InputAssignmentImpl();
jsBody = "processVars.get(\"operand\");";
exp = new ExpressionImpl();
exp.setBody(jsBody);
exp.setName("from1");
exp.setLanguage("JavaScript");
inputAssignment.setFrom(exp);//
toExpression = new ExpressionImpl();
toExpression.setLanguage("xpath");
toExpression.setBody("/inputs/arg1");
toExpression.setName("arg1");
toExpression.setDisplayName("arg1");
toExpression.setDataType(operations.get(0).getInputs().get(1).getDataType());
inputAssignment.setTo(toExpression);
inputAssignments.add(inputAssignment);
//arg2
inputAssignment = new InputAssignmentImpl();
jsBody = "2";
exp = new ExpressionImpl();
exp.setBody(jsBody);
exp.setName("from2");
exp.setLanguage("JavaScript");
inputAssignment.setFrom(exp);//
toExpression = new ExpressionImpl();
toExpression.setLanguage("xpath");
toExpression.setBody("/inputs/arg2");
toExpression.setName("arg2");
toExpression.setDataType(operations.get(0).getInputs().get(2).getDataType());
inputAssignment.setTo(toExpression);
inputAssignments.add(inputAssignment);
serviceBinding.setInputAssignments(inputAssignments);
//构造输出映射
List<Assignment> outputAssignments = new ArrayList<Assignment>();
// 1、 输出到实例级别的流程变量
AssignmentImpl outputAssignment = new AssignmentImpl();
ExpressionImpl expression = new ExpressionImpl();
expression.setLanguage("JavaScript");
expression.setBody("outputs.get(\""+operations.get(0).getOutputs().get(0).getName()+"\");");
expression.setName(JavaInterfaceDef.OUTPUT_NAME_PREFIX+"calculate");
outputAssignment.setFrom(expression);
toExpression = new ExpressionImpl();
toExpression.setLanguage("xpath");
toExpression.setBody("/processVars/result");
toExpression.setName("result");
toExpression.setDataType(new QName(NameSpaces.JAVA.getUri(),"org.fireflow.service.java.mock.Result",NameSpaces.JAVA.getPrefix()));
outputAssignment.setTo(toExpression);
outputAssignments.add(outputAssignment);
// 2、输出到活动级别的流程变量
outputAssignment = new OutputAssignmentImpl();
expression = new ExpressionImpl();
expression.setLanguage("JavaScript");
expression.setBody("outputs.get(\""+operations.get(0).getOutputs().get(0).getName()+"\");");
expression.setName(JavaInterfaceDef.OUTPUT_NAME_PREFIX+"calculate");
outputAssignment.setFrom(expression);
toExpression = new ExpressionImpl();
toExpression.setLanguage("xpath");
toExpression.setBody("/activityVars/result1");
toExpression.setName("result1");
toExpression.setDataType(new QName(NameSpaces.JAVA.getUri(),"org.fireflow.service.java.mock.Result",NameSpaces.JAVA.getPrefix()));
outputAssignment.setTo(toExpression);
outputAssignments.add(outputAssignment);
// 3、输出到session attribute
outputAssignment = new OutputAssignmentImpl();
expression = new ExpressionImpl();
expression.setLanguage("JavaScript");
expression.setBody("outputs.get(\""+operations.get(0).getOutputs().get(0).getName()+"\");");
expression.setName(JavaInterfaceDef.OUTPUT_NAME_PREFIX+"calculate");
outputAssignment.setFrom(expression);
toExpression = new ExpressionImpl();
toExpression.setLanguage("xpath");
toExpression.setBody("/sessionAttributes/result2");
toExpression.setName("result2");
toExpression.setDataType(new QName(NameSpaces.JAVA.getUri(),"org.fireflow.service.java.mock.Result",NameSpaces.JAVA.getPrefix()));
outputAssignment.setTo(toExpression);
outputAssignments.add(outputAssignment);
serviceBinding.setOutputAssignments(outputAssignments);
//执行java 调用
boolean b = invoker.invoke(session, actInst, serviceBinding, null, new ActivityMock(service));
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Assert.fail(e.getMessage());
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Assert.fail(e.getMessage());
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Assert.fail(e.getMessage());
} catch (InvalidOperationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceInvocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
});
//验证
// 1、验证processInstance中是否有result
Object result = procInst.getVariableValue(session, "result");
Assert.assertNotNull(result);
Assert.assertTrue(result instanceof Result);
Assert.assertEquals(6, ((Result)result).getResult());
// 2、验证 activityInstance中是否有 result
result = actInst.getVariableValue(session, "result1");
Assert.assertNotNull(result);
Assert.assertTrue(result instanceof Result);
Assert.assertEquals(6, ((Result)result).getResult());
// 3、验证session中是否有 result
result = ((WorkflowSessionLocalImpl)session).getAttribute("result2");
Assert.assertNotNull(result);
Assert.assertTrue(result instanceof Result);
Assert.assertEquals(6, ((Result)result).getResult());
//顺便测试一下存取org.w3c.dom.Document和org.dom4j.Document;
transactionTemplate.execute(new TransactionCallback(){
public Object doInTransaction(TransactionStatus arg0) {
try{
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Person id=\"123456\"><name>张三</name></Person>";
ByteArrayInputStream in = new ByteArrayInputStream(xml.getBytes("UTF-8"));
SAXReader reader = new SAXReader();
org.dom4j.Document dom4jDoc = reader.read(in);
procInst.setVariableValue(session, "dom4jDoc", dom4jDoc);
WorkflowQuery<Variable> variableQuery = session.createWorkflowQuery(Variable.class);
Variable v = variableQuery.add(Restrictions.eq(VariableProperty.NAME, "dom4jDoc"))
.add(Restrictions.eq(VariableProperty.SCOPE_ID, procInst.getId()))
.unique();
Assert.assertNotNull(v);
Assert.assertTrue(v.getPayload() instanceof org.dom4j.Document);
Assert.assertEquals(v.getHeaders().get(Variable.HEADER_KEY_CLASS_NAME), "org.dom4j.Document");
DOMWriter domWriter = new DOMWriter();
org.w3c.dom.Document w3cDom = domWriter.write(dom4jDoc);
procInst.setVariableValue(session, "w3cDom", w3cDom);
variableQuery.reset();
v = variableQuery.add(Restrictions.eq(VariableProperty.NAME, "w3cDom"))
.add(Restrictions.eq(VariableProperty.SCOPE_ID, procInst.getId()))
.unique();
Assert.assertNotNull(v);
Assert.assertTrue(v.getPayload() instanceof org.w3c.dom.Document);
Assert.assertEquals(v.getHeaders().get(Variable.HEADER_KEY_CLASS_NAME), "org.w3c.dom.Document");
}catch(Exception e){
e.printStackTrace();
}
return null;
}
});
}
@Test
public void testInvoke2() {
final ServiceDef service = this.buildService2();
//检验interface解析是否正确
InterfaceDef _interface = service.getInterface();
final List<OperationDef> operations = _interface.getOperations();
Assert.assertNotNull(operations);
Assert.assertEquals(1, operations.size());
Assert.assertEquals("calculate",operations.get(0).getOperationName());
List<Input> inputs = operations.get(0).getInputs();
Assert.assertNotNull(inputs);
Assert.assertEquals(3, inputs.size());
Assert.assertEquals(new QName(NameSpaces.JAVA.getUri(),"org.fireflow.service.java.mock.MathsAction"),inputs.get(0).getDataType());
Assert.assertEquals(new QName(NameSpaces.JAVA.getUri(),"org.fireflow.service.java.mock.Operand"),inputs.get(1).getDataType());
Assert.assertEquals(new QName(NameSpaces.JAVA.getUri(),"int"),inputs.get(2).getDataType());
List<Output> outputs = operations.get(0).getOutputs();
Assert.assertNotNull(outputs);
Assert.assertEquals(1, outputs.size());
Assert.assertEquals(new QName(NameSpaces.JAVA.getUri(),"org.fireflow.service.java.mock.Result"), outputs.get(0).getDataType());
//
TransactionTemplate transactionTemplate = (TransactionTemplate)this.applicationContext.getBean("transactionTemplate");
transactionTemplate.execute(new TransactionCallback(){
public Object doInTransaction(TransactionStatus arg0) {
//测试invoker
String invokerClassName = service.getInvokerClassName();
Class clz;
try {
clz = Class.forName(invokerClassName);
ServiceInvoker invoker = (ServiceInvoker)clz.newInstance();
RuntimeContext runtimeContext = (RuntimeContext)applicationContext.getBean("runtimeContext");
session = WorkflowSessionFactory.createWorkflowSession(runtimeContext, FireWorkflowSystem.getInstance());
//构造processInstance
procInst = createProcessInstance(session, runtimeContext);
((WorkflowSessionLocalImpl)session).setCurrentProcessInstance(procInst);
procInst.setVariableValue(session, "operand", new Operand(2,3));
procInst.setVariableValue(session, "action", org.fireflow.service.java.mock.MathsAction.ADD);
//构造activityInstance
actInst = createActivityInstance(runtimeContext, procInst);
((WorkflowSessionLocalImpl)session).setCurrentActivityInstance(actInst);
//构造service binding
ServiceBindingImpl serviceBinding = new ServiceBindingImpl();
// serviceBinding.setService(service);
serviceBinding.setServiceId(service.getId());
serviceBinding.setOperationName("calculate");
// serviceBinding.setOperation(operations.get(0));
//构造输入映射
List<Assignment> inputAssignments = new ArrayList<Assignment>();
//arg0
InputAssignmentImpl inputAssignment = new InputAssignmentImpl();
String jsBody = "processVars.get(\"action\");";
ExpressionImpl exp = new ExpressionImpl();
exp.setBody(jsBody);
exp.setLanguage("JavaScript");
exp.setName("from1");
inputAssignment.setFrom(exp);//
ExpressionImpl toExpression = new ExpressionImpl();
toExpression.setLanguage("xpath");
toExpression.setBody("/inputs/arg0");
toExpression.setName("arg0");
toExpression.setDataType(operations.get(0).getInputs().get(0).getDataType());
inputAssignment.setTo(toExpression);
inputAssignments.add(inputAssignment);
//arg1
inputAssignment = new InputAssignmentImpl();
jsBody = "processVars.get(\"operand\");";
exp = new ExpressionImpl();
exp.setBody(jsBody);
exp.setName("from1");
exp.setLanguage("JavaScript");
inputAssignment.setFrom(exp);//
toExpression = new ExpressionImpl();
toExpression.setLanguage("xpath");
toExpression.setBody("/inputs/arg1");
toExpression.setName("arg1");
toExpression.setDataType(operations.get(0).getInputs().get(1).getDataType());
inputAssignment.setTo(toExpression);
inputAssignments.add(inputAssignment);
//arg2
inputAssignment = new InputAssignmentImpl();
jsBody = "2";
exp = new ExpressionImpl();
exp.setBody(jsBody);
exp.setName("from2");
exp.setLanguage("JavaScript");
inputAssignment.setFrom(exp);//
toExpression = new ExpressionImpl();
toExpression.setLanguage("xpath");
toExpression.setBody("/inputs/arg2");
toExpression.setName("arg2");
toExpression.setDataType(operations.get(0).getInputs().get(2).getDataType());
inputAssignment.setTo(toExpression);
inputAssignments.add(inputAssignment);
serviceBinding.setInputAssignments(inputAssignments);
//构造输出映射
List<Assignment> outputAssignments = new ArrayList<Assignment>();
// 1、 输出到实例级别的流程变量
OutputAssignmentImpl outputAssignment = new OutputAssignmentImpl();
ExpressionImpl expression = new ExpressionImpl();
expression.setLanguage("JavaScript");
expression.setBody("outputs.get(\""+operations.get(0).getOutputs().get(0).getName()+"\");");
expression.setName(JavaInterfaceDef.OUTPUT_NAME_PREFIX+"calculate");
outputAssignment.setFrom(expression);
toExpression = new ExpressionImpl();
toExpression.setLanguage("xpath");
toExpression.setBody("/processVars/result4");
toExpression.setName("result4");
toExpression.setDataType(new QName(NameSpaces.JAVA.getUri(),"org.fireflow.service.java.mock.Result",NameSpaces.JAVA.getPrefix()));
outputAssignment.setTo(toExpression);
outputAssignments.add(outputAssignment);
// 2、输出到活动级别的流程变量
outputAssignment = new OutputAssignmentImpl();
expression = new ExpressionImpl();
expression.setLanguage("JavaScript");
expression.setBody("outputs.get(\""+operations.get(0).getOutputs().get(0).getName()+"\");");
expression.setName(JavaInterfaceDef.OUTPUT_NAME_PREFIX+"calculate");
outputAssignment.setFrom(expression);
toExpression = new ExpressionImpl();
toExpression.setLanguage("xpath");
toExpression.setBody("/activityVars/result5");
toExpression.setName("result5");
toExpression.setDataType(new QName(NameSpaces.JAVA.getUri(),"org.fireflow.service.java.mock.Result",NameSpaces.JAVA.getPrefix()));
outputAssignment.setTo(toExpression);
outputAssignments.add(outputAssignment);
// 3、输出到session attribute
outputAssignment = new OutputAssignmentImpl();
expression = new ExpressionImpl();
expression.setLanguage("JavaScript");
expression.setBody("outputs.get(\""+operations.get(0).getOutputs().get(0).getName()+"\");");
expression.setName(JavaInterfaceDef.OUTPUT_NAME_PREFIX+"calculate");
outputAssignment.setFrom(expression);
toExpression = new ExpressionImpl();
toExpression.setLanguage("xpath");
toExpression.setBody("/sessionAttributes/result6");
toExpression.setName("result6");
toExpression.setDataType(new QName(NameSpaces.JAVA.getUri(),"org.fireflow.service.java.mock.Result",NameSpaces.JAVA.getPrefix()));
outputAssignment.setTo(toExpression);
outputAssignments.add(outputAssignment);
serviceBinding.setOutputAssignments(outputAssignments);
//执行java 调用
boolean b = invoker.invoke(session, actInst, serviceBinding, null, new ActivityMock(service));
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Assert.fail(e.getMessage());
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Assert.fail(e.getMessage());
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Assert.fail(e.getMessage());
} catch (InvalidOperationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceInvocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
});
//验证
// 1、验证processInstance中是否有result
Object result = procInst.getVariableValue(session, "result4");
Assert.assertNotNull(result);
Assert.assertTrue(result instanceof Result);
Assert.assertEquals(5, ((Result)result).getResult());
// 2、验证 activityInstance中是否有 result
result = actInst.getVariableValue(session, "result5");
Assert.assertNotNull(result);
Assert.assertTrue(result instanceof Result);
Assert.assertEquals(5, ((Result)result).getResult());
// 3、验证session中是否有 result
result = ((WorkflowSessionLocalImpl)session).getAttribute("result6");
Assert.assertNotNull(result);
Assert.assertTrue(result instanceof Result);
Assert.assertEquals(5, ((Result)result).getResult());
}
public ServiceDef buildService1(){
JavaService svc = new JavaService();
svc.setName("java_service_1");
svc.setDisplayName("测试Calculator");
svc.setDescription("This is a java service");
svc.setBizCategory("test\\modules\\java");
svc.setJavaClassName("org.fireflow.service.java.mock.CalculatorImpl");
JavaInterfaceDef javaInterface = new JavaInterfaceDef();
javaInterface.setInterfaceClassName("org.fireflow.service.java.mock.Calculator");
svc.setInterface(javaInterface);
svc.getExtendedAttributes().put("key1", "value1");
svc.getExtendedAttributes().put("key2", "value2");
return svc;
}
public ServiceDef buildService2(){
JavaService svc = new JavaService();
svc.setName("java_service_2");
svc.setDisplayName("测试Calculator2");
svc.setDescription("This is a java service");
svc.setBizCategory("test\\modules\\java");
svc.setJavaBeanName("calculator");
svc.setInvokerBeanName("javaServiceInvoker");
JavaInterfaceDef javaInterface = new JavaInterfaceDef();
javaInterface.setInterfaceClassName("org.fireflow.service.java.mock.Calculator");
svc.setInterface(javaInterface);
svc.getExtendedAttributes().put("key1", "value1");
svc.getExtendedAttributes().put("key2", "value2");
return svc;
}
}