web-dev-qa-db-ja.com

Springでスケジュールされたジョブを条件付きで有効または無効にする方法は?

@Scheduledアノテーションを使用して、Springでcronスタイルパターンでスケジュールジョブを定義しています。

Cronパターンは、構成プロパティファイルに保存されます。実際には、2つのプロパティファイルがあります。1つはデフォルトの構成、もう1つは環境に依存するプロファイル構成(例:dev、test、prod customer 1、prod customer 2など)であり、デフォルト値の一部をオーバーライドします。

SpringコンテキストでプロパティプレースホルダーBeanを構成し、${}スタイルプレースホルダーを使用してプロパティファイルから値をインポートできるようにしました。

ジョブBeanは次のようになります。

@Component
public class ImagesPurgeJob implements Job {

    private Logger logger = Logger.getLogger(this.getClass());

    @Override
    @Transactional(readOnly=true)
    @Scheduled(cron = "${jobs.mediafiles.imagesPurgeJob.schedule}")
    public void execute() {
        //Do something
            //can use DAO or other autowired beans here
    }
}

コンテキストXMLの関連部分:

<!-- Enable configuration of scheduled tasks via annotations -->
    <task:annotation-driven/>

<!-- Load configuration files and allow '${}' style placeholders -->
    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:config/default-config.properties</value>
                <value>classpath:config/environment-config.properties</value>
            </list>
        </property>
        <property name="ignoreUnresolvablePlaceholders" value="true"/>
        <property name="ignoreResourceNotFound" value="false"/>
    </bean>

私は本当にこれが好きです。最小限のXMLで非常にシンプルでクリーンです。

ただし、もう1つ要件があります。これらのジョブの一部は、場合によっては完全に無効にすることができます。

したがって、Springを使用してそれらを管理する前に、手動で作成し、設定ファイルにcronパラメータとともにブールパラメータがあり、ジョブを有効にする必要があるかどうかを指定します:

jobs.mediafiles.imagesPurgeJob.enable=true or false
jobs.mediafiles.imagesPurgeJob.schedule=0 0 0/12 * * ?

この設定パラメータに応じて、Springでこのパラメータを使用して条件付きでBeanを作成するか、Beanを単に無視するにはどうすればよいですか?

明らかな回避策の1つは、評価されないcronパターンを定義して、ジョブが実行されないようにすることです。しかし、Beanはまだ作成され、構成は少し不明瞭になるため、より良い解決策が必要だと感じています。

56
Pierre Henry
@Component
public class ImagesPurgeJob implements Job {

    private Logger logger = Logger.getLogger(this.getClass());

    @Value("${jobs.mediafiles.imagesPurgeJob.enable}")
    private boolean imagesPurgeJobEnable;

    @Override
    @Transactional(readOnly=true)
    @Scheduled(cron = "${jobs.mediafiles.imagesPurgeJob.schedule}")
    public void execute() {

         //Do something
        //can use DAO or other autowired beans here
        if(imagesPurgeJobEnable){

            Do your conditional job here...

        }
    }
}
38
Prabhakaran

Spring Bootは @ ConditionalOnProperty を提供します。これは、Spring Bootを使用している場合に最適です。この注釈は、Spring 4.0.0で導入された @ Conditional の特殊化です。

Spring Bootではなく「通常の」スプリングを使用していると仮定すると、Spring Bootの@ConditionalOnPropertyを模倣する@Conditionalで使用する独自の条件実装を作成できます。

27
tmullin

条件ごとにスケジュールメソッドをいくつかのサービスにグループ化し、次のように初期化できます。

@Service
@ConditionalOnProperty("yourConditionPropery")
public class SchedulingService {

@Scheduled
public void task1() {...}

@Scheduled
public void task2() {...}

}
24
Oleg

プロパティから@EnableSchedulingを切り替える場合は、@ EnableSchedulingアノテーションを構成クラスに移動し、次のように@ConditionalOnPropertyを使用して、Spring Bootでこれを行うことができます。

@Configuration
@EnableScheduling
@ConditionalOnProperty(prefix = "com.example.scheduling", name="enabled", havingValue="true", matchIfMissing = true)
public class SchedulingConfiguration {

}

これにより、アプリケーションのスケジューリングが無効になります。これは、アプリケーションの起動方法に応じて、アプリケーションを1回またはスケジュールして実行できるようにする場合に役立ちます。

ここに関するウィルキンソナのコメントから: https://github.com/spring-projects/spring-boot/issues/12682

6
user3474985

あなたの質問は、Beanの実際の作成を調整することを示しています。少なくともSpring 3.1を使用している場合は、@ Profileを使用して、このパラメーターを使用して簡単にこれを行うことができます。

こちらのドキュメントを参照してください: http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/context/annotation/Profile.html

4
aweigold
@Component
public class CurrencySyncServiceImpl implements CurrencySyncService {

    private static Boolean isEnableSync;
    /**
     * Currency Sync FixedDelay in minutes
     */
    private static Integer fixedDelay;

    @Transactional
    @Override
    @Scheduled(fixedDelayString = "#{${currency.sync.fixedDelay}*60*1000}")
    public void sync() {
        if(CurrencySyncServiceImpl.isEnableSync) {
            //Do something
            //you can use DAO or other autowired beans here.
        }
    }

    @Value("${currency.sync.fixedDelay}")
    public void setFixedDelay(Integer fixedDelay) {
        CurrencySyncServiceImpl.fixedDelay = fixedDelay;
    }

    @Value("${currency.sync.isEnable}")
    public void setIsEnableSync(Boolean isEnableSync) {
        CurrencySyncServiceImpl.isEnableSync = isEnableSync;
    }
}
2
Vinit Solanki

条件に基づいてBeanを作成し、そのBeanにScheduledメソッドを含めることもできます。

@Component
@Configuration
@EnableScheduling
public class CustomCronComponent {
    @Bean
    @ConditionalOnProperty(value = "my.cron.enabled", matchIfMissing = true, havingValue = "true")
    public MyCronTask runMyCronTask() {
        return new MyCronTask();
    }
}

そして

@Component
public class MyCronTask {
    @Scheduled(cron = "${my.cron.expression}")
    public void run() {
        String a = "";
    }
}
0
labm0nkey

私の答えはハックであることは知っていますが、実行されない有効なcron式を指定すると、(環境固有の構成で)問題が解決する場合があります Quartz:実行されないCron式

0