创建一个事务,jbpm都是在一个事务中完成的
JbpmContext jbpmContext =
JbpmConfiguration.getInstance().createJbpmContext();
----中间写点东西
jbpmContext.close();
我们其实可以在web.xml里面配置一个选项,那么我们就不用创建流程和关闭流程了
也就是
JbpmContext jc = JbpmConfiguration.getInstance().getCurrentJbpmContext();
代替 :
JbpmContext jc = JbpmConfiguration.getInstance().createJbpmContext();
CloseJbpmConfigurationServlet
org.jbpm.web.CloseJbpmConfigurationServlet
1
JbpmContextFilter
org.jbpm.web.JbpmContextFilter
JbpmContextFilter
*.jsp
注意:loadTaskInstance和loadProcessInstance 的工作其实可以调用
jbpmContext.loadTaskInstance(123);
jbpmContext.loadProcessInstance(123);
jbpmContext.save(processInstance);
他会去委托相应的session来完成
-----------Session--------------------------------------------------------------
Session , GraphSession , TaskMgmtSession
GraphSession graphSession = jbpmContext.getGraphSession();
Session session = jbpmContext.getSession();
其中GraphSession对于维护Jbpm的表,因为jbpm的xml对我们来说就是一个图(至少eclipse中是)
而Session是管理jbpm以外的表的
所以graphSession可以部署流程定义(其实就是save到jbpm的表里面嘛)
graphSession.deployProcessDefinition(processDefinition);//部署流程定义,如果已经存在同名的定义,则版本号会自动累加
graphSession.loadProcessDefinition(processDefinitionId);
graphSession.findLastestProcessDefinition("xxx");
graphSession.saveProcessDefinition(pd);
而session可以增删改查普通数据表
session.save(qingjiaForm);
session.load(QingjiaForm.class,Long.parseLong(id));
TaskMgmtSession tackMgmtSession = jbpmContext.getTaskMgmtSession();
这个session是用来和jbpm数据库表中的与工作相关的东西打交道的
//只能获取尚未完成的任务列表
//得到这个用户的所有taskInstance,这个userId就是assigment里面的actor-id
List list = taskMgmtSession.findTaskInstance(userId);
TaskInstance taskInstance = taskMgmtSession.loadTaskInstance(id);
---------------ProcessDefinition----------------------------------------------------------
ProcessDefinition这个对象是拥有xml信息的对象
从文件中拿到
ProcessDefinition processDefinition =
ProcessDefinition.parseXmlResource("org/ministone/training/jbpm/processdefinition.xml");
ProcessDefinition pd =
ProcessDefinition.parseParZipInputStream(new ZipInputStream(file.getInputStream()));
从数据库中拿到
ProcessDefinition processDefinition =
graphSession.loadProcessDefinition(processDefinitionId);
ProcessDefinition processDefinition =
graphSession.findLastestProcessDefinition("xxx");
从字符串中拿到
ProcessDefinition processDefinition =
ProcessDefinition.parseXmlString("
xx");
pd.getFileDefinition().getBytes(String name); //这个是从数据库中获取文件的字节流,需要传入文件的名字
Map bytesMap = pd.getFileDefinition().getBytesMap();//得到每一个文件
ZipOutputStream zipOutputStream
= new ZipOutputStream(resp.getOutputStream());
for(Iterator it=bytesMap.keySet().iterator();it.hasNext();){
String fname = (String)it.next();
byte[] filebytes = fd.getBytes(fname);
ZipEntry zipEntry = new ZipEntry(fname); //创建一个zip文件入口
zipOutputStream.putNextEntry(zipEntry);//使得入口和outputStream相连
zipOutputStream.write(fileBytes);
zipOutputStream.closeEntry();
}
zipOutputStream.finish();
zipOutputStream.flush();
zipOutputStream.close();
------------------ProcessInstance---------------------------------------------------------------
ProcessInstance是根据processDefinition给new出来的,他相当于xml的动态部分,
也就是有状态的ProcessInstance
ProcessInstance processInstance =
new ProcessInstance(processDefinition);
jbpmContext.save(processInstance); //一般是在开始加载流程的时候弄
--------------taskInstance-----------------------------------------
if(taskInstance.getStart()==null)
taskInstance.start(); //标识一个任务的执行开始:任务的开始时间被填充,看成提交申请
//taskInstance.end();//任务结束时间被填充,下一个节点的初始化,前一个任务的结束和下一个节点的开始在一个事物内,可以看成事审批申请
jbpmContext.save(taskInstance);//记住:驱动完成之后还要save
--------------------创建数据库---------------------------------------
JbpmConfiguration.getInstance().createSchema(); //创建数据库
JbpmConfiguration.getInstance().dropSchema();
pi.signal(); 与 ti.end()的区别
联系: 他们都是调用了rootToken.signal()方法,
区别: ti.end()里面有这样一段代码
this.end = Clock.getCurrentTime(); //这个是对时间做了处理
而我们取代办任务列表的时候List list = taskMgmtSession.findTaskInstance(userId);
他的依据是if(end == null){获取}他不管流程的位置的
-----------------xml----------------------------------------------------
//这种形式,那么这个工作fill form只固定这一个人来处理
//这种形式,那么这个工作fill form只固定这一个人来处理
流程角色 swimlane
然后
//这种形式,那么这个工作fill form只固定这一个人来处理
就可以变成
用变量传递参与者id
---通过这个类和上一个参数来动态加载这个actor-id
Handler 实现
public class UserIdAssigmentHandler implements AssignmentHandler{
public void assign(Assignable assignable,ExecutionContext executionContext){
// String actorid = (String)executionContext.getVariable("userid");
String currentActorId = (String)executionContext.getProcessInstance().getContextInstance().getVariable("currentId");
//先得到当前的id,然后再通过业务逻辑,找到相应的处理者,然后设置进去
assignable.setActorId(this.getRealActorId(currentActorId)); //把我们需要的actor-id放进去
}
}
String currentActorId = (String)executionContext.getProcessInstance().getContextInstance().getVariable("currentId");
这一句依赖于上一个页面有:
taskInstance.getProcessInstance().getContextInstance().setVariable("currentId","34");
这样也可以
但是在到达这个tack前需要设置
pi.getContextInstance().setVariable("userid",xxx);
这样的话,assignement的执行者就会被自动赋值上
List list = ti.getTask().getTaskNode().getLeavingTransitions();
这个可以得到TaskNode的所有trans,因为有时候会有多个trans
-----------------------------------------------------------------------
--------------节点介绍-----------------------------------
start-state 这个节点可以指定task 但是不能指定task里面的actor
public TaskInstance createStartTaskInstance()
{
TaskInstance taskInstance = null;
Task startTask = taskMgmtDefinition.getStartTask();
if(startTask != null)
{
Token rootToken = processInstance.getRootToken();
ExecutionContext executionContext = new ExecutionContext(rootToken);
taskInstance = createTaskInstance(startTask, executionContext);
taskInstance.setActorId(SecurityHelper.getAuthenticatedActorId()); //这里actorId被覆盖了
}
return taskInstance;
}
那么如何设置这个被认证过的id呢?
jbpmContext.setActorId((String)session.getAttribute("actorId"));
TaskInstance ti = pi.getTaskMgmtInstance().createStartTaskInstance();//这里就得到了在start里面的任务
ti.start();
ti.end(); //一般第一个start节点就是做些初始化准备工作,所以连续的start,end
在start-state里面还可以指定swimlane,而且这个swimlane都不用写assigment,因为这个任务的执行者也是通过set进去的
这样就可以直接用
---------------------------------------------
jbpm.cfg.xml
---这个配置意思是把流程定义存到指定的目录下面而不是数据库中