石英jboss弹簧多个webapps

时间:2012-08-13 14:51:20

标签: spring jboss datasource quartz-scheduler

我在我的应用程序中成功使用了石英。 基本上我在webapp1内部捆绑了石英,它在Jboss内部运行。

但是我们在jboss中运行了另一个webapp2,它还需要有石英作业

现在我需要做的是在jboss中运行石英调度程序作为某种服务,并且两个webapps都应该能够 在单个石英调度程序上注册他们的工作。

下面是我对webapp1的相关弹簧配置,它一直在工作。

<bean id="qtzScheduler"
    class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="dataSource">
        <ref bean="jndiDataSource" />
    </property>
    <property name="applicationContextSchedulerContextKey">
        <value>applicationContext</value>
    </property>
    <property name="transactionManager">
        <ref bean="transactionManager" />
    </property>
    <property name="schedulerName" value="webapp1" />       
</bean>

<bean id="wrapperScheduler" class="uk.fa.quartz.schedule.ServiceScheduler">
    <property name="scheduler">
        <ref bean="qtzScheduler" />
    </property>
</bean>

<bean id="jndiDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName">
        <value>java:/FmManagerDS</value>
    </property>
</bean>

当我必须安排工作时,代码如下:

   WrapperScheduler scheduler = (WrapperScheduler) ctx.getBean("wrapperScheduler");
   scheduler.scheduleCronJob(job, jobName + "CronTrigger", WrapperScheduler.TRIGGER_GROUP, cronExpression);

现在我不想在webapp2中再次定义相同的调度程序,这将导致在jboss中运行2个石英调度程序。

有人知道怎么做吗? 我在互联网上看到了一个例子,如下面的Link,我认为这样做是我想做的。 但是我不明白如何使用我的spring源中定义的数据源将它与我的系统集成。 如果有人可以共享配置或指向我在互联网上的正确资源,我将非常感谢。

2 个答案:

答案 0 :(得分:2)

您引用的link解释了如何访问Quartz调度程序服务built into JBoss。我从来没有使用过这种方法,但基本上你让JBoss处理你的调度程序,数据源及其周围的一切。这使得在没有所有配置喧嚣的情况下很容易利用作业调度 - 但不是非常灵活,并且您的应用程序不再是自包含的。

在你的情况下,我看到两个值得研究的选择:

集群Quartz调度程序

将您的两个Web应用程序配置为run in a cluster。两个应用程序将共享同一个数据库,并将运行彼此定义的作业。由于以下几个原因,这可能不适合您:

  • 两个应用程序必须能够运行彼此定义的作业 - 例如必须在CLASSPATH上提供工作类

  • 您仍然需要在两个应用程序中定义Quartz配置(您可以轻松地共享配置,例如通过将XML配置提取到单独的文件中)

  • 两个应用程序都将维护单独的线程池

群集更适合在多台计算机上运行的同类应用程序,而不是单节点上的异构应用程序。

远程调度程序

Quartz的built-in support for remote schedulers来自。基本上,一个应用程序托管完整的Quartz服务器,而另一个应用程序连接到该服务器。这似乎是一种更好的方法(让我们称之为“ master-slave ”),因为只有一个应用程序管理调度程序,而另一个应用程序使用现有的调度程序。

请参阅:RemoteScheduler

答案 1 :(得分:0)

最后,我有时间为所有可能必须使用Quartz作为运行在jboss中的服务的人写下来。 但是@Tomasz在他的回答中提到的其他选择也可以尝试。

请注意,如果您尝试从绑定它的JBoss服务器外部检索它,您将获得空引用。如果您有这样的要求,您可能需要考虑使用Quartz的RMI支持。

1)首先确保你删除jboss / [profile] / lib或quartz.rar中任何现有版本的石英,这是jboss发行版。

2)请你的石英.1.8.3.jar&amp; quartz-jboss.1.8.jar进入acccesmanager / [profile] / lib

3)下面是quartz-service.xml的代码,需要放在jboss deploy文件夹中,该文件夹将启动Quartz调度程序:

    <server> 
     <mbean code="org.quartz.ee.jmx.jboss.QuartzService" 
     name="user:service=QuartzService,name=QuartzService">    
     <attribute name="JndiName">Quartz</attribute> 
     <attribute name="Properties">        
     org.quartz.scheduler.instanceName = BGSScheduler 
     org.quartz.scheduler.rmi.export = false 
     org.quartz.scheduler.rmi.proxy = false 
     org.quartz.scheduler.xaTransacted = false 
     org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool  
     org.quartz.threadPool.threadCount = 5 
     org.quartz.threadPool.threadPriority = 4 
     org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer = true
     org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
     org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreCMT
     org.quartz.jobStore.driverDelegateClass =  org.quartz.impl.jdbcjobstore.StdJDBCDelegate
     org.quartz.jobStore.dataSource = QUARTZ
     org.quartz.dataSource.QUARTZ.jndiURL = java:FmManagerDS 
     org.quartz.jobStore.nonManagedTXDataSource = QUARTZ_NO_TX
     org.quartz.dataSource.QUARTZ_NO_TX.jndiURL = java:FmManagerDS
     </attribute>     
     <depends>jboss.jca:service=DataSourceBinding,name=FmManagerDS</depends>
     </mbean> 
     </server>

] 大多数事情都是自我解释的,或者你可以在Quartz Configuration获得更多详细信息。 关键是要注意石英需要2个datasources.One是容器管理的数据源 - 与jboss * -ds.xml中定义的数据源相同(在我的例子中为java:FmManagerDS)。 如果你的'org.quartz.jobStore.dataSource'是XA,那么将'org.quartz.jobStore.nonManagedTXDataSource'设置为非XA数据源(对于同一个DB)。否则,您可以将它们设置为相同。

然后在spring applicationContext中,我必须得到石英的​​句柄,以便我可以注入到wrapperScheduler.Code中,因为它位于

之下
    <bean id="quartzScheduler" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName">
                <value>Quartz</value>
            </property>
    </bean>

<bean id="wrapperScheduler" class="k.fa.quartz.schedule.ServiceScheduler">
            <property name="scheduler">
                <ref bean="quartzScheduler" />
            </property>
    </bean>

然后我们可以使用下面的

来安排工作
Timestamp t = new Timestamp (System.currentTimeMillis());
ScheduleJob job = new ScheduleJob(EmailJob.class.getCanonicalName() +t.toString(), EmailJob.class);

下面是将spring applicationContext传递给EmailJob的代码,以便我们可以访问bean和其他东西。         为了实现这一点,我们需要实现ApplicationContextAware接口,以便applicationContext可用,然后也是如此         推入schedulerContext。请确保我们不将applicationContext放入JobdataMap,因为它会使用JDBC存储,因为它会产生序列化问题。

    serviceScheduler.getScheduler().getContext().put("applicationContext", ctx);
    serviceScheduler.scheduleCronJob(job, "test" + t.toString(), ServiceScheduler.DEFAULT_TRIGGER_GROUP, cronExpression);

其他未使用wrapperscheduler的人可以使用下面的代码直接将石英的句柄直接输入到他们的代码中

    InitialContext ctx = new InitialContext();
    Scheduler scheduler = (Scheduler) ctx.lookup("Quartz");
    ScheduleJob job = new ScheduleJob(EmailJob.class.getCanonicalName() +t.toString(), Executor.class);
    scheduler.scheduleJob(job, trigger);

在电子邮件作业类中,您可以使用以下内容获取applicationContext

       applicationContext = (ApplicationContext) context.getScheduler().getContext().get(APPLICATION_CONTEXT_KEY);
       //get spring bean and do the necessary stuff

另一个重要的事情是,当石英计算器在web应用程序之外运行时,如果它在战争中,则石英将无法触发作业类。它需要位于jboss / [profile] / lib中的共享jar中