title: How to add item to ObservableList in onMessage event listener
body: <p>I am making two simple JMS application with JavaFx (one for sender and the other one is receiver). </p>
  
  <p>But, I could not refresh the GUI of the receiver with the new arriving message from the sender. </p>
  
  <p>From debugging, I noticed that the receiver received the message from the server, but the receiver could not add it to my ObservableList (which, of course, resulted in no refreshing in the GUI of the ListView). </p>
  
  <p>I looked up on the internet with onMessage event, and override it (to add an item to the ObservableList there), but it is not working. After the event is raised, no element was added to the ObservableList.</p>
  
  <p>This is my receiver:</p>
  
  <pre><code>public class Administrator extends Application {
      private ObservableList&lt;String&gt; observableList;
      private final String DESTINATION_TYPE = "queue";
      private final String RECEIVE_CHANNEL = "askDestination";
      private final String SEND_CHANNEL = "answerDestination";
      private MessageConsumer messageConsumer;
      private MessageProducer messageProducer;
      private Session session;
      private Destination destination;
      private Connection connection;
  
      @FXML
      public TextField tfMessage;
  
      @FXML
      public ListView&lt;String&gt; lvMessage;
  
      @FXML
      public Button btnSend;
  
      @Override
      public void start(Stage stage) throws IOException {
          Parent root = FXMLLoader.load(getClass().getResource("administratorUI.fxml"));
          stage.setTitle("Administrator");
          stage.setScene(new Scene(root, 640, 480));
          stage.setResizable(false);
          stage.show();
      }
  
      @Override
      public void init() throws Exception {
          super.init();
          lvMessage = new ListView&lt;&gt;();
          tfMessage = new TextField();
          //questionList = new ArrayList&lt;&gt;();
          observableList = FXCollections.observableArrayList();
          lvMessage.setItems(observableList);
          initService(RECEIVE_CHANNEL, DESTINATION_TYPE);
          getMessage(RECEIVE_CHANNEL);
          //Platform.runLater(this::updateLV);
      }
  
      public static void main(String[] args) {
          launch();
      }
  
      public void onButtonAnswerClick() {
          String message = tfMessage.getText();
  
          if (message.equals("")) {
              Alert alert = new Alert(Alert.AlertType.ERROR);
              alert.setContentText("Please enter your message!!");
              alert.show();
              return;
          }
  
          if (replyToQuestion(message, SEND_CHANNEL)) {
              tfMessage.clear();
          } else {
              handleServiceError("Service Error", "Could not send the message to the service");
          }
      }
  
      private void handleServiceError(String errorTitle, String errorText){
          Alert error = new Alert(Alert.AlertType.ERROR);
          error.setTitle(errorTitle);
          error.setContentText(errorText);
      }
  
      private void updateLV(){
          lvMessage.getItems().clear();
          lvMessage.setItems(observableList);
      }
  
      private void initService(String targetDestination, String destinationType){
          try {
              Properties props = new Properties();
              props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
                      "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
              props.setProperty(Context.PROVIDER_URL, "tcp://localhost:61616");
  
              // connect to the Destination called “myFirstChannel”
              // queue or topic: “queue.myFirstDestination” or “topic.myFirstDestination”
              props.put((destinationType + "." + targetDestination), targetDestination);
              Context jndiContext = new InitialContext(props);
              ConnectionFactory connectionFactory = (ConnectionFactory) jndiContext.lookup("ConnectionFactory");
  
              // to connect to the JMS
              connection = connectionFactory.createConnection();
  
              // session for creating consumers
              session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
  
              // connect to the receiver destination
              //reference to a queue/topic destination
              destination = (Destination) jndiContext.lookup(targetDestination);
          } catch (NamingException | JMSException e) {
              e.printStackTrace();
          }
      }
  
      private boolean replyToQuestion(String message, String sendDestination) {
          try {
              initService(sendDestination, DESTINATION_TYPE);
  
              // for sending messages
              messageProducer = session.createProducer(destination);
  
              // create a text message
              Message msg = session.createTextMessage(message);
  
              msg.setJMSMessageID("222");
              System.out.println(msg.getJMSMessageID());
  
              // send the message
              messageProducer.send(msg);
  
              //questionList.add(message);
              updateLV();
              return true;
          } catch (JMSException e) {
              e.printStackTrace();
              return false;
          }
      }
  
      private void getMessage(String receiveDestination) {
          try {
              initService(receiveDestination, DESTINATION_TYPE);
  
              // this is needed to start receiving messages
              connection.start();
  
              // for receiving messages
              messageConsumer = session.createConsumer(destination);
              MessageListener listener = message -&gt; {
                  try {
                      observableList.add(((TextMessage)message).getText());
                  } catch (JMSException e) {
                      e.printStackTrace();
                  }
              };
  
              messageConsumer.setMessageListener(listener);
          } catch (JMSException e) {
              e.printStackTrace();
          }
      }
  }
  </code></pre>
  
  <p>And my sender: </p>
  
  <pre><code>    public class User extends Application implements MessageListener {
      private static List&lt;String&gt; questions;
      private final String DESTINATION_TYPE = "queue";
      private final String RECEIVE_CHANNEL = "answerDestination";
      private final String SEND_CHANNEL = "askDestination";
      private String requestId;
      private MessageConsumer messageConsumer;
      private MessageProducer messageProducer;
      private Session session;
      private Destination destination;
      private Connection connection;
  
      @FXML
      public Button btnSend;
  
      @FXML
      public TextField tfMessage;
  
      @FXML
      public ListView lvMessage;
  
      @Override
      public void start(Stage stage) throws IOException {
          Parent root = FXMLLoader.load(getClass().getResource("userUI.fxml"));
          stage.setTitle("Sender");
          stage.setScene(new Scene(root, 640, 480));
          stage.setResizable(false);
          stage.show();
      }
  
      @Override
      public void init() throws Exception {
          super.init();
          btnSend = new Button();
          tfMessage = new TextField();
          lvMessage = new ListView();
          questions = new ArrayList&lt;&gt;();
          initService(RECEIVE_CHANNEL, DESTINATION_TYPE);
          getAnswer(RECEIVE_CHANNEL);
      }
  
      public static void main(String[] args){
          launch(args);
      }
  
      public void onButtonSendClick(javafx.event.ActionEvent actionEvent) {
          String message = tfMessage.getText();
  
          if (message.equals("")) {
              Alert alert = new Alert(Alert.AlertType.ERROR);
              alert.setContentText("Please enter your question!!");
              alert.show();
              return;
          }
  
          if (sendQuestion(message, SEND_CHANNEL)) {
              tfMessage.clear();
          } else {
              handleServiceError("Service Error", "Could not send the message tot the service");
          }
      }
  
      private void handleServiceError(String errorTitle, String errorText){
          Alert error = new Alert(Alert.AlertType.ERROR);
          error.setTitle(errorTitle);
          error.setContentText(errorText);
      }
  
      private void updateLV(){
          lvMessage.getItems().clear();
          lvMessage.getItems().addAll(questions);
      }
  
      private void initService(String targetDestination, String destinationType){
          try {
              Properties props = new Properties();
              props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
                      "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
              props.setProperty(Context.PROVIDER_URL, "tcp://localhost:61616");
  
              // connect to the Destination called “myFirstChannel”
              // queue or topic: “queue.myFirstDestination” or “topic.myFirstDestination”
              props.put((destinationType + "." + targetDestination), targetDestination);
              Context jndiContext = new InitialContext(props);
              ConnectionFactory connectionFactory = (ConnectionFactory) jndiContext.lookup("ConnectionFactory");
  
              // to connect to the JMS
              connection = connectionFactory.createConnection();
              // session for creating consumers
              session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
  
              // connect to the receiver destination
              //reference to a queue/topic destination
              destination = (Destination) jndiContext.lookup(targetDestination);
          } catch (NamingException | JMSException e) {
              e.printStackTrace();
          }
      }
  
      private boolean sendQuestion(String message, String sendDestination) {
          try {
              initService(sendDestination, DESTINATION_TYPE);
  
              // for sending messages
              messageProducer = session.createProducer(destination);
  
              // create a text message
              Message msg = session.createTextMessage(message);
  
              msg.setJMSMessageID("111");
              System.out.println(msg.getJMSMessageID());
  
              // send the message
              messageProducer.send(msg);
  
              //questionList.add(message);
              updateLV();
              return true;
          } catch (JMSException e) {
              e.printStackTrace();
              return false;
          }
      }
  
      private void getAnswer(String receiveDestination) {
          try {
              initService(receiveDestination, DESTINATION_TYPE);
  
              // for receiving messages
              messageConsumer = session.createConsumer(destination);
              messageConsumer.setMessageListener(this);
  
  
              // this is needed to start receiving messages
              connection.start();
          } catch (JMSException e) {
              e.printStackTrace();
          }
      }
  
      @Override
      public void onMessage(Message message) {
          try {
              questions.add(((TextMessage)message).getText());
              requestId = message.getJMSMessageID();
              System.out.println(requestId);
              updateLV();
          } catch (JMSException e) {
              e.printStackTrace();
          }
      }
  }
  </code></pre>
  
  <p>The FXML of the receiver: </p>
  
  <pre><code>    &lt;GridPane hgap="10" prefHeight="400.0" prefWidth="600.0" vgap="10" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Administrator"&gt;
      &lt;padding&gt;
          &lt;Insets bottom="10" left="10" right="10" top="10" /&gt;
      &lt;/padding&gt;
      &lt;Label text="Current question:" textFill="cornflowerblue" GridPane.columnIndex="0" GridPane.rowIndex="0"&gt;
          &lt;font&gt;
              &lt;Font name="System Bold" size="15.0" /&gt;
          &lt;/font&gt;
      &lt;/Label&gt;
      &lt;ListView fx:id="lvMessage" prefWidth="600" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="1"&gt;
  
      &lt;/ListView&gt;
  
      &lt;HBox spacing="10" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="2"&gt;
          &lt;TextField fx:id="tfMessage" prefHeight="61.0" prefWidth="504.0" promptText="Type your answer here..."&gt;
              &lt;font&gt;
                  &lt;Font size="15.0" /&gt;
              &lt;/font&gt;
          &lt;/TextField&gt;
          &lt;Button fx:id="btnSend" onAction="#onButtonAnswerClick" prefHeight="61.0" prefWidth="88.0" text="Send"&gt;
          &lt;/Button&gt;
      &lt;/HBox&gt;
     &lt;columnConstraints&gt;
        &lt;ColumnConstraints /&gt;
        &lt;ColumnConstraints /&gt;
     &lt;/columnConstraints&gt;
     &lt;rowConstraints&gt;
        &lt;RowConstraints /&gt;
        &lt;RowConstraints /&gt;
        &lt;RowConstraints /&gt;
     &lt;/rowConstraints&gt;
  &lt;/GridPane&gt;
  </code></pre>
  
  <p>After the receiver received the message, the event is raised so I expected the ListView to be updated with the new message. However, no element was added to the ObservableList => no update in the ListView. </p>
  
  <p>So, I would like to ask if what I did is wrong or correct?</p>