Внедрение свойств в QuartzJobObject - PullRequest
2 голосов
/ 26 сентября 2011

Прав ли я, полагая, что в моем QuartzJobObject не может быть введено никаких объектов DAO или других объектов, управляемых Spring?

Я надеялся, что смогу сделать что-то подобное (orderService - это то, что я хочу ввести):

<object name="checkPendingOrdersJob" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
  <property name="JobType" value="Munch.ScheduledTasks.CheckPendingOrdersJob" />
  <!-- We can inject values through JobDataMap -->
  <property name="JobDataAsMap">
    <dictionary>
      <!--entry key="UserName" value="Alexandre" /-->
    </dictionary>      
  </property>
  <property name="orderService" ref="orderService"/>
</object>

... что я знаю, не имеет смысла из-за типа это. Но я мог бы сделать что-то с возможностью вводить некоторые DAO, Сервисы и т. Д. Я не могу понять это все же. Как я могу это сделать?

Ответы [ 2 ]

2 голосов
/ 28 сентября 2011

Это то, с чем я закончил, и это прекрасно работает (надеюсь, полезно кому-то еще)

Фабрика заданий, которая осведомлена о контексте Spring

/// <summary>
/// A custom job factory that is aware of the spring context
/// </summary>
public class ContextAwareJobFactory : AdaptableJobFactory, IApplicationContextAware
{
    /// <summary>
    /// The spring app context
    /// </summary>
    private IApplicationContext m_Context;

    /// <summary>
    /// Set the context
    /// </summary>
    public IApplicationContext ApplicationContext
    {
        set
        {
            m_Context = value;
        }
    }

    /// <summary>
    /// Overrides the default version and sets the context
    /// </summary>
    /// <param name="bundle"></param>
    /// <returns></returns>
    protected override object CreateJobInstance(TriggerFiredBundle bundle)
    {
        return m_Context.GetObject(bundle.JobDetail.JobType.Name, bundle.JobDetail.JobType);
    }
}

Само задание (проверяет БД на наличие записей и, если их хотя бы HomeManyMenuItemsIsOK , все хорошо). Примечание: menuService - это внедренный объект с пружинным управлением, в котором есть несколько DAO). HowManyMenuItemsIsOK - это статическое свойство, которое передается через карту данных задания.

public class CheckMenuIsHealthyJob : QuartzJobObject 
{
    private static readonly ILog log = LogManager.GetLogger(typeof(CheckMenuIsHealthyJob));

    public IMenuService menuService { get; set; }
    public int HowManyMenuItemsIsOK { get; set; }

    /// <summary>
    /// Check how healthy the menu is by seeing how many menu items are stored in the database. If there
    /// are more than 'HowManyMenuItemsIsOK' then we're ok.
    /// </summary>
    /// <param name="context"></param>
    protected override void ExecuteInternal(JobExecutionContext context)
    {
        IList<MenuItem> items = menuService.GetAllMenuItems();
        if (items != null && items.Count >= HowManyMenuItemsIsOK)
        {
            log.Debug("There are " + items.Count + " menu items. Menu is healthy!");
        }
        else
        {
            log.Warn("Menu needs some menu items adding!");
        }

    }
}

И, наконец, конфигурация Spring

<!-- Scheduled Services using Quartz -->
  <!-- This section contains Quartz config that can be reused by all our Scheduled Tasks ---->  
  <!-- The Quartz scheduler factory -->
  <object id="quartzSchedulerFactory" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
    <!-- Tell Quartz to use our custom (context-aware) job factory -->
    <property name="JobFactory" ref="contextAwareJobFactory"/>

    <!-- Register the triggers -->
    <property name="triggers">
      <list>
        <ref object="frequentTrigger" />
      </list>
    </property>
  </object>  

  <!-- Funky new context-aware job factory -->
  <object name="contextAwareJobFactory" type="Munch.Service.ScheduledTasks.ContextAwareJobFactory" />

  <!-- A trigger that fires every 10 seconds (can be reused by any jobs that want to fire every 10 seconds) -->
  <object id="frequentTrigger" type="Spring.Scheduling.Quartz.CronTriggerObject, Spring.Scheduling.Quartz" lazy-init="true">
    <property name="jobDetail" ref="checkMenuIsHealthyJobDetail" />
    <property name="cronExpressionString" value="0/10 * * * * ?" />
  </object>  

  <!-- Now the job-specific stuff (two object definitions per job; 1) the job and 2) the job detail) --> 
  <!-- Configuration for the 'check menu is healthy job' -->
  <!-- 1) The job -->
  <object name="checkMenuIsHealthyJob" type="Munch.Service.ScheduledTasks.CheckMenuIsHealthyJob" singleton="false">
    <property name="menuService" ref="menuService"/>
  </object>

  <!-- 2) The job detail -->
  <object name="checkMenuIsHealthyJobDetail" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
    <property name="JobType" value="Munch.Service.ScheduledTasks.CheckMenuIsHealthyJob"/>
    <property name="JobDataAsMap">
      <dictionary>
        <entry key="HowManyMenuItemsIsOK" value="20" />
      </dictionary>
    </property>    
  </object>
1 голос
/ 26 сентября 2011

Вы можете внедрить свойство / конструктор в свою работу, переместив CreateJobInstance из AdaptableJobFactory и зарегистрируя свой новый JobFactory вместо используемого по умолчанию.

Переданный в TriggerFiredBundle обеспечиваету вас достаточно информации, чтобы запросить контекст для соответствующей работы (на основе соглашений).bundle.JobDetail.JobType.Name и bundle.JobDetail.JobType соответствовали моим потребностям, поэтому в 2008 году я закончил с sth.вот так (класс является производной формой AdaptableJobFactory и реализует IApplicationContextAware для ввода контекста):

public class ContextAwareJobFactory : AdaptableJobFactory, IApplicationContextAware
{
  private IApplicationContext m_Context;

  public IApplicationContext ApplicationContext
  {
    set
    {
      m_Context = value;
    }
  }

  protected override object CreateJobInstance( TriggerFiredBundle bundle )
  {
    return m_Context.GetObject( bundle.JobDetail.JobType.Name, bundle.JobDetail.JobType );
  }
}

Вам необходимо зарегистрировать ContextAwareJobFactory, используя следующую конфигурацию:

<objects xmlns="http://www.springframework.net">
  <!-- Some simple dependency -->
  <object name="SomeDependency" type="Namespace.SomeDependency, Assembly" />

  <!-- The scheduled job, gets the dependency. -->
  <object name="ExampleJob" type="Namespace.ExampleJob, Assembly" singleton="false">
    <constructor-arg name="dependency" ref="SomeDependency"/>
  </object>

  <!-- The JobDetail is configured as usual. -->
  <object name="ExampleJobDetail" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
    <property name="JobType" value="Namespace.ExampleJob, Assembly"/>        
  </object>

  <!-- The new JobFactory. -->
  <object name="ContextAwareJobFactory" type="Namespace.ContextAwareJobFactory, Assembly" />

  <!-- Set the new JobFactory onto the scheduler factory. -->
  <object id="quartzSchedulerFactory" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
    <property name="JobFactory" ref="ContextAwareJobFactory"/>
  </object>      
</objects>

Я не знаю, есть ли что-нибудь.ootb, так как это было разработано в 2008 году, и я не следил за прогрессом интеграции, достигнутым для quartz.net.

...