Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I'm developing a simple conferencing app with a Swing standalone client which connects to enterprise java beans. Users can create "sessions" (conferences) on the server, and then can join those sessions, send text messages and see the participants's webcams in the same session.

I followed the MVC pattern, but I'm not quite satisfied with the design so far. All the examples of MVC on the web are simplified, and I think I don't fully understand yet how to implement MVC on the application scale.

I have two views (JFrames) so far, each with its own controller and model. One is for the administration of sessions (SessionsFrame), the other is what the user sees while participating in a conference (ConferenceFrame).

The design I came up with is like this: The event handler methods in the views call the controller's methods, which then update the EJB on the server side. The EJBs "push" their changes to all clients in the same session. The changes are received by "listener" classes on the client side, which then update the client side models. The models then push their changes to the views.

For example (I try to keep the code as short as I can):

SessionsFrame.java:

public class SessionsFrame extends javax.swing.JFrame implements IView {
    private SessionsController controller;

    private javax.swing.JList sessionsList;
    private javax.swing.JButton newSessionButton;
    //...

    public SessionsFrame(SessionsController controller) {
        this.controller = controller;
        //...
    }

    @Override //from IView
    public void update(String propertyName, Object property) {
        //update the JList with the list of sessions
    } 

    private void newSessionButtonActionPerformed(java.awt.event.ActionEvent evt) {
        String name = JOptionPane.showInputDialog(this, "New session name:",
                "New session", JOptionPane.PLAIN_MESSAGE);
        controller.performNewSession(name);
    }

    //...
}

SessionsController.java:

public class SessionsController {
    private SessionsBeanRemote sessionsBean;

    public SessionsController(SessionsBeanRemote sessionsBean) {
        this.sessionsBean = sessionsBean;
    }

    public void performNewSession(String name) {
        sessionsBean.createSession(new Session(name));
    }

    public void performJoin(String selection) {
        Session currentSession = sessionsBean.getSession(selection);
        new ApplicationBuilder().buildConferencingInterface(currentSession).setVisible(true);
    }

    //...
} 

SessionsDb.java:

public class SessionsDb {
    public static final String PROPERTYCHANGE_SESSIONSLIST = "SessionsList";

    private List<IView> views = new ArrayList<IView>();
    private List<Session> list = new ArrayList<Session>();

    public void addView(IView view) {
        views.add(view);
    }

    public void setList(List<Session> list) {
        this.list = list;
        updateViews();
    }

    private void updateViews() {
        for (IView view : views) {
            view.update(PROPERTYCHANGE_SESSIONSLIST, list);
        }
    }

    //...
}

SessionsListener.java:

public class SessionsListener implements SessionsListenerRemote {
    private SessionsDb model;
    private SessionsBeanRemote bean;

    public SessionsListener(SessionsDb model, SessionsBeanRemote bean) {
        this.model = model;
        this.bean = bean;
    }

    public void listen() {
        try {
            javax.rmi.PortableRemoteObject.exportObject(this);
            bean.subscribe(this);
        } catch (RemoteException ex) {
            //...
        }
    }

    @Override
    public void update(List<Session> sessions) throws RemoteException {
        model.setList(sessions);
    }
}

ApplicationBuilder.java:

public class ApplicationBuilder {

    public SessionsFrame buildSessionsInterface(SessionsBeanRemote sessionsBean) {
        SessionsDb sessionsDb = new SessionsDb();
        SessionsController sessionsController = new SessionsController(sessionsBean);
        SessionsListener sessionsListener = new SessionsListener(sessionsDb, sessionsBean);
        SessionsFrame sessionsFrame = new SessionsFrame(sessionsController);

        sessionsDb.addView(sessionsFrame);
        sessionsListener.listen();

        return sessionsFrame;
    } 

    //...
}

Main.java:

public class Main {
    @EJB
    public static SessionsBeanRemote sessionsBean;
    //...

    public static void main(String[] args) {
        SessionsFrame sessionsFrame = new ApplicationBuilder().buildSessionsInterface(sessionsBean);
        sessionsFrame.setVisible(true);
    }

}

Similarly for text messages, there is a ConferencingFrame, MessagesController, MessagesDb, MessagesBean, and MessagesListener.

So my questions are: Do I understand MVC correctly? How can I make this design more extensible? Would I be better off with a single controller in the entire application, or a separate controller for each view (each JFrame)? How can I decouple the components further? Is there a better design pattern for this situation?

share|improve this question
add comment

Know someone who can answer? Share a link to this question via email, Google+, Twitter, or Facebook.

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.