3

I have a javafx.concurrent.Task that run some code in background and use the java.util.logging.Logger to give information about its status. I need to show this log entry in the UI in the main thread. how can I do this?

this is a simple toy project I've made to solve the problem out of the context

@Override
public void start(Stage primaryStage) {


    ListView<String> list = new ListView<>();
    final ObservableList<String> items =FXCollections.observableArrayList ();
    list.setItems(items);

    Task<String> task = new Task<String>() {

        @Override
        protected String call() throws Exception {
            doStuff();
            return "yey";
        }
    };

    new Thread(task).start();



    Scene scene = new Scene(list, 300, 250);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
}

private void doStuff() {
    for (int i=0;i<10;i++) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            Logger.getLogger("LoggerUI").log(Level.INFO, "error");
        }
        Logger.getLogger("LoggerUI").log(Level.SEVERE, "whatever");
    }

[...]
}

I've tried this but it doesn't work

public class LoggerUI extends Application {

@Override
public void start(Stage primaryStage) {
    System.out.println("UI"+ Thread.currentThread().getId());


    ListView<String> list = new ListView<>();
    final ObservableList<String> items =FXCollections.observableArrayList ();
    list.setItems(items);

    Logger.getLogger("LoggerUI").addHandler(new Handler() {

        @Override
        public void publish(LogRecord lr) {
            System.out.println("publish()"+ Thread.currentThread().getId());

            items.add(lr.getMessage());
        }

        @Override
        public void flush() {
            System.out.println("flush");
        }

        @Override
        public void close() throws SecurityException {
            System.out.println("close");

        }
    });

    Task<String> task = new Task<String>() {

        @Override
        protected String call() throws Exception {
            doStuff();
            return "yey";
        }
    };

    new Thread(task).start();



    Scene scene = new Scene(list, 300, 250);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
}

private void doStuff() {

    System.out.println("doStuff()"+ Thread.currentThread().getId());
    for (int i=0;i<300;i++) {
        final int j =i;
        try {
            Thread.sleep(30);
        } catch (InterruptedException ex) {

            Logger.getLogger("LoggerUI").log(Level.INFO, "error");
        }

        Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    System.out.println("runLater()"+ Thread.currentThread().getId());
                    Logger.getLogger("LoggerUI").log(Level.SEVERE, "whatever" +j);
                }
            });
    }

   [..]

}
}

it shows the first 20-30th entries and then stop to update the UI

Sergey Grinev
  • 34,078
  • 10
  • 128
  • 141
lucaconlaq
  • 1,511
  • 4
  • 19
  • 36

1 Answers1

2

Update: It's not actually JavaFX issue, but java logging's one.

Store Logger into variable, because Loggers returned by Logger.getLogger() are not the same each time, they are cached, garbage collected and stuff.

private Logger logger = Logger.getLogger("LoggerUI");

and use as follows:

logger.addHandler(new Handler() { ... });

logger.log(Level.SEVERE, "whatever" +j);

Also, I would advise to move Platform.runLater() call to publish() methods, so your logger will work from any thread.

Sergey Grinev
  • 34,078
  • 10
  • 128
  • 141
  • in the second example I'm actually using Platform.runLater() – lucaconlaq Sep 09 '12 at 22:06
  • method `publish()` is called from `doStuff()` which is called from `new Thread().start()` which is not FX thread. – Sergey Grinev Sep 09 '12 at 22:41
  • at line 65 of the second example I use Platform.runLater() and then inside I call the logger. if you are referring to line 62 where I log "error" than it doesn't really matter because that line is never reached and this is a toy example. thanks for helping anyway – lucaconlaq Sep 10 '12 at 08:02
  • I see now, I was wrong about root cause of your problem. See updated answer – Sergey Grinev Sep 10 '12 at 10:04
  • thank you very much! I think you're totally right, I'll try tonight when I'll get home and I'll accept the answer :) – lucaconlaq Sep 10 '12 at 11:47