0

I'm trying to use a javafx alert in a task schedule in quartz:

public class ChecarJob implements Job{
    private Connection con;
    public ChecarJob() {
        this.con = new ConnectionFactory().getConnection();
    }
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Executou!");
                try {
                    String verStatus = "SELECT COUNT(*) FROM equipamento_requisicao";
                    PreparedStatement stmt = con.prepareStatement(verStatus);
                        ResultSet rsStatus = stmt.executeQuery();
                        if(rsStatus.next()){
                        Alerts a = new Alerts();
                        int Resultado = rsStatus.getInt(1);
                        if(Resultado>Sessao.getInstancia().getQtdRegistroBD()){
                        Sessao.getInstancia().setQtdRegistroBD(Resultado);
                                                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                        alert.setTitle("SUCESS");
                        alert.setHeaderText("SUCESS");
                        alert.setContentText("SUCESS");
                        alert.showAndWait();
                        }
                        else if(Resultado<Sessao.getInstancia().getQtdRegistroBD()){
                        Alert alert = new Alert(Alert.AlertType.INFORMATION);
                        alert.setTitle("FAIL");
                        alert.setHeaderText("FAIL");
                        alert.setContentText("FAIL");
                        alert.showAndWait();
                        Sessao.getInstancia().setQtdRegistroBD(Resultado);
                        } 
                        else{
                        //aq não irei fazer nada.
                        }
                        }
                    }catch (Exception e) {
            e.printStackTrace();
                    }
    }   

}

calling in my main class:

public void start(Stage stage) throws Exception {
    JobDetail j = JobBuilder.newJob(ChecarJob.class).build();
    Trigger t = TriggerBuilder.newTrigger().withIdentity("CroneTrigger")
            .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(60).repeatForever()).build();
    Scheduler s = StdSchedulerFactory.getDefaultScheduler();
    s.start();
    s.scheduleJob(j,t);

msg do error:

java.lang.IllegalStateException: Not on FX application thread; currentThread = DefaultQuartzScheduler_Worker-2Executou!

Vaibs
  • 2,018
  • 22
  • 29
  • 2
    Possible duplicate of [Why am I getting java.lang.IllegalStateException "Not on FX application thread" on JavaFX?](https://stackoverflow.com/questions/17850191/why-am-i-getting-java-lang-illegalstateexception-not-on-fx-application-thread) – Slaw Jul 14 '19 at 12:27
  • And https://stackoverflow.com/questions/29449297/java-lang-illegalstateexception-not-on-fx-application-thread-currentthread-t – Slaw Jul 14 '19 at 12:28
  • i try but not sucess :( maybe with timertask not problem . –  Jul 14 '19 at 14:08
  • Platform.runLater(new Runnable() { new Thread() { JobDetail j = JobBuilder.newJob(ChecarJob.class).build(); Trigger t = TriggerBuilder.newTrigger().withIdentity("CroneTrigger") .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(60).repeatForever()).build(); Scheduler s = StdSchedulerFactory.getDefaultScheduler(); s.start(); s.scheduleJob(j,t); }.start(); }); –  Jul 14 '19 at 14:08
  • can help mee pls? –  Jul 14 '19 at 14:09
  • Inside the job you need to execute the code that modifies the UI on the _JavaFX Application Thread_, and only the code that modifies the UI. – Slaw Jul 14 '19 at 14:10
  • u can help me with reply? i vote + please . I am new to java and do not understand much about threads –  Jul 14 '19 at 14:12

1 Answers1

1

JavaFX, like most UI toolkits, is single-threaded and not thread-safe. Once a scene graph is being displayed in a window, it must only be interacted with on the JavaFX Application Thread. And some objects must be instantiated on the FX thread. To do otherwise can lead to errors, as you've encountered, or just full on undefined behavior. If you're on a background thread and you need to schedule an action with the FX thread, you can use Platform.runLater(Runnable) (link is to the Javadoc).

Your code is not a minimal and complete example, so I can't be sure of what everything does. In general, however, I would start by moving all the code relating to Alert instances into a runLater call.

public void execute(JobExecutionContext context) throws JobExecutionException {
    System.out.println("Executou!");
    try {
        String verStatus = "SELECT COUNT(*) FROM equipamento_requisicao";
        PreparedStatement stmt = con.prepareStatement(verStatus);
        ResultSet rsStatus = stmt.executeQuery();
        if (rsStatus.next()) {
            Alerts a = new Alerts(); // what does this do?
            int Resultado = rsStatus.getInt(1);
            if (Resultado > Sessao.getInstancia().getQtdRegistroBD()) {
                Sessao.getInstancia().setQtdRegistroBD(Resultado); // unknown side-effects
                Platform.runLater(() -> {
                    Alert alert = new Alert(Alert.AlertType.INFORMATION);
                    alert.setTitle("SUCESS");
                    alert.setHeaderText("SUCESS");
                    alert.setContentText("SUCESS");
                    alert.showAndWait();
                });
            } else if (Resultado < Sessao.getInstancia().getQtdRegistroBD()) {
                Platform.runLater(() -> {
                    Alert alert = new Alert(Alert.AlertType.INFORMATION);
                    alert.setTitle("FAIL");
                    alert.setHeaderText("FAIL");
                    alert.setContentText("FAIL");
                    alert.showAndWait();
                });
                Sessao.getInstancia().setQtdRegistroBD(Resultado); // unknown side-effects
            } else {
                //aq não irei fazer nada.
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Some notes:

  • The above uses lambda expressions.
  • Don't forget to close resources (e.g. PreparedStatement, ResultSet) when done with them. Use try-with-resources.
  • The calls to runLater do not wait for the Runnable to return.
  • The "unknown side-effects" comments are there because I have no idea if those method invocations modify the UI. I've left them out of the runLater call on the assumption that they don't.
  • I couldn't find where Alerts a = new Alerts() is actually used.
  • The name Resultado does not follow standard Java naming conventions for local variables.
  • Notice that properly indenting your code makes it much easier to read and follow what is happening.

I am new to java and do not understand much about threads

Not having at least a basic understanding of concurrency in Java will hinder your efforts to create all but the most trivial of GUI applications. I highly recommend you study this topic before moving forward. As a start, read these:

Also, a good book on the topic is Java Concurrency in Practice by Brian Goetz et al.

Slaw
  • 37,820
  • 8
  • 53
  • 80
  • thanks I had forgotten to close stament and prepared These alerts I will use in case I have a new record added in the database so I do a routine every 10 minutes –  Jul 16 '19 at 21:27
  • and i found this for fix shutdown: stage.setOnCloseRequest(e -> { try { s.shutdown(); Platform.exit(); System.exit(0); } catch (SchedulerException ex) { Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex); } }); –  Jul 16 '19 at 21:27
  • I could not think very well how to overwrite the stop could you help me? –  Jul 16 '19 at 21:28