title: Most efficient way to log messages to JavaFX TextArea via threads with simple custom logging frameworks
body: <p>I have a simple custom logging framework like this:</p>
  
  <pre><code>package something;
  
  import javafx.scene.control.TextArea;
  
  public class MyLogger {
      public final TextArea textArea;
  
      private boolean verboseMode = false;
      private boolean debugMode = false;
  
      public MyLogger(final TextArea textArea) {
          this.textArea = textArea;
      }
  
      public MyLogger setVerboseMode(boolean value) {
          verboseMode = value;
          return this;
      }
  
      public MyLogger setDebugMode(boolean value) {
          debugMode = value;
          return this;
      }
  
      public boolean writeMessage(String msg) {
          textArea.appendText(msg);
          return true;
      }
  
      public boolean logMessage(String msg) {
          return writeMessage(msg + "\n");
      }
  
      public boolean logWarning(String msg) {
          return writeMessage("Warning: " + msg + "\n");
      }
  
      public boolean logError(String msg) {
          return writeMessage("Error: " + msg + "\n");
      }
  
      public boolean logVerbose(String msg) {
          return verboseMode ? writeMessage(msg + "\n") : true;
      }
  
      public boolean logDebug(String msg) {
          return debugMode ? writeMessage("[DEBUG] " + msg + "\n") : true;
      }
  }
  </code></pre>
  
  <p>Now what I want to do is to extend it so that it would be able to properly handle logging of messages via threads. I have tried solutions like <a href="https://stackoverflow.com/questions/22772379/updating-ui-from-different-threads-in-javafx">using message queues with an AnimationTimer</a>. It works but it slows the GUI down.</p>
  
  <p>I also tried using a <a href="http://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/ScheduledService.html" rel="noreferrer">scheduled service</a> which runs a thread that reads messages from the message queue, concatenates them, and appends them to TextArea (<code>textArea.appendText(stringBuilder.toString())</code>). The problem is that the TextArea control goes unstable i.e. you had to highlight all texts with <code>Ctrl-A</code> and try resizing the window to make them appear well. There are also some of them being displayed in a light-blue background not sure what's causing it. My first guess here is that the race condition may not be allowing the control to update itself well from the new strings. It is also worth noting that the textarea is wrapped around a ScrollPane so it adds the confusion if TextArea is actually the one having the problem or ScrollPane. I have to mention as well that this approach doesn't make the TextArea control update itself with messages quickly.</p>
  
  <p>I thought about <code>binding</code> <code>TextArea.TextProperty()</code> to something that does the update but I'm not sure how I would do that properly knowing that the gatherer of messages (be it by a service or a lone thread) would still be running different from the GUI thread.</p>
  
  <p>I have tried to look up on other known logging framework solutions like log4j and some stuffs referred <a href="https://stackoverflow.com/questions/5950557/good-examples-using-java-util-logging">here</a> but none of them seems to give an apparent approach to logging via threads to TextArea. I also don't like the idea of building my logging system on top of them as they already have their pre-defined mechanisms like logging level, etc.</p>
  
  <p>I've seen <a href="https://stackoverflow.com/questions/10785560/write-logger-message-to-file-and-textarea-while-maintaining-default-behaviour-in">this</a> as well. It implies using <code>SwingUtilities.invokeLater(Runnable)</code> to update the control but I already tried a similar approach using <code>javafx.application.platform.runLater()</code> which gets executed on the worker thread. I'm not sure if there was something I was doing wrong but it just hangs. It can produce messages but not when they're aggressive enough. I estimate that the worker thread running in a purely synchronous fashion can actually produce about 20 or more average lines per second and more when it's in debug mode. A possible workaround would be to add message queueing to it as well but that doesn't make sense anymore.</p>