<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>It looks like you are manipulating a property that is bound to a
      UI control on an external thread.</p>
    <p>Property manipulations that are tied to controls that are part of
      an active (visible) Scene **must** be done on the FX thread.</p>
    <p>Try:</p>
    <div>    StreamingResponseHandler<AiMessage>
      streamingResponseHandler = new StreamingResponseHandler<>()
      {<br>
    </div>
    <div>                @Override<br>
    </div>
    <div>                public void onNext(String token) {<br>
                          Platform.runLater(() ->
      searchAction.appendAnswer(token));<br>
    </div>
    <div>                }<br>
    </div>
        }<br>
    <br>
    --John<br>
    <br>
    <div class="moz-cite-prefix">On 19/12/2023 09:14, Frank Delporte
      wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:18c81245644.d1c3bcab152400.4552689918614942273@webtechie.be">
      <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
      <div style="font-family: Verdana, Arial, Helvetica, sans-serif;
        font-size: 10pt;">
        <div class="zmail_extra" data-zbluepencil-ignore="true">
          <blockquote style="margin: 0px;" id="blockquote_zmail">
            <div>
              <div style="font-family : Verdana, Arial, Helvetica,
                sans-serif; font-size : 10pt;">
                <div>Hi, while experimenting with a ChatGPT-like user
                  interface, I found a crashing JVM with different types
                  of errors when streaming the response towards a
                  TextArea. This is probably caused by too fast
                  refreshes of the text as pieces of content are
                  received within the same milliseconds:<br>
                </div>
                <div><br>
                </div>
                <div>19/12/2023 08:51:57.874 |
                  DocsAnswerService                   |
                  onNext               | INFO     | Appending ' better'<br>
                </div>
                <div>19/12/2023 08:51:57.874 |
                  DocsAnswerService                   |
                  onNext               | INFO     | Appending '
                  performance'<br>
                </div>
                <div>19/12/2023 08:51:57.875 |
                  DocsAnswerService                   |
                  onNext               | INFO     | Appending ' after'<br>
                </div>
                <div>19/12/2023 08:51:57.978 |
                  DocsAnswerService                   |
                  onNext               | INFO     | Appending ' the'<br>
                </div>
                <div>19/12/2023 08:51:57.979 |
                  DocsAnswerService                   |
                  onNext               | INFO     | Appending ' first'<br>
                </div>
                <div>19/12/2023 08:51:57.979 |
                  DocsAnswerService                   |
                  onNext               | INFO     | Appending ' and'<br>
                </div>
                <div><br>
                </div>
                <div>But even when collecting this pieces of text to
                  e.g. minimum 255 characters to reduce the number of
                  TextArea changes, errors happen. So it's not clear how
                  to prevent this as I can't define the threshold to be
                  used...<br>
                </div>
                <div><br>
                </div>
                <div>Dummy code causing the crash:<br>
                </div>
                <div><br>
                </div>
                <div>public class SearchAction {<br>
                </div>
                <div>    private final StringProperty answer;<br>
                </div>
                <div>    ...<br>
                </div>
                <div>    public StringProperty getAnswerProperty() {<br>
                </div>
                <div>        return answer;<br>
                </div>
                <div>    }<br>
                </div>
                <div><br>
                </div>
                <div>    public void appendAnswer(String token) {<br>
                </div>
                <div>        this.answer.set(this.answer.getValue() +
                  token);<br>
                </div>
                <div>    }<br>
                </div>
                <div>}<br>
                </div>
                <div><br>
                </div>
                <div>TextArea lastAnswer = new TextArea();<br>
                </div>
                <div>lastAnswer.textProperty().bind(searchAction.getAnswerProperty());<br>
                </div>
                <div><br>
                </div>
                <div>StreamingResponseHandler<AiMessage>
                  streamingResponseHandler = new
                  StreamingResponseHandler<>() {<br>
                </div>
                <div>            @Override<br>
                </div>
                <div>            public void onNext(String token) {<br>
                </div>
                <div>                searchAction.appendAnswer(token);<br>
                </div>
                <div>            }<br>
                </div>
                <div>}<br>
                </div>
                <div><br>
                </div>
                <div><b>Fatal Error </b><br>
                </div>
                <div><br>
                </div>
                <div>#<br>
                </div>
                <div># A fatal error has been detected by the Java
                  Runtime Environment:<br>
                </div>
                <div>#<br>
                </div>
                <div>#  SIGBUS (0xa) at pc=0x000000013f53b630,
                  pid=13013, tid=80715<br>
                </div>
                <div>#<br>
                </div>
                <div># JRE version: OpenJDK Runtime Environment
                  Zulu21.30+15-CA (21.0.1+12) (build 21.0.1+12-LTS)<br>
                </div>
                <div># Java VM: OpenJDK 64-Bit Server VM Zulu21.30+15-CA
                  (21.0.1+12-LTS, mixed mode, sharing, tiered,
                  compressed oops, compressed class ptrs, g1 gc,
                  bsd-aarch64)<br>
                </div>
                <div># Problematic frame:<br>
                </div>
                <div># j 
javafx.scene.text.Text.queryAccessibleAttribute(Ljavafx/scene/AccessibleAttribute;[Ljava/lang/Object;)Ljava/lang/Object;+576
                  <a class="moz-txt-link-abbreviated" href="mailto:javafx.graphics@21.0.1">javafx.graphics@21.0.1</a><br>
                </div>
                <div>#<br>
                </div>
                <div># No core dump will be written. Core dumps have
                  been disabled. To enable core dumping, try "ulimit -c
                  unlimited" before starting Java again<br>
                </div>
                <div>#<br>
                </div>
                <div># An error report file with more information is
                  saved as:<br>
                </div>
                <div>#
                  /Users/frankdelporte/GitLab/docs-langchain4j/hs_err_pid13013.log<br>
                </div>
                <div>Exception in thread "JavaFX Application Thread"
                  java.lang.StackOverflowError: Delayed
                  StackOverflowError due to ReservedStackAccess
                  annotated method<br>
                </div>
                <div>at
javafx.graphics/com.sun.glass.ui.mac.MacAccessible.NSAccessibilityPostNotification(Native
                  Method)<br>
                </div>
                <div>at
javafx.graphics/com.sun.glass.ui.mac.MacAccessible.sendNotification(MacAccessible.java:816)<br>
                </div>
                <div>at
javafx.graphics/javafx.scene.Node.notifyAccessibleAttributeChanged(Node.java:10004)<br>
                </div>
                <div>at
javafx.graphics/javafx.scene.text.Text$TextAttribute$12.invalidated(Text.java:1847)<br>
                </div>
                <div>at
javafx.base/javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:113)<br>
                </div>
                <div>at
javafx.base/javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:148)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.text.Text.setCaretPosition(Text.java:961)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.text.Text$3.invalidated(Text.java:466)<br>
                </div>
                <div>at
javafx.base/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)<br>
                </div>
                <div>at
javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:145)<br>
                </div>
                <div>at
javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:50)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.text.Text.setText(Text.java:444)<br>
                </div>
                <div>at
javafx.controls/javafx.scene.control.skin.TextAreaSkin.lambda$new$16(TextAreaSkin.java:347)<br>
                </div>
                <div>at
javafx.controls/com.sun.javafx.scene.control.LambdaMultiplePropertyChangeListenerHandler.lambda$new$2(LambdaMultiplePropertyChangeListenerHandler.java:95)<br>
                </div>
                <div>at
javafx.base/javafx.beans.WeakInvalidationListener.invalidated(WeakInvalidationListener.java:82)<br>
                </div>
                <div>at
javafx.base/com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:360)<br>
                </div>
                <div>at
javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)<br>
                </div>
                <div>at
javafx.controls/javafx.scene.control.TextInputControl$TextProperty.fireValueChangedEvent(TextInputControl.java:1496)<br>
                </div>
                <div>at
javafx.controls/javafx.scene.control.TextInputControl$TextProperty.markInvalid(TextInputControl.java:1500)<br>
                </div>
                <div>at
javafx.controls/javafx.scene.control.TextInputControl$TextProperty.controlContentHasChanged(TextInputControl.java:1439)<br>
                </div>
                <div>at
javafx.controls/javafx.scene.control.TextInputControl.lambda$new$0(TextInputControl.java:176)<br>
                </div>
                <div>at
javafx.base/com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:147)<br>
                </div>
                <div>at
javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)<br>
                </div>
                <div>at
javafx.controls/javafx.scene.control.TextInputControl$ContentBase.fireValueChangedEvent(TextInputControl.java:149)<br>
                </div>
                <div>at
javafx.controls/javafx.scene.control.TextArea$TextAreaContent.insert(TextArea.java:214)<br>
                </div>
                <div>at
javafx.controls/javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:1301)<br>
                </div>
                <div>at
javafx.controls/javafx.scene.control.TextInputControl.filterAndSet(TextInputControl.java:1266)<br>
                </div>
                <div>at
javafx.controls/javafx.scene.control.TextInputControl$TextProperty.doSet(TextInputControl.java:1517)<br>
                </div>
                <div>at
javafx.controls/javafx.scene.control.TextInputControl$TextProperty$Listener.invalidated(TextInputControl.java:1540)<br>
                </div>
                <div>at
javafx.base/com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:360)<br>
                </div>
                <div>at
javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)<br>
                </div>
                <div>at
javafx.base/javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:104)<br>
                </div>
                <div>at
javafx.base/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:111)<br>
                </div>
                <div>at
javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:145)<br>
                </div>
                <div>at
javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:50)<br>
                </div>
                <div>at
com.azul.docs.langchain4j.SearchAction.appendAnswer(SearchAction.java:45)<br>
                </div>
                <div>at
com.azul.docs.langchain4j.DocsAnswerService$2.onNext(DocsAnswerService.java:172)<br>
                </div>
                <div>at
dev.langchain4j.model.openai.OpenAiStreamingChatModel.handle(OpenAiStreamingChatModel.java:152)<br>
                </div>
                <div>at
dev.langchain4j.model.openai.OpenAiStreamingChatModel.lambda$generate$0(OpenAiStreamingChatModel.java:133)<br>
                </div>
                <div>at
dev.ai4j.openai4j.StreamingRequestExecutor$2.onEvent(StreamingRequestExecutor.java:178)<br>
                </div>
                <div>at
                  okhttp3.internal.sse.RealEventSource.onEvent(RealEventSource.kt:101)<br>
                </div>
                <div>at
okhttp3.internal.sse.ServerSentEventReader.completeEvent(ServerSentEventReader.kt:108)<br>
                </div>
                <div>at
okhttp3.internal.sse.ServerSentEventReader.processNextEvent(ServerSentEventReader.kt:52)<br>
                </div>
                <div>at
okhttp3.internal.sse.RealEventSource.processResponse(RealEventSource.kt:75)<br>
                </div>
                <div>at
                  okhttp3.internal.sse.RealEventSource.onResponse(RealEventSource.kt:46)<br>
                </div>
                <div>at
                  okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)<br>
                </div>
                <div>at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)<br>
                </div>
                <div>at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)<br>
                </div>
                <div>at java.base/java.lang.Thread.run(Thread.java:1583)<br>
                </div>
                <div>[93.499s][warning][os] Loading hsdis library failed<br>
                </div>
                <div>#<br>
                </div>
                <div># If you would like to submit a bug report, please
                  visit:<br>
                </div>
                <div>#   <a target="_blank"
                    href="http://www.azul.com/support/"
                    moz-do-not-send="true" class="moz-txt-link-freetext">http://www.azul.com/support/</a><br>
                </div>
                <div># The crash happened outside the Java Virtual
                  Machine in native code.<br>
                </div>
                <div># See problematic frame for where to report the
                  bug.<br>
                </div>
                <div>#<br>
                </div>
                <div><br>
                </div>
                <div>Process finished with exit code 134 (interrupted by
                  signal 6:SIGABRT)<br>
                </div>
                <div><br>
                </div>
                <div><b>Error #1</b><br>
                </div>
                <div><br>
                </div>
                <div>Exception in thread "JavaFX Application Thread"
                  java.lang.NullPointerException: Cannot read field
                  "advances" because "this.layoutCache" is null<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.shape(PrismTextLayout.java:919)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.layout(PrismTextLayout.java:1113)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.ensureLayout(PrismTextLayout.java:230)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.getBounds(PrismTextLayout.java:256)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.text.Text.getLogicalBounds(Text.java:432)<br>
                </div>
                <div>at
javafx.graphics/javafx.scene.text.Text.doComputeGeomBounds(Text.java:1186)<br>
                </div>
                <div>at
javafx.graphics/javafx.scene.text.Text$1.doComputeGeomBounds(Text.java:149)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.scene.shape.TextHelper.computeGeomBoundsImpl(TextHelper.java:90)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3812)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3774)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Node.getLocalBounds(Node.java:3722)<br>
                </div>
                <div>at
javafx.graphics/javafx.scene.Node$MiscProperties$3.computeBounds(Node.java:6812)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Node$LazyBoundsProperty.get(Node.java:9749)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Node$LazyBoundsProperty.get(Node.java:9740)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Node.getBoundsInLocal(Node.java:3402)<br>
                </div>
                <div>at
javafx.controls/javafx.scene.control.skin.TextAreaSkin$ContentView.layoutChildren(TextAreaSkin.java:1325)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.layout(Parent.java:1208)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:594)<br>
                </div>
                <div>at
javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2600)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:401)<br>
                </div>
                <div>at
java.base/java.security.AccessController.doPrivileged(AccessController.java:400)<br>
                </div>
                <div>at
                  javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:400)<br>
                </div>
                <div>at
                  javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:430)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:592)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:572)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:565)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:352)<br>
                </div>
                <div>at
javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)<br>
                </div>
                <div><br>
                </div>
                <div><b>Error #2</b><br>
                </div>
                <div><br>
                </div>
                <div>Exception in thread "JavaFX Application Thread"
                  java.lang.NullPointerException: Cannot read the array
                  length because "this.lines" is null<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.layout(PrismTextLayout.java:1316)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.ensureLayout(PrismTextLayout.java:230)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.getBounds(PrismTextLayout.java:256)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.text.Text.getLogicalBounds(Text.java:432)<br>
                </div>
                <div>at
javafx.graphics/javafx.scene.text.Text.doComputeGeomBounds(Text.java:1186)<br>
                </div>
                <div>at
javafx.graphics/javafx.scene.text.Text$1.doComputeGeomBounds(Text.java:149)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.scene.shape.TextHelper.computeGeomBoundsImpl(TextHelper.java:90)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3812)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3774)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Node.getLocalBounds(Node.java:3722)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Node.updateTxBounds(Node.java:3876)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Node.getTransformedBounds(Node.java:3668)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Node.updateBounds(Node.java:776)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
                </div>
                <div>at
                  javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
                </div>
                <div>at
javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2615)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:401)<br>
                </div>
                <div>at
java.base/java.security.AccessController.doPrivileged(AccessController.java:400)<br>
                </div>
                <div>at
                  javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:400)<br>
                </div>
                <div>at
                  javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:430)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:592)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:572)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:565)<br>
                </div>
                <div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:352)<br>
                </div>
                <div>at
javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)<br>
                </div>
                <div><br>
                </div>
                <div class="x_1879826395zmail_signature_below">
                  <div id="">
                    <div>Best regards<br>
                    </div>
                    <div>Frank Delporte<br>
                    </div>
                    <div>
                      <div><br>
                      </div>
                    </div>
                    <div><i>Want to have coding-fun? </i><br>
                    </div>
                    <div><i>Check my blog </i><a target="_blank"
                        href="https://webtechie.be/"
                        moz-do-not-send="true"><i>https://webtechie.be/</i></a><i>
                        and book "Getting started with Java on Raspberry
                        Pi" on </i><a target="_blank"
                        href="https://webtechie.be/books/"
                        moz-do-not-send="true"><i>https://webtechie.be/books/</i></a><br>
                    </div>
                    <div>
                      <div><br>
                      </div>
                    </div>
                    <div><br>
                    </div>
                  </div>
                </div>
                <div><br>
                </div>
              </div>
              <br>
            </div>
          </blockquote>
        </div>
        <div><br>
        </div>
      </div>
      <br>
    </blockquote>
  </body>
</html>