2

I have a javaFX application and I'm having a logging problem. I can't figure out how to dynamically output logs to a TextArea in JavaFX and to a file at the same time.

For the file I have this setup:

handlers = java.util.logging.FileHandler, java.util.logging.ConsoleHandler

java.util.logging.FileHandler.level     = ALL
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.FileHandler.append    = true
java.util.logging.FileHandler.pattern   = log.txt

And in each class such static initialization:

public class BuildTest{
static {
        try(FileInputStream ins = new FileInputStream("src/main/resources/log.config")) {
            LogManager.getLogManager().readConfiguration(ins);
            LOGGER = Logger.getLogger(BuildTest.class.getName());
            initialContext = new InitialContext();
        } catch (NamingException | IOException e) {
            LOGGER.log(Level.WARNING,"Error ", e);
        }
    }
}

But I have a problem, how can I also output to the TextArea at the same time?

The TextArea itself:

<TextArea layoutX="20.0" layoutY="705.0" prefHeight="100.0" prefWidth="560.0" fx:id="LogID"/>

And the controller is attached to the fxml file:

public class ControllerFrame {

    private TextArea LogID;

static {
        try(FileInputStream ins = new FileInputStream("src/main/resources/log.config")){
            LogManager.getLogManager().readConfiguration(ins);
            LOGGER = Logger.getLogger(ControllerFrame .class.getName());
        } catch (Exception e) {
            LOGGER.log(Level.WARNING,"Error ", e);
        }
    }
}

I tried to insert this code into both the static method and the initialize method in the controller class:

TextAreaHandler handler = new TextAreaHandler(textArea);
        handler.setFormatter(new SimpleFormatter());
        LOGGER.addHandler(handler);

Implementing the TextAreaHandler class:

package sample;

import java.util.logging.ErrorManager;
import java.util.logging.Handler;
import java.util.logging.LogRecord;

import javafx.application.Platform;
import javafx.scene.control.TextArea;

public class TextAreaHandler extends Handler {

    private final TextArea textArea;
    private volatile boolean open = true;

    public TextAreaHandler(TextArea textArea) {
        this.textArea = textArea;
    }

    @Override
    public void publish(LogRecord record) {
        if (open && isLoggable(record)) {
            String message;
            try {
                message = getFormatter().format(record);
            } catch (Exception ex) {
                reportError(null, ex, ErrorManager.FORMAT_FAILURE);
                return;
            }

            if (Platform.isFxApplicationThread()) {
                appendMessage(message);
            } else {
                try {
                    Platform.runLater(() -> appendMessage(message));
                } catch (Exception ex) {
                    reportError(null, ex, ErrorManager.GENERIC_FAILURE);
                }
            }
        }
    }

    private void appendMessage(String message) {
        try {
            textArea.appendText(message);
        } catch (Exception ex) {
            reportError(null, ex, ErrorManager.GENERIC_FAILURE);
        }
    }

    @Override
    public void flush() {
        // no buffer
    }

    @Override
    public void close() {
        open = false;
    }
}

But I still don't get logs in the TextArea. The very essence is that the application displays logs both in a text file and in a TextArea

Vanish
  • 57
  • 6
  • This is not a duplicate, as they asked to recreate, since the condition is different – Vanish Jun 18 '23 at 22:39
  • If you repost, you shouldn't delete the old question (assuming you did). If you do, then all context and comments or answers on the old post are lost. – jewelsea Jun 19 '23 at 04:58
  • You should provide a [mcve] so your question can be replicated by copy and paste with no change or addition, otherwise you are requesting potential answerers to do more work to verify a possible soultion. – jewelsea Jun 19 '23 at 04:59
  • Appending text to a text area via run later for each record won't scale very well. It will me OK for a short, light volume logs. – jewelsea Jun 19 '23 at 05:02
  • Unrelated: see [how to access resource from a JavaFX app](https://stackoverflow.com/questions/61531317/how-do-i-determine-the-correct-path-for-fxml-files-css-files-images-and-other). – jewelsea Jun 19 '23 at 05:06
  • this is a reproducible example, but logging to the TextArea does not work, that's why I started this question – DarkSoul Jun 19 '23 at 06:05
  • your link to another question does not answer my problem – DarkSoul Jun 19 '23 at 06:06
  • Can't you get the log data as a `String` and write that to the `TextField` and to a text file? – SedJ601 Jun 19 '23 at 06:25
  • But how to transfer the log data to a String, and then dynamically add it to the TextArea? – Vanish Jun 19 '23 at 07:22
  • Don't you want to have the `Exception` data as a `String`? Isn't that what you are writing to the log file? Why not write the `Exception` string to the `TextArea` and then write it to the log file? – SedJ601 Jun 19 '23 at 09:50
  • I also have the usual method processing, that is, successful, not Exception. And even if you write only Exception, then how to make it dynamic? And how to enter the data from the logger into the TextArea if the output of the logger goes through the line: LOGGER.log(Level.WARNING,"Error ", e); – Vanish Jun 19 '23 at 10:00
  • 1
    Although you indicate that it "is not a duplicate", see also [_How to display log in JavaFX TextArea?_](https://stackoverflow.com/q/76488986/230513). – trashgod Jun 19 '23 at 17:16
  • I unsubscribed in the comments in the question why I created this question – Vanish Jun 19 '23 at 17:49
  • 2
    You should provide a [mre]. We'd have to make assumptions about your current code to make it work. There are also a few things that don't seem complete, such as missing `@FXML` annotations. You also don't show how you actually add the `TextAreaHandler` to your logger (you have a copy-paste from your previous question, but that doesn't match your own code). – Slaw Jun 19 '23 at 19:02
  • 1
    Note you should not be reading a resource with `FileInputStream`. A resource is not a file, particularly once it's packaged in a JAR file or JRT image. Use the standard resource API to read the configuration file: `Class#getResourceAsStream(String)`. That also means you need to use `"/log.config"`, as the package `"src/main/resources"` does not exist on the class-path. – Slaw Jun 19 '23 at 19:04
  • 2
    @trashgod I believe "Vanish" (the account that asked this question) and "DarkSoul" (the account that asked the question you linked) are the same person. The question you linked was answered, but the OP seems to be having additional issues, so I suggested they ask a new question. – Slaw Jun 19 '23 at 19:06
  • 1
    Vanish, note I've updated the `TextAreaHandler` code from my answer to your other question to make it more robust (addressing concerns brought up by @jewelsea). These changes won't fix the problem you're having in this question, however. – Slaw Jun 19 '23 at 19:42

0 Answers0