Planifier une tâche à une heure précise dans JFinal avec cron4j

![CDATA[

Pour exécuter une action à un moment donné dans une application JFinal, le plugin Cron4jPlugin permet d'enregistrer des tâches planifiées via la syntaxe cron de la bibliothèque cron4j. La mise en place compernd l'ajout de la dépendance Maven, l'activation du support asynchrone du filtre JFinal sous Tomcat, puis l'enregistrement de la tâche dans la méthode configPlugin.

Dépendance Maven

Ajoutez dans votre pom.xml :

<dependency>
    <groupId>it.sauronsoftware.cron4j</groupId>
    <artifactId>cron4j</artifactId>
    <version>2.2.5</version>
</dependency>

Support asynchrone du filtre Tomcat

Dans web.xml, positionnez le filtre JFinal comme suit :

<filter>
    <filter-name>jfinal</filter-name>
    <filter-class>com.jfinal.core.JFinalFilter</filter-class>
    <async-supported>true</async-supported>
    <init-param>
        <param-name>configClass</param-name>
        <param-value>com.example.jfinal.config.AppConfig</param-value>
    </init-param>
</filter>

Configurtaion du plugin

Dans la classe héritant de JFinalConfig, instanciez le scheduler et ajoutez votre job :

@Override
public void configPlugin(Plugins plugins) {
    PropKit.use("jdbc.properties");

    Cron4jPlugin scheduler = new Cron4jPlugin();
    scheduler.addTask("0 0 * * *", () -> {
        LogArchiveJob.runArchive();
    });
    plugins.add(scheduler);
}

L'expression 0 0 * * * déclenche le traitement tous les jours à minuit.

Exemple de job planifié

Le service ci-dessous archive les anciens logs lors du déclenchemnet. Il utilise ActiveRecord de JFinal et un logger SLF4J plutôt que System.out.

package com.example.jfinal.job;

import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogArchiveJob {
    private static final Logger logger = LoggerFactory.getLogger(LogArchiveJob.class);
    private static final String CONFIG_KEY = "log.archive.enabled";
    private static final int COMPANY_ID = 130;

    public static void runArchive() {
        logger.info("Démarrage de l'archivage des logs");

        if (!isArchivingEnabled()) {
            logger.info("L'archivage automatique est désactivé");
            return;
        }

        Record oldestLog = findOldestPendingLog();
        if (oldestLog == null) {
            logger.info("Aucun log en attente d'archivage");
            return;
        }

        markLogsAsArchived(oldestLog.getLong("batch_id"));
        insertArchiveEntry(oldestLog);
        logger.info("Archivage terminé");
    }

    private static boolean isArchivingEnabled() {
        String value = Db.queryStr(
            "SELECT pvalue FROM app_config WHERE pkey = ? AND company_id = ?",
            CONFIG_KEY, COMPANY_ID
        );
        return "1".equals(value) || "true".equalsIgnoreCase(value);
    }

    private static Record findOldestPendingLog() {
        String sql = "SELECT batch_id, MIN(created_at) AS created_at " +
                     "FROM system_logs WHERE company_id = ? AND archived = 0 " +
                     "GROUP BY batch_id ORDER BY batch_id ASC LIMIT 1";
        return Db.findFirst(sql, COMPANY_ID);
    }

    private static int markLogsAsArchived(Long batchId) {
        if (batchId == null) {
            return 0;
        }
        String sql = "UPDATE system_logs SET archived = 1, archived_at = NOW() " +
                     "WHERE company_id = ? AND batch_id = ? AND archived = 0";
        return Db.update(sql, COMPANY_ID, batchId);
    }

    private static void insertArchiveEntry(Record source) {
        String sql = "INSERT INTO log_archive_history (company_id, batch_id, archived_at) VALUES (?, ?, NOW())";
        int rows = Db.update(sql, COMPANY_ID, source.getLong("batch_id"));
        if (rows > 0) {
            logger.info("Entrée d'archive créée pour le batch {}", source.getLong("batch_id"));
        } else {
            logger.warn("Échec de la création de l'entrée d'archive");
        }
    }
}

]]>

Étiquettes: JFinal cron4j Tomcat Maven ActiveRecord

Publié le 1 juillet à 23h58