Search code examples
javadatabasemultithreadingobserver-pattern

How do I implement Observer design pattern for a Multi-Threaded Java server?


I have the following situation:

A Java server has to respond to multiple clients through sockets. The server responses are, in fact, results of database queries. The clients can also demand tohe server to update the database content.

A new thread is assigned for each new connected client. I want each connected client to "know" when other clients update the database content.

I have tried to implement the Observer design pattern to achieve this but I didn't succeeded: the observers are not notified when an update query is applied to the database -> the update method in observer is never called. The actual Java code is complicated so I will try to summarize the Observer design pattern implementation through the following code snippet:

public class DBDataPersistance<E> extends Observable implements DataPersistance<E>{
private static Connection conn;
protected Statement stmt;
protected ResultSet res;
protected List<Observer> obs = new LinkedList<Observer>();

//The method that alters the database;
public void updateData(String parameters) {
    try {
        this.setChanged();
        this.notifyObservers();
        this.stmt.executeUpdate(parameters);
    } catch (SQLException e) {
        JOptionPane.showMessageDialog(null, e.getMessage());
    }
}

public void addObserver(Observer o){
    System.out.println("New observer added!");
    this.obs.add(o);
    }
}

//MultiThreadServer implements Runnable and Observer and contains an instance of DBDataPersistance
public class PizzaMultiThreadServer implements Runnable, Observer{
    private static PizzaDBDataPersistance sDB;
    private static ObjectOutputStream sendClientResponse;
    private static ObjectInputStream isc;


    MultiThreadServer(Socket s) {
        this.cSocket = s;
        try {
            sendClientResponse = new ObjectOutputStream(cSocket.getOutputStream());
            sendClientResponse.flush();
            isc = new ObjectInputStream(cSocket.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
    sDB = new DBDataPersistance("jdbc:sqlserver://LAPTOPPC;database=BD;integratedSecurity=true;");
        while (true) {
             //client-server communication
             MultiThreadServer newClient = new MultiThreadServer(csock);
             sDB.addObserver(newClient);
             Thread t = new Thread(newClient);
             t.start();
        }
    }


 @Override
 public void run() {
 //Client server communication on a separate thread
 }


 @Override
 public void update(Observable o, Object arg) {
         System.out.println("Thread " + Thread.currentThread().getId()+ ":Noticed on update!");
 }
}

Could you tell me where I am wrong and indicate me the steps to correctly implement the Observer design pattern in this case?

Many thanks.


Solution

  • Your problem here is due to the fact that you override the method addObserver in your class DBDataPersistance such that you have no Observers registered into the class Observable so you have no Observer that can be notified.

    The code should be:

    public void addObserver(Observer o){
        // Calls the method addObserver of the class Observable
        super.addObserver(o);
        System.out.println("New observer added!");
        this.obs.add(o);
    }
    

    Please note that you don't need to manage the list of Observer yourself as it is already managed by the class Observable so you should get rid of obs, the code then will be:

     public void addObserver(Observer o){
        // Calls the method addObserver of the class Observable
        super.addObserver(o);
        System.out.println("New observer added!");
    }
    

    Last remark about your code is the fact that you are supposed to call executeUpdate before notifying the Observers so it should be:

    public void updateData(String parameters) {
        try {
            this.stmt.executeUpdate(parameters);
            this.setChanged();
            this.notifyObservers();        
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(null, e.getMessage());
        }
    }