Scheduling: "Quartz" verwenden, Hilfe bei Umstellung

internet

Top Contributor
Hallo zusammen,

ich nutze derzeit die Mittel von JAVA EE / Jakarta EE für das Scheduling.
Ich sehe aber mit Quartz hat man dennoch mehr Möglichkeiten, auch renne die derzeit in Transaction - Probleme, die eventuell mit Quartz Geschichte sind.

Aktuell habe ich bereits eine Datenbank - Tabelle, die mir den Status des Schedules, geplantes Ausführungsdatum etc. speichert.
Daher benötige ich nicht die Option eine weitere DB - Tabelle für Quartz zu erstellen.

Derzeit habe ich ein Java EE Schedule, der jede Minute läuft und eine Datenbank - Abfrage macht, ob es ausstehende Schedules gibt.

Nun wäre meine Idee „Quartz“ zu nutzen.
Meine Idee ist nun:
  • Beim Hochfahren des Servers per Quartz alle Schedules erstellen, die aus der Tabelle „Schedule“ ausstehend und eingeplant sind.
  • Den Java EE Schedule, der aktuell jede Minute läuft und prüft, ob es ausstehende Schedules gibt, kann ich mir damit sparen.

Nun habe ich folgende Fragen:

  • Passt der Switch zu Quartz mit dem aktuellen Konzept / Setup?
  • Inwiefern muss der Code geändert werden um auf Quartz umzustellen? Hat hier vielleicht jemand Erfahrungen?
    • Vielleicht hat jemand ein einfaches Beispiel für den Schedule und dann die Ausführung?
  • Benötige ich dann ebenfalls, denn dies benötige ich wohl für Apache Shiro
  • Java:
    Runnable myRunnable = new Runnable() {
                    @Override
                    public void run() {
                        try {
                              .....

Hier der Code, den ich aktuell verwende für Java EE:

Code:
@Singleton
@LocalBean
@Startup
public class Scheduler {

@PostConstruct
    public void init() {
        // Check outstanding Schedules...
        
          startSchedule();
     }
    
     /**
     * Create Schedule
     *
     * @throws Exception
     */
    public void startSchedule() {

            ScheduleExpression scheduleExpression = new ScheduleExpression();
            scheduleExpression.minute("*/1").hour("*");

            TimerConfig timerConfig = new TimerConfig();
            timerConfig.setPersistent(false);

            timerService.createCalendarTimer(scheduleExpression, timerConfig);

            execute();
    }
    
    @Timeout
    @AccessTimeout(value = 20, unit = TimeUnit.MINUTES)
    public void execute() throws Exception {

            // Globale Einstellungen laden und prüfen, ob der ScheduleService aktiv ist
            Object objectScheduleActive = applicationSettingsStoredBean
                    .findValue(ApplicationSettingConstants.SCHEDULE_ACTIVE);

            if (objectScheduleActive == null)
                return;

            scheduleIsActive = (boolean) objectScheduleActive;

            if (scheduleIsActive == false) {
                LOGGER.warn("Scheduler is currently not active...");
                return;
            }

            if (currentlyRunning) {
                LOGGER.warn("Scheduler is currently running...");
                return;
            }

            if (schedulingService == null)
                schedulingService = new SchedulingService();

            currentlyRunning = true;

            /**
             * Alle noch nicht ausgeführten Schedules bekommen
             */
            List<ScheduleExecution> scheduleExecutionList = scheduleExecutionService
                    .findAllScheduleExecutionOutstanding();

            if (scheduleExecutionList == null || scheduleExecutionList.size() == 0) {
                LOGGER.info("NO PLANNED SCHEDULES FOUND");
                currentlyRunning = false;
                return;
            }

            for (ScheduleExecution scheduleExecution : scheduleExecutionList) {

                // Hinzufügen zur Liste der Ausführungen
                addScheduleToList(scheduleExecution);
            }

            currentlyRunning = false;
        }
    }

    /**
     * Add Schedule to List
     *
     * @param scheduleExecution
     * @throws UnknownHostException
     */
    private void addScheduleToList(ScheduleExecution scheduleExecution) throws UnknownHostException {

        synchronized (this) {

            // generate a taskID and store them for further use
            String taskId = RandomStringUtils.randomAlphanumeric(20);
            scheduleExecution.setProcessId(taskId);

            // Dispatcher Name speichern
            String hostname = SessionInformationHelper.getHostName();
            scheduleExecution.setDispatcherName(hostname);

           // Apache Shiro
            Subject subject = permissionSystemUserServiceStoredBean.getSystemUser();

            Runnable myRunnable = new Runnable() {
                @Override
                public void run() {
                    try {

                        // Add tasks
                        executeAction(scheduleExecution);

                        ////// STATUS UPDATEN ///////
                        scheduleExecution.setEndExecutionDate(LocalDateTime.now());

                        // Uhrzeit berechnen
                        if (scheduleExecution.getStartExecutionDate() != null) {
                            Duration duration = Duration.between(scheduleExecution.getStartExecutionDate(),
                                    scheduleExecution.getEndExecutionDate());
                            scheduleExecution.setExecutionTimeMilliSeconds(duration.toMillis());
                            double milliToSecond = duration.toMillis();
                            scheduleExecution.setExecutionTimeSeconds(milliToSecond / 1000);
                        }

                        scheduleExecution.setStatus(ScheduleExecution.Status.DONE.toString());
                        scheduleExecutionService.updateScheduleExecution(scheduleExecution);

                        //// Hier werden die nächsten ScheduleExecution Termine festgelegt /////
                        createInterval(scheduleExecution);

                    } catch (Exception e) {

                        // IssueLog erstellen und Status auf Failed setzen
                        createIssueMessage(e, scheduleExecution);

                        //// Hier werden die nächsten ScheduleExecution Termine festgelegt /////
                        try {

                            // TODO, prüfen, ob die letzte Male erfolgreich gelaufen, wenn nein, dann
                            // Interval deaktivieren
                            createInterval(scheduleExecution);

                        } catch (Exception e2) {

                        }

                        // TODO ausstellen, damit nicht in LOG File
                        LOGGER.error(ExceptionUtils.getFullStackTrace(e));

                    }
                }
            };

            // Apache Shiro
            myRunnable = subject.associateWith(myRunnable);

            //////
            schedulingService.addTaskToExecutor(taskId, myRunnable, 0);
        }

    }

Danke für jede Hilfe
 
Hast du wirklich Probleme mit JEE? Ich würde versuchen diese zu lösen. Ich sehe mit aktuellen JEE Versionen keinen Vorteil durch eine 3rd Party Lib wie Quartz.
 
Hast du wirklich Probleme mit JEE? Ich würde versuchen diese zu lösen. Ich sehe mit aktuellen JEE Versionen keinen Vorteil durch eine 3rd Party Lib wie Quartz.
Ich bin vor kurzem in ein Problem gerannt, bei dem wohl gleichzeitig mehrmals versucht wird ein Objekt in einem Thread zu aktualisieren in der Datenbank.... Ich habe leider die Fehlermeldung nicht mehr... Vllt. finde ich in den Logs noch was....

Bei Quartz kann man wohl auch einstellen, dass ein entsprechender Job auch nur 1x laufen darf.
Insgesamt scheint mir die Quartz API verständlicher zu sein...

Quartz scheint mir recht einfach zu sein...
Wie es mir scheint ist aber auch ein Scheduler, der jede Minute läuft Quatsch (Scheduler macht eine Abfrage gegen die DB und prüft, welche eingeplanten Schedules aus der DB noch nicht gelaufen sind).
Wäre es nicht besser, dass beim Hochfahren der Applikation initial eine Abfrage gegen die DB gemacht wird und einen Job (Schedule-Job) erstellt wird mit der entsprechenden Uhrzeit etc., anstatt jede Minute dies zu prüfen?

Man müsste dann eben nur sicherstellen, dass wenn man einen Schedule aus der DB ändert, dass die Änderung in dem Objekt von Quartz (Schedule-Job - Objekte) dann ebenfalls angepasst wird / gelöscht wird....

Gibt es hier Leute, die Quartz schon Mal verwendet haben?
 
Ich habe Quartz schon oft verwendet. Vermutlich verwendet JEE im Hintergrund, ja nach Implementierung, auch Quartz. Wenn ich deinen Text so lese frage ich mich aber, ob du überhaupt eine Vorstellung davon hast.
Du erstellst einen Job/Trigger usw., dieser wird geplant und zur geplanten Zeit ausgeführt - wenn du diese Variante verwendest. Wenn diese Planung einen Neustart überleben soll, dann musst du einfach den Vorgang persistent machen und nicht nur im Speicher halten. Quartz wird dann beim Neustart die unerledigten Jobs ausführen - falls das so eingestellt ist. Da muss man nichts nachschauen, alle 1 Minute usw.. Auch Kollisionen von Jobs kann man vermeiden. Die Möglichkeiten und Einstellungen sind so vielfältig, dass die Quartz-Leute eine Anleitung dafür erstellt haben. Man muss das aber auch lesen, nicht einfach irgendwas basteln!
 

Zurück
Oben