0

Basically, I'm working on a Client Server Architecture so Objects can be modified externally by some Clients.

I have a bank :

public class Bank{
    private List<BankingOperation> operationList = new ArrayList<BankingOperation>();

    public void addOperation(BankingOperation op) {
        this.operationList.add(op);
//...
}

And my Server :

public class ServerBank extends JFrame {
    private Bank bank;
    private JTable table;
    private OperationTableModel model;

    public ServerBank() {
        this.bank = new Bank();
        this.model= new OperationTableModel(this.bank.getOperationList());
        table = new JTable(model);
        getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
        pack();
    }

    public static void main (String args[]) throws Exception {

        ServerBank frame=new ServerBank();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800,700);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);


    }
    class OperationTableModel extends AbstractTableModel {

    private static final long serialVersionUID = 1L;
    private List<BankingOperation> operationList;
    public String[] colNames = { "Date", "Login", "Customer","Account", "Operation", "Amount", "Final Balance" };
    public Class<?>[] colTypes = { String.class, String.class, String.class, String.class, String.class, Integer.class,
            Integer.class };


    public OperationTableModel(List<BankingOperation> operationList) {
        super();
        this.operationList = operationList;
    }//...
}

Clients can add an Operation in the Bank operationList by calling addOperation().

The question is: How can the JTable detect that and refresh the display?

Because Clients are not using the TableModel methods for adding Operations. They have no access to this class. On top of that, I don't know if giving the whole operationList of the Bank in the TableModel constructor is a good idea...

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
xenom
  • 377
  • 1
  • 5
  • 15

1 Answers1

1

By giving the clients access to the internal list used by the bank, you allow them to do things behind the bank of the bank. A bit like if a real bank gave access to its internal database, instead of forcing all the clients to go through the online bank application.

You should give the clients a reference to an interface which allows them to perform their operations. The implementation of this interface would control that every operation they do is allowed, and does everything necessary.

For example, the addOperation() method of the interface implementation would not only add the operation to the list of operations, but also fire a table model event in order for the table to display this added operation.

This could be done directly, if the bank encapsulates the table model, or indirectly, by having the bank fire a custom "operation added" event. The table model would listen to those events, and fire its own table model event in order for the table to be updated.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Effectively the clients are only given a Session to do their operation if the Connection was successful. But I'm obliged to give an instance of the Bank to the Session constructor, right ? Because effectively, I don't send the whole Bank instance to clients but even for the list of operations in Session, we must do the operations on something, so I have a constructor Session(Bank bank); Concerning the Table problem, if I understand, the solution would be to encapsulate the table model itself and remove my ArrayList of Operation? (Because the ArrayList would be already in the table model). – xenom Dec 03 '12 at 13:00
  • Yes, you could indeed encapsulate the table model into the bank, and the bank into the session. That makes everything extremely tightly coupled, and not realistic for a real application, but the idea is to do that. Using events and event listeners would make the whole thing less coupled. – JB Nizet Dec 03 '12 at 13:03
  • Well if the architecture is not realistic, I'd rather go for the event and event listeners. But I don't really understand how to do so. Because if Session doesn't know the Bank how can it call the Bank methods ? – xenom Dec 03 '12 at 13:18
  • Look at how JButton works. It doesn't know anything about your application. But when you click it, it calls a method of your application, that you implemented yourself. It does so because your application adds alistener to the button, an the button calls this listener when it's clicked. Do the same with the bank and the session: the bank adds a listner to the session. When an operation is done, the session firs an event. The bank receives the vent from the session, and updates its table model. – JB Nizet Dec 03 '12 at 15:25
  • The problem is that the Bank is not the server. In fact the Server instantiate a Bank and also instantiate the Session. That's why Bank doesn't know Session. Do you think it's preferable to merge the Server as the Bank itself ? If I do in that way I understand more or less how to deal with with basic Banking operation and Listener. But concerning retrieval of balance or the list of Account? How do you manage with a Listener ? The Session will say to the Bank "the client wants his/her infos" but how do you get a return value ? – xenom Dec 03 '12 at 16:31