Search code examples
javadesign-patternsobservablesubscriber

Is there any better way to track subscriber changes?


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?


Solution

  • 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;
       }
    
    }