3

Lets say we have a Client class with method to send messages to server queue. It is also subscribed to queue and server will send a notification back to all clients when it receives a new message from any of registered clients:

public class Client {
   public void sendMessage(String message) {
      // Method to send messages to server
   }

   public void messageDelivered(String receivedMessage) {
      // This is a method subscribed successfull message delivering
   }
}

In another class I would like to instansiate my Client, send a message and check that it was sent successfuly:

public class ParentClass {
   protected boolean checkConnection() {
      Client client = new Client(); // Lets skip all configuration and connection details
      String testMessage = "Test message";
      client.sendMessage(testMessage);

      // Check that messageDelivered() was called in client with testMessage parameter

      return result;
   }
}

What is the best way to check that messageDelivered() was called asynchroniously inside parent checkConnection() method?

I see the simple solution to create a flag in Client class, update it when message is delivered and wrap checking of this flag in some loop limited by time in parent class. But this option looks very dirty for me. Maybe there are some better practicies or "watchers" in Java SDK?

dmkov
  • 334
  • 2
  • 11
  • If it called asynchronously, it can't be called inside `checkConnection()`, these two are mutually exclusive in your code sample. – M. Prokhorov Aug 30 '17 at 13:48
  • @M.Prokhorov it can be done in following way: retries = 1000; do { if (client.deliveredResult == true) { // success } sleep(1000); retries--; } while (retries > 0); and client.deliveredResult will be set to true when `messageDelivered()` is executed. But I am wondering if there is a more elegant solution. (sorry, it messed formatting) – dmkov Aug 30 '17 at 13:57
  • why don't you add a callback (`Runnable` or `Consumer)` as a second parameter to the `sendMessage`? A client will trigger that parameter when a successful response comes from the server – Andrew Tobilko Aug 30 '17 at 13:58
  • @AndrewTobilko this is a good idea, but I need to receive result before checkConnection() ends (not asynchronous callback). it should be a health check of connection and checkConnection() should send and receive a test message (I simplified example with `messageDelivered()` a little) – dmkov Aug 30 '17 at 14:04
  • @AndrewTobilko, or possibly return `Future` or `CompletableFuture`. – M. Prokhorov Aug 30 '17 at 14:17
  • Looks like the Observer pattern is required here, [observer-pattern](https://dzone.com/articles/observer-pattern-java) I hope it helps – Jorge Chavez Aug 30 '17 at 13:45

1 Answers1

2

Maybe something like that?

public class Client {
   private Runnable runnable;

   public void sendMessage(String message, Runnable runnable) {
      // Method to send messages to server
      this.runnable = runnable;
   }

   public void messageDelivered(String receivedMessage) {
      // This is a method subscribed successfull message delivering
      this.runnable.run();
   }
}

Then create a Runnable in your ParentClass and pass it to the client.

public class ParentClass {

   protected boolean checkConnection() {
      Client client = new Client(); // Lets skip all configuration and connection details
      String testMessage = "Test message";
      // Check that messageDelivered() was called in client with testMessage parameter
      MyRunnable runnable = new MyRunnable();
      client.sendMessage(testMessage, runnable);

      try {
         runnable.wait( 10000 );  // Wait for 10 seconds
      } catch( InterruptedException e ) {
         e.printStackTrace();
      }

      return runnable.getResult();
   }
}

Runnable class:

public class MyRunnable implements Runnable {

   private boolean result;

   public MyRunnable( ) {
      this.result = false;
   }

   @Override
   public void run( ) {
      this.result = true;
      this.notifyAll();
   }

   public boolean getResult( ) {
      return this.result;
   }

}
Henry Martens
  • 229
  • 1
  • 10
  • Yes, this is a good solution if I have something I can postpone for execution. But I do not want to end checkConnection() method before I know the result (it should wait for success delivery or throw an exception if it does not happen). `checkConnection()` method is a health check to verify connection to the server and it should return result to the top (sorry if I confused with the void method type) – dmkov Aug 30 '17 at 14:11
  • @diko Ok, so you want to return a boolean value that indicates that the server connection is working? – Henry Martens Aug 30 '17 at 14:13
  • @HenryMartens right, `checkConnection()` should return this result (I have updated initial post) – dmkov Aug 30 '17 at 14:15
  • @diko I updated my code. It is a little bit dirty but it should work. I'm interested in a better solution. – Henry Martens Aug 30 '17 at 14:40
  • @diko I cleaned up a little bit by implementing `Runnable` and create my own Runnable class (`MyRunnable`) – Henry Martens Aug 30 '17 at 14:48
  • @HenryMartens this is what I looked for! Thank you! I probably would not create a separate class for this check and will try to adapt you previous option but they both look great. – dmkov Aug 30 '17 at 14:53