`

完整工作流JBPM项目实战全过程教程2---项目详细讲解

阅读更多




继续上一篇。
当数据库建立完成后,下载源代码,部署到服务器后,即可以开始体验完整的JBPM+SSH应用了。 
  项目采用的是ssh+jbpm开发模式,而且,项目功能比较齐全,代码量比较大,所以,本教程就不介绍开发过程了。
如果你对SSH整合开发应用已经够熟悉了的话,相信本项目对你来说将并不会有多大难度 。
下面我们把重点放在JBPM上。当然你得先把项目部署成功,才好边做边理解jbpm是怎么在项目中管理流程的。 
     ok,假定你已经把项目跑起来了吧。
先以管理员manager登录系统,管理员具有添加新文章类型的权限。当你添加一个文章类型后,需要指定该类型的文章到时候是按哪个流程来进行审批的。你需要上传一个zip格式的流程定义文件文件(其中压缩了gpd.xml,processdifinition.xml,和processimage.jpg)。点击发布,系统转到articletypeaddsub.do,执行ArticleTypeAddSubAction.java
......
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
........
/**
*
* 增加文章类型操作Action类
*
* @struts.action path="/articletypeaddsub" scope="request" validate="false"
*/
public class ArticleTypeAddSubAction extends Action {
private static final Log log = LogFactory.getLog(MainAction.class);

    /**
     * JBPM服务接口实现对象
     */
private JbpmConfiguration jbpmConfiguration;   //参见spring的配置文件applicationContext.xml
    /**
     * 文章类型服务接口实现对象
     */
private ArticleTypeService articleTypeService;
/**
  * Method execute
  *
  * @param mapping
  * @param form
  * @param request
  * @param response
  * @return ActionForward
  */
public ActionForward execute(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) {
  log.debug("MainAction.execute()");

  UploadDeployForm theForm = (UploadDeployForm) form;
  FormFile file = theForm.getFiles();// 取得上传的文件
  //得到JBPM环境
  JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
  try {
   //解压zip文件流
   ZipInputStream zipInputStream = new ZipInputStream(file
     .getInputStream());
   ProcessDefinition processDefinition = ProcessDefinition
     .parseParZipInputStream(zipInputStream);
   //发布流程文件
   jbpmContext.deployProcessDefinition(processDefinition);
   jbpmContext.close();
   zipInputStream.close();
   //增加文章类型
   ArticleType articleType = new ArticleType();
   articleType.setPdName(processDefinition.getName());
   articleType.setTypeName(theForm.getTypeName());
  
   articleTypeService.addArticleType(articleType);
  } catch (IOException e) {
   log.error("exception", e);
  }
 
  request.setAttribute("success","发布成功");
 
  return mapping.findForward("success");
}

/**
  * 得到JBPM服务接口实现对象
  * @return jbpmConfiguration
  */
public JbpmConfiguration getJbpmConfiguration() {
  return jbpmConfiguration;
}

/**
  * 设置JBPM服务接口实现对象
  * @param jbpmConfiguration
  *            要设置的 jbpmConfiguration
  */
public void setJbpmConfiguration(JbpmConfiguration jbpmConfiguration) {
  this.jbpmConfiguration = jbpmConfiguration;
}

/**
  * 得到文章类型服务接口实现对象
  * @return articleTypeService
  */
public ArticleTypeService getArticleTypeService() {
  return articleTypeService;
}

/**
  * 设置文章类型服务接口实现对象
  * @param articleTypeService 要设置的 articleTypeService
  */
public void setArticleTypeService(ArticleTypeService articleTypeService) {
  this.articleTypeService = articleTypeService;
}

}
执行到这步后,你可以去查看下数据库中表jbpm_processdifinition,你会发现表中多出里一条记录,并且名字就是你上传的压缩文件中processdifinition.xml中的name属性的值。其他的表也会有相应的变化,具体看字段的定义就会大概明白了。
好了,流程已经发布到了系统中了。当然你还可以增加其他的文章类型并且指定不同的流程定义。

      我们退出系统,以guest用户登录系统,然后编写文章,这里需要说明的是,当你选择不同的文章类型后,该文章的审批过程就会与你刚才定义的执行流程相关了。 
     点击保存,
系统调用的ACTION为: 
   MyArticleAddSubAction.java
.........
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;

........
/**
*
* 撰写文章操作Action类
* @struts.action path="/myarticleaddsub" scope="request" validate="false"
*/
public class MyArticleAddSubAction extends Action{
    private static final Log log = LogFactory.getLog(MyArticleAddSubAction.class);
    /**
     * 文章服务接口实现对象
     */
    private ArticleService articleService;
    /**
     * 文章类型服务接口实现对象
     */
    private ArticleTypeService articleTypeService;
    /**
     * JBPM服务接口实现对象
     */
    private JbpmConfiguration jbpmConfiguration;
/**
  * Method execute
  * @param mapping
  * @param form
  * @param request
  * @param response
  * @return ActionForward
  */
public ActionForward execute(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) {
  log.debug("MyArticleAction.execute()");
 
  UserSession userSesssion = UserSession.getSession(request, response);
  //得到文章信息
  String stypeNo = request.getParameter("typeNo");
  int typeNo = ConvertUtil.convertInt(stypeNo);
  String articleName = request.getParameter("articleName");
  String content = request.getParameter("content");
 
  Article article = new Article();
  article.setArticleName(articleName);
  article.setContent(content);
  article.setState(Article.EDITED);
  article.setTypeNo(new Integer(typeNo));
  article.setUserNo(new Integer(userSesssion.getUserNo()));

  //得到相应的文章类型
  ArticleType articleType = articleTypeService.getArticleType(article.getTypeNo().intValue());

  //得到相应的流程定义,启动流程实例
  JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
 
  ProcessDefinition processDefinition = jbpmContext.getGraphSession().findLatestProcessDefinition(articleType.getPdName());
  ProcessInstance processInstance = new ProcessInstance(processDefinition);
 
  //让流程往下进行一步
  Token token = processInstance.getRootToken();
  token.signal();
 
  //保存流程实例与状态
  jbpmContext.save(processInstance);
  jbpmContext.save(token);
  jbpmContext.close();

 
  article.setPiId(processInstance.getId());
 
  //增加文章
  articleService.addArticle(article); 
      return mapping.findForward("success");
}
/**
  * 得到文章服务接口实现对象
  * @return articleService
  */
public ArticleService getArticleService() {
  return articleService;
}
/**
  * 设置文章服务接口实现对象
  * @param articleService 要设置的 articleService
  */
public void setArticleService(ArticleService articleService) {
  this.articleService = articleService;
}
/**
  * 得到文章类型服务接口实现对象
  * @return articleTypeService
  */
public ArticleTypeService getArticleTypeService() {
  return articleTypeService;
}
/**
  * 设置文章类型服务接口实现对象
  * @param articleTypeService 要设置的 articleTypeService
  */
public void setArticleTypeService(ArticleTypeService articleTypeService) {
  this.articleTypeService = articleTypeService;
}
/**
  * 得到JBPM服务接口实现对象
  * @return jbpmConfiguration
  */
public JbpmConfiguration getJbpmConfiguration() {
  return jbpmConfiguration;
}
/**
  * 设置JBPM服务接口实现对象
  * @param jbpmConfiguration 要设置的 jbpmConfiguration
  */
public void setJbpmConfiguration(JbpmConfiguration jbpmConfiguration) {
  this.jbpmConfiguration = jbpmConfiguration;
}



    执行该action后,则就创建了一个与之匹配的流程实例。
查看数据库中article表的变化。可以发现
PiId记录了一个数字编号,同时jbpm_processinstance表中最大的一个id号与之匹配,这说明当保存文章时,系统后台创建了一个流程实例,该流程实例就是记录该文章的审批过程的JBPM实例。(你可以运行一个文章的审批全过程来跟踪与之匹配的流程实例变化情况)。
下一步就是发布该文章了。
到你的文章列表中点击“发布”。 
  系统调用ACTION:MyArticlePubAction.java继而转到MyArticlePubSubAction.java
.......
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.Transition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
.........

/**
*
* 发布文章操作Action类
* @struts.action path="/myarticle" scope="request" validate="false"
*/
public class MyArticlePubAction extends Action{
    private static final Log log = LogFactory.getLog(MyArticlePubAction.class);
   
    private ArticleService articleService;
   
    private ArticleTypeService articleTypeService;

    private JbpmConfiguration jbpmConfiguration;
       
/**
  * Method execute
  * @param mapping
  * @param form
  * @param request
  * @param response
  * @return ActionForward
  */
public ActionForward execute(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) {
  log.debug("MyArticleAction.execute()");
 
  UserSession userSesssion = UserSession.getSession(request, response);
  //得到文章信息
  //得到文章号
  String sarticleNo = request.getParameter("articleNo");
  int articleNo = ConvertUtil.convertInt(sarticleNo);
 
  Article article = articleService.getArticle(articleNo);
  request.setAttribute("article", article);
  //判断是否是此用户文章
  if(article.getUserNo() != null && article.getUserNo().intValue() == userSesssion.getUserNo()){
  
   //创建相应的流程实例
   //得到相应的文章类型
   ArticleType articleType = articleTypeService.getArticleType(article.getTypeNo().intValue());
   request.setAttribute("articleType", articleType);
   //得到相应的流程
   JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
  
   ProcessInstance processInstance = jbpmContext.getProcessInstance(article.getPiId());
   log.error("instance:" + processInstance.getId());
  
    //得到当前的执行令牌
   Token token = processInstance.getRootToken();
   //得到当前的可执行转换
   //Set transitions = token.getNode().getArrivingTransitions();
   List transitions = token.getNode().getLeavingTransitions();
   Set transitionnames = new HashSet();
   if(transitions != null){
    for(int i=0; i<transitions.size(); i++){
     Transition transition = (Transition)transitions.get(i);
     System.err.println("transition.getName()" + transition.getName());
     transitionnames.add(transition.getName());
    }
   }
   request.setAttribute("transitionnames", transitionnames);
   jbpmContext.close();
  
  }
 
 
return mapping.findForward("success");
 }
 public ArticleService getArticleService() {
  return articleService;
 }
 public void setArticleService(ArticleService articleService) {
  this.articleService = articleService;
 }
 public JbpmConfiguration getJbpmConfiguration() {
  return jbpmConfiguration;
 }
 public void setJbpmConfiguration(JbpmConfiguration jbpmConfiguration) {
  this.jbpmConfiguration = jbpmConfiguration;
 }
 public ArticleTypeService getArticleTypeService() {
  return articleTypeService;
 }
 public void setArticleTypeService(ArticleTypeService articleTypeService) {
  this.articleTypeService = articleTypeService;
 }

}

 

ok,到这里,你仍然可以去查看数据库中article表的变化情况。你会发现表中的Auditstate字段

由null变成了一级审批,这是为什么,因为该文章对应的流程的下一个节点就是一级审批。

然后我们以one(一级审批)用户登录,就可以看到需要一级审批用户审批的文章列表了。

  需要说明的是:这些文章是按照登录用户的权限来显示的,只要是该权限级别的用户,就可以看到系统中所有的Auditstate为该状态(权限名和状态名相同,方便查询)的文章article了 。

执行相关的审批操作。继续调用相应的action,然后按照流程定义,一直执行下去,知道该文章的审批流程结束(这里就不再一一说明了)。

OK,流程执行完成。一个完整的JBPM实例执行结束。

  思考的问题来了!

  我们并不知道articl表中的Auditstate是怎么变化的啊?

在Struts的action中并没有看见显示的代码调用来修改数据库Auditstate字段啊,难道是JBPM自动做的处理?

当然不是!不过我们可以让JBPM帮助我们来完成。

你注意到了processdefinition.xml配置文件吗?

-<state name="编辑完成">
-<transition name="发布" to="一级审批">
  <action name="action" class="c20.jbpm.action.PubActionHandler" />
</transition>
</state>

没错,就是<action name="action" class="c20.jbpm.action.PubActionHandler" /> 的功劳。

当一个流程中一个state执行完,需要transition 到下一个State时,JBPM将会自动执行class指定的句柄。

 

.......

import org.jbpm.graph.def.ActionHandler;
import org.jbpm.graph.def.Node;
import org.jbpm.graph.def.Transition;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.graph.exe.ProcessInstance;

........

/**
 * 文章发布处理器
 * @author yuxd
 *
 */
public class PubActionHandler implements ActionHandler {

 private static final long serialVersionUID = 1L;
 
 /**
  * A message process variable is assigned the value of the message
  * member. The process variable is created if it doesn't exist yet.
  */
 public void execute(ExecutionContext context) throws Exception {
  //得到对应实例ID
  ProcessInstance processInstance = context.getContextInstance().getProcessInstance();
  
  //得到当前执行转换
  Transition transition = context.getTransition();
  Node node = transition.getTo();
  
  //得到对应的文章
  ArticleService articleService = (ArticleService)BeanFactory.getBean("articleService");

  List list = articleService.getArticlesByPdInstance(processInstance.getId());
  
  //设置文章状态为发布中
  if(list != null){
   for(int i=0; i<list.size(); i++){
    Article article = (Article)list.get(i);
    
    if(article.getState() != null && article.getState().intValue() == Article.EDITED){
     article.setState(new Integer(Article.PUBLISH));
     
     article.setAuditState(node.getName());
     
     articleService.modArticle(article);
    }
   }
  }
 }

}

 

由此,可以得知,JBPM中句柄是怎么在流程运作的过程中对业务数据做出处理的吧!,这也正是JBPM句柄的作用之所在!

 

 

 

 到这里,JBPM的具体应用就介绍的已经很详细了。

下面来说说项目中是怎么巧妙的将业务和JBPM流程结合使用的吧。

我们来看看业务表article的结构,

article  CREATE TABLE `article` (                                                                     
           `ArticleNo` int(11) NOT NULL auto_increment COMMENT '文章号',                           
           `UserNo` int(11) default NULL COMMENT '用户号',                                         
           `TypeNo` int(11) default NULL COMMENT '文章类型号',                                   
           `ArticleName` varchar(128) default NULL COMMENT '文章名称',                            
           `Content` text COMMENT '文章内容',                                                     
           `PiId` bigint(20) default NULL COMMENT '对应流程实例号',                            
           `AuditState` varchar(64) default NULL COMMENT '审批状态',                              
           `AuditComment` varchar(255) default NULL COMMENT '审批说明',                           
           `State` int(11) default NULL COMMENT '文章状态',                                       
           PRIMARY KEY  (`ArticleNo`),                                                                
           KEY `FK_Relationship_1` (`TypeNo`),                                                        
           KEY `FK_Relationship_2` (`UserNo`),                                                        
           CONSTRAINT `FK_Relationship_1` FOREIGN KEY (`TypeNo`) REFERENCES `articletype` (`TypeNo`), 
           CONSTRAINT `FK_Relationship_2` FOREIGN KEY (`UserNo`) REFERENCES `user` (`UserNo`)         
         ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=gb2312 COMMENT='文章表'                 
不然看出,恰恰是表中的 `PiId` bigint(20) default NULL COMMENT '对应流程实例号字段,完美的和流程的ID映射起来,使得一篇文章绑定到一个具体的流程实例。并且文章的状态在流程的运作当中利用JBPM句柄ActionHandler动态变化。最终实现业务的运作。

 

     so,JBPM在web项目中的具体应用就介绍完了。希望通过本教程学习的朋友,能够得到确实的提高。并且在教程中的一些个人拙见,望大侠们积极的批正!

24
3
分享到:
评论
14 楼 zpchen 2008-10-28  
sam.ds.chen 写道

bluemare 写道
貌似跑不起来 Java代码 java.lang.ClassNotFoundException: org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean 这是因为缺少依赖:spring-modules,可以去springmodules项目(springmodules跟spring不是一个东西)的官方网站下载https://springmodules.dev.java.net/ P.S.:建议zpchen重新打一下包,里面一堆病毒会吓人家一跳的。

因为上传单个文件限制在10M,所以项目就分成了几个文件来上传,可能那个jar包没添加进去,现在上传了,不过要申明下,病毒是绝对没有滴,可能是你杀软的问题
13 楼 sam.ds.chen 2008-10-28  
bluemare 写道

貌似跑不起来


Java代码

java.lang.ClassNotFoundException: org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean



这是因为缺少依赖:spring-modules,可以去springmodules项目(springmodules跟spring不是一个东西)的官方网站下载https://springmodules.dev.java.net/

P.S.:建议zpchen重新打一下包,里面一堆病毒会吓人家一跳的。
12 楼 longhao 2008-10-28  
javaeye 写道

org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean

11 楼 longhao 2008-10-28  
真跑不起来

org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean
10 楼 lsqlister 2008-10-28  
楼主上传的jar缺少spring-modules-jbpm31.jar
9 楼 hellboy 2008-10-27  
正是我想要的东东,非常谢谢
8 楼 mn_1127 2008-10-27  
我下载的时候怎么提示有病毒呀
7 楼 zpchen 2008-10-27  
严重: StandardWrapper.Throwable  
java.lang.RuntimeException: ???????????????  
bluemare 写道

貌似跑不起来
..............
严重:&nbsp;action:&nbsp;null&nbsp;&nbsp;
...........
严重:&nbsp;StandardWrapper.Throwable &nbsp;&nbsp;
java.lang.RuntimeException:&nbsp;??????????????? &nbsp;&nbsp;

...........

在我看来你的环境可能没搭好,
java.lang.RuntimeException: ???????????????  
这里应该是输出中文的,而且这个RuntimeException是自定义的。输出应该为中文。
6 楼 bluemare 2008-10-27  
貌似跑不起来
13:13:30,625  WARN QuerySplitter:116 - no persistent classes found for query class: 
    
      delete
      from org.jbpm.msg.Message m
      where m.token = :token
    
  
13:13:30,625  WARN QuerySplitter:116 - no persistent classes found for query class: 
    
      update org.jbpm.msg.Message m
      set m.isSuspended = false
      where m.token = :token 
    
  
13:13:30,703  WARN QuerySplitter:116 - no persistent classes found for query class: 
    
      select message
      from org.jbpm.msg.Message as message
      where message.destination = :destination
        and message.isSuspended != true
        and message.exception is not null
    
  
13:13:30,703  WARN QuerySplitter:116 - no persistent classes found for query class: 
    
      update org.jbpm.msg.Message m
      set m.isSuspended = true
      where m.token = :token 
    
  
13:13:30,765  WARN QuerySplitter:116 - no persistent classes found for query class: 
    
      select message
      from org.jbpm.msg.Message as message
      where message.destination = :destination
        and message.isSuspended != true
        and message.exception is null
    
  
13:13:30,953  INFO HibernateTransactionManager:382 - Using DataSource [org.springframework.jdbc.datasource.DriverManagerDataSource@145c761] of Hibernate SessionFactory for HibernateTransactionManager
13:13:30,953  INFO DefaultListableBeanFactory:274 - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@b122a1: defining beans [dataSource,sessionFactory,transactionManager,jbpmConfiguration,userInfoDao,userService,userdutyDao,userdutyService,articleDao,articleService,articleTypeDao,articleTypeService,/loginsub,/logout,/modpass,/modpasssub,/useradd,/useraddsub,/usermod,/usermodsub,/userdelsub,/user,/userdutyadd,/userdutyaddsub,/userdutymod,/userdutymodsub,/userdutydelsub,/userduty,/main,/menu,/myarticleadd,/myarticleaddsub,/myarticlemod,/myarticlemodsub,/myarticledelsub,/myarticlepub,/myarticlepubsub,/myarticle,/myarticlelist,/articleaudit,/articleauditsub,/articleauditlist,/articletypeadd,/articletypeaddsub,/articletypemod,/articletypemodsub,/articletypedelsub,/articletype]; root of factory hierarchy
13:13:30,968  INFO LocalSessionFactoryBean:188 - Closing Hibernate SessionFactory
13:13:30,968  INFO SessionFactoryImpl:729 - closing
13:13:31,015 ERROR ContextLoaderPlugIn:229 - Context initialization failed
org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean] for bean with name 'jbpmConfiguration' defined in ServletContext resource [/WEB-INF/applicationContext.xml]; nested exception is java.lang.ClassNotFoundException: org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean
Caused by: 
java.lang.ClassNotFoundException: org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1358)
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1204)
	at org.springframework.util.ClassUtils.forName(ClassUtils.java:201)
	at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:325)
	at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1033)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:274)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:360)
	at org.springframework.web.struts.ContextLoaderPlugIn.createWebApplicationContext(ContextLoaderPlugIn.java:355)
	at org.springframework.web.struts.ContextLoaderPlugIn.initWebApplicationContext(ContextLoaderPlugIn.java:296)
	at org.springframework.web.struts.ContextLoaderPlugIn.init(ContextLoaderPlugIn.java:225)
	at org.apache.struts.action.ActionServlet.initModulePlugIns(ActionServlet.java:869)
	at org.apache.struts.action.ActionServlet.init(ActionServlet.java:336)
	at javax.servlet.GenericServlet.init(GenericServlet.java:212)
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:981)
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4045)
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4351)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
	at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:920)
	at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:883)
	at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
	at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
	at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
	at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
	at org.apache.catalina.core.StandardService.start(StandardService.java:516)
	at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
2008-10-27 13:13:31 org.apache.catalina.core.ApplicationContext log
严重: action: null
org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean] for bean with name 'jbpmConfiguration' defined in ServletContext resource [/WEB-INF/applicationContext.xml]; nested exception is java.lang.ClassNotFoundException: org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean
Caused by: java.lang.ClassNotFoundException: org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1358)
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1204)
	at org.springframework.util.ClassUtils.forName(ClassUtils.java:201)
	at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:325)
	at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1033)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:274)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:360)
	at org.springframework.web.struts.ContextLoaderPlugIn.createWebApplicationContext(ContextLoaderPlugIn.java:355)
	at org.springframework.web.struts.ContextLoaderPlugIn.initWebApplicationContext(ContextLoaderPlugIn.java:296)
	at org.springframework.web.struts.ContextLoaderPlugIn.init(ContextLoaderPlugIn.java:225)
	at org.apache.struts.action.ActionServlet.initModulePlugIns(ActionServlet.java:869)
	at org.apache.struts.action.ActionServlet.init(ActionServlet.java:336)
	at javax.servlet.GenericServlet.init(GenericServlet.java:212)
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:981)
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4045)
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4351)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
	at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:920)
	at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:883)
	at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
	at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
	at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
	at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
	at org.apache.catalina.core.StandardService.start(StandardService.java:516)
	at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
2008-10-27 13:13:31 org.apache.catalina.core.ApplicationContext log
信息: Marking servlet action as unavailable
2008-10-27 13:13:31 org.apache.catalina.core.StandardContext loadOnStartup
严重: Servlet /articleaudit threw load() exception
javax.servlet.UnavailableException
	at org.apache.struts.action.ActionServlet.initModulePlugIns(ActionServlet.java:880)
	at org.apache.struts.action.ActionServlet.init(ActionServlet.java:336)
	at javax.servlet.GenericServlet.init(GenericServlet.java:212)
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:981)
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4045)
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4351)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
	at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:920)
	at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:883)
	at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
	at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
	at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
	at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
	at org.apache.catalina.core.StandardService.start(StandardService.java:516)
	at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
2008-10-27 13:13:31 org.apache.catalina.core.ApplicationContext log
严重: StandardWrapper.Throwable
java.lang.RuntimeException: ???????????????
	at c20.helper.AppInitServlet.init(AppInitServlet.java:29)
	at javax.servlet.GenericServlet.init(GenericServlet.java:212)
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:981)
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4045)
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4351)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
	at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:920)
	at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:883)
	at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
	at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
	at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
	at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
	at org.apache.catalina.core.StandardService.start(StandardService.java:516)
	at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
2008-10-27 13:13:31 org.apache.catalina.core.StandardContext loadOnStartup
严重: Servlet /articleaudit threw load() exception
java.lang.RuntimeException: ???????????????
	at c20.helper.AppInitServlet.init(AppInitServlet.java:29)
	at javax.servlet.GenericServlet.init(GenericServlet.java:212)
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:981)
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4045)
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4351)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
	at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:920)
	at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:883)
	at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
	at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
	at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
	at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
	at org.apache.catalina.core.StandardService.start(StandardService.java:516)
	at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)

5 楼 flyfan 2008-10-27  
真的很需要,自己对工作流的认识还少,谢谢你的文章
4 楼 zpchen 2008-10-27  
shanghui_12 写道

呵呵,新教程来了,同学们好好学习!

谢谢支持!
3 楼 zpchen 2008-10-27  
kangsg219 写道

太需要了 ,及时雨啊!感谢!不知道有没有用户自定义流程功能呢?

当然可以,你只需要自己定义流程定义文件gpd.xml,processdifinition.xml,和processimage.jpg,不过注意了,在定义流程定义的时候,各个state的名称必须在数据库userduty表中.如果你想自己定义了流程定义state名称,那么你需要把这个新的名称加入到userduty表中,这就是业务中,用户职责和权限的耦合。
   当然你在定义流程文件的时候可以利用MyEclipse的插件,这样效率会比较高.
2 楼 kangsg219 2008-10-27  
太需要了 ,及时雨啊!感谢!
不知道有没有用户自定义流程功能呢?
1 楼 shanghui_12 2008-10-27  
呵呵,新教程来了,同学们好好学习!

相关推荐

    完整工作流JBPM项目实战全过程教程3----项目后续DIY

    在本教程中,我们将深入探讨基于JBPM的工作流项目实战全过程,特别关注“项目后续DIY”阶段。JBPM(Java Business Process Management)是一个开源的工作流管理系统,它提供了全面的业务流程管理和工作流自动化功能...

    JBPM开发实战教程

    通过本教程的学习,读者可以全面了解JBPM的基本概念、安装配置过程以及如何基于JBPM开发实际项目中的工作流应用。无论是初学者还是有一定经验的开发者,都能够从中获得有价值的信息和技术指导。希望读者能够在实践中...

    jbpm实战讲解.pdf

    ### JBPM实战讲解知识点概述 #### 一、JBPM概览与重要性 JBPM,全称为Java Business Process Management,是JBoss旗下的一款强大的工作流和业务流程管理框架。它旨在帮助企业通过自动化业务流程,提高效率和灵活性...

    jbpm-jpdl-designer-site-3.1.7.zip

    jbpm-jpdl-designer-site-3.1.7.zip jbpm-jpdl-designer-site-3.1.7.zip jbpm-jpdl-designer-site-3.1.7.zip

    jbpm-jpdl-designer-nodeps-3.1.4

    "jbpm-jpdl-designer-nodeps-3.1.4" 是一个针对Jbpm工作流管理系统中的JPDL设计工具的无依赖版本,主要用于创建和编辑JPDL(Jbpm Process Definition Language)文件。该资源包含了该工具的详细文档、许可证协议以及...

    工作流jbpm---学习文档+简单实例项目

    标题提到的“工作流jbpm---学习文档+简单实例项目”是一份包含学习资料和实际操作案例的资源集合,旨在帮助开发者快速理解和掌握jbpm的使用。其中,"jBPM4.4课程文档.doc"很可能是关于jbpm 4.4版本的详细教程,涵盖...

    jbpm5初级demo的安装过程-基于eclipse

    这个过程主要讲解如何在Windows环境下,使用Eclipse集成开发环境来安装并运行jbpm5的初级演示项目。 首先,我们需要安装基础环境,即JBoss应用服务器。步骤如下: 1. **安装JBoss**:访问指定的下载地址...

    jbpm-3_2_2-Api

    jbpm-3_2_2-Api jbpm 著名工作流引擎

    jbpm下载 jbpm-jpdl-suite-3.2GA -(5)分开压缩(共5个文件)

    jbpm-jpdl-suite-3.2GA -(5)分开压缩(共5个文件)jbpm下载 jbpm-jpdl-suite-3.2GA -(5)分开压缩(共5个文件)jbpm下载

    jbpm中文教程-详细

    【jbpm中文教程-详细】 Java Business Process Management(jbpm)是开源社区提供的一款强大的业务流程管理系统,它允许开发者设计、执行和管理业务流程。jbpm不仅提供了完整的BPM(Business Process Management)...

    工作流JBPM开发计划书

    ### 工作流JBPM开发计划书 #### 一、项目背景与目标 在当前数字化转型的大背景下,企业越来越依赖于高效的工作流程管理来提升业务效率和服务质量。JBPM(JBoss流程管理)作为一款开源的工作流引擎,因其灵活性、可...

    jbpm-2.0-beta1.zip_java 工作流引擎_jbpm_jbpm-demo_工作流_工作流引擎

    jbpm-2.0-beta1是该系统的早期版本,其核心功能包括工作流引擎、流程建模工具以及一系列示例项目,如jbpm-demo,用于帮助用户更好地理解和应用jbpm。 工作流引擎是jbpm的核心组件,它负责解析和执行工作流定义...

    JBPM5工作流引擎 S2SH+JBPM4.4开发工作流的一个完整的请假流程例子

    JBPM5工作流引擎 S2SH+JBPM4.4开发工作流的一个完整的请假流程例子。带有文档教程和所有源码+JAR包。在网上找了半天jbpm6\jbpm7的资料,都很少。所以 环境:Myeclipse2015 JDK1.7 mysql 5.0 Struts2+Spring3.1 1...

    jbpm-jpdl-designer-nodeps-3.0.13.zip

    jbpm-jpdl-designer-nodeps-3.0.13.zip是一款专为流程设计和管理而生的工具,主要用于JBPM(Java Business Process Management)系统。JBPM是一个开源的工作流和业务流程管理系统,它提供了对业务流程的建模、部署、...

Global site tag (gtag.js) - Google Analytics