首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

jBPM的Scheduler模块跟Spring集成失败

2012-11-04 
jBPM的Scheduler模块和Spring集成失败我的Web系统中使用了jBPM,并使用Spring来管理bean,并使用Spring+JTOM

jBPM的Scheduler模块和Spring集成失败
我的Web系统中使用了jBPM,并使用Spring来管理bean,并使用Spring+JTOM组合来管理来自多个数据库的事务(有Oracle9i,Microsoft SQL Server 2000)。但是没有使用jBPM的Scheduler。系统运行很好。
最近由于业务需要,我在jBPM中添加了timer。这样,就需要配置一个Scheduler了。而我的麻烦也从此开始。

我一开始使用jBPM提供的那个SchedulerServlet,可是发现这个Servlet会去自动加载jBPM的默认配置,也就是在default.jbpm.ctf.xml中配置的属性,特别是数据库的配置。这样,我的Spring就无法管理它的事务了。
我查看了它的源代码,发现其代码如下(省略了不相干代码):

public class SchedulerServlet extends HttpServlet {  private static final long serialVersionUID = 1L;    Scheduler scheduler = null;  public void init() throws ServletException {    // create a new scheduler    scheduler = new Scheduler();    // start the scheduler    scheduler.start();  }  ...}public class Scheduler {    SchedulerThread schedulerThread = null;  ...  public void start() {    log.debug("starting the scheduler");    schedulerThread = new SchedulerThread();    schedulerThread.setInterval(interval);    schedulerThread.addListener(new HistoryListener());    schedulerThread.start();  }  ...}public class SchedulerThread extends Thread {  JbpmConfiguration jbpmConfiguration = null;  String jbpmContextName = null;  ...  public SchedulerThread() {    this(JbpmConfiguration.getInstance(), JbpmContext.DEFAULT_JBPM_CONTEXT_NAME);  }  ...}


我查找了相关资源,发现没有现成的和Spring集成的工具。(jBPM的核心引擎已经有spring-module提供了集成工具)。我想,那我自己覆盖这个SchedulerServlet,让这个SchedulerThread使用Spring管理下的JbpmConfiguration实例,那不就可以达到目的了吗?于是动手。

可是这时候才发现,这个jBPM提供的Scheduler对象,根本就没有可以让我能够向SchedulerThread注射入JbpmConfiguration的入口。而且这个类是default的可见范围,连继承扩展都做不到。迫于无奈,我在Scheduler的相同package下,建了一个子类,来提供注入Spring管理的JbpmConfiguration实例的能力,然后自己写了一个ServletContextListener来加载这个监听线程。
代码如下:
package org.jbpm.scheduler.impl;...public class SpringAwareScheduler extends Scheduler {        private static final Log log = LogFactory.getLog(SpringAwareScheduler.class);    protected JbpmConfiguration jbpmConfiguration;        public SpringAwareScheduler() {        this(null);    }        public SpringAwareScheduler(JbpmConfiguration jbpmConfiguration) {        super();        this.jbpmConfiguration = jbpmConfiguration;    }        /**     * @param jbpmConfiguration the jbpmConfiguration to set     */    public void setJbpmConfiguration(JbpmConfiguration jbpmConfiguration) {        this.jbpmConfiguration = jbpmConfiguration;    }        public void start() {      log.debug("starting the scheduler");      schedulerThread = new SchedulerThread(this.jbpmConfiguration);      schedulerThread.setInterval(interval);      schedulerThread.addListener(new HistoryListener());      schedulerThread.start();    }}

这里是用来取代SchedulerServlet的ServletContextListener:
public class SpringAwareJbpmSchedulerListener implements ServletContextListener {    private Scheduler scheduler = null;        @Override    public void contextDestroyed(ServletContextEvent sce) {        scheduler.stop();    }    @Override    public void contextInitialized(ServletContextEvent sce) {        // create a new scheduler        String beanName = sce.getServletContext().getInitParameter("jbpmConfigurationBeanName");        if (StringUtils.isBlank(beanName)) {            beanName = "jbpmConfiguration";        }        WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext());        JbpmConfiguration jbpmConfiguration = (JbpmConfiguration) wac.getBean(beanName);        scheduler = new SpringAwareScheduler(jbpmConfiguration);                JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext(JbpmContext.DEFAULT_JBPM_CONTEXT_NAME);        SessionFactory sessionFactory = jbpmContext.getSessionFactory();        assert sessionFactory != null;                // initialize it with the servlet init parameters         int interval = 5000;        if (!StringUtils.isBlank(sce.getServletContext().getInitParameter("interval"))) {            interval = Integer.parseInt(sce.getServletContext().getInitParameter("interval"));        }        scheduler.setInterval(interval);                int historyMaxSize = 50;        if (!StringUtils.isBlank(sce.getServletContext().getInitParameter("historyMaxSize"))) {            historyMaxSize = Integer.parseInt(sce.getServletContext().getInitParameter("historyMaxSize"));        }        scheduler.setHistoryMaxSize(historyMaxSize);                // put the scheduler in the web app context        sce.getServletContext().setAttribute("scheduler", scheduler);                // start the scheduler        scheduler.start();    }}


好了,以为现在在web.xml中配置好了以后,总该可以了吧?可是不然。问题又来了。发现系统在启动的过程中,根本没有使用在JbpmConfiguration实例中配置的SessionFactory,而是继续使用根据default.jbpm.cfg.xml中的配置生成的那个SessionFactory实例。
我单步跟踪了一下代码,发现之所以会去加载根据default.jbpm.cfg.xml中的配置生成的那个SessionFactory实例,原因是在DbPersistenceService在获取SessionFactory实例的时候,发现为空,所以就按照默认配置去创建一个新的SessionFactory实例。异常信息如下:
10:19:32,939 FATAL [org.hibernate.connection.DatasourceConnectionProvider] - Could not find datasource: java:/DefaultDSjavax.naming.NameNotFoundExceptionat org.objectweb.carol.jndi.enc.java.CompNamingContext.lookupCtx(CompNamingContext.java:689)at org.objectweb.carol.jndi.enc.java.CompNamingContext.lookup(CompNamingContext.java:179)at org.objectweb.carol.jndi.enc.java.JavaURLContext.lookup(JavaURLContext.java:138)at javax.naming.InitialContext.lookup(InitialContext.java:392)at org.hibernate.connection.DatasourceConnectionProvider.configure(DatasourceConnectionProvider.java:52)at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:124)at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:56)at org.hibernate.cfg.SettingsFactory.createConnectionProvider(SettingsFactory.java:414)at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:62)at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2009)at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1292)at org.jbpm.persistence.db.DbPersistenceServiceFactory.getSessionFactory(DbPersistenceServiceFactory.java:91)at org.jbpm.persistence.db.DbPersistenceService.getSessionFactory(DbPersistenceService.java:76)at org.jbpm.persistence.db.DbPersistenceService.getSession(DbPersistenceService.java:80)at org.jbpm.persistence.db.DbPersistenceService.getSchedulerSession(DbPersistenceService.java:261)at org.jbpm.JbpmContext.getSchedulerSession(JbpmContext.java:531)at org.jbpm.scheduler.impl.SchedulerThread.executeTimers(SchedulerThread.java:104)at org.jbpm.scheduler.impl.SchedulerThread.run(SchedulerThread.java:71)

可是,明明DbPersistenceService的实例是根据JbpmContext创建的,而JbpmContext又是根据JbpmConfiguration实例创建的。也就是说,DbPersistenceService使用的SessionFactory的实例应该是来自JbpmConfiguration的实例中的那个。为什么实际上却为空呢?

现在我晕掉了。到底错误在那里呢? 1 楼 gabriel80 2008-05-14   提示个方法。。用JobExecutorServlet方法来代替你的SchedulerServlet 。
由于我还没有完全弄明白。。只能提供你一个方向。。
抱歉。。。。。
关注中。。。。。。。。 2 楼 ossd_小羊 2008-11-04   是jbpm3.2.3版本吗?

热点排行