I am writing an application with Java 8 using NetBeans, and want some reassurance that I am going the correct way with this.
I am finding it tough because of the use of Swing.
I have gone for one model (for now), one controller and a set of views. All of the MVC examples for Java/Swing involve one JDialog, one model and one controller.
The controller maintains a list of views and commands, each of which are in a HashMap and are initiated in the main method of the application.
Each command takes the dependencies required to carry out the logic between the view and model in it's constructor. I know this is not the strict implementation of the Command pattern, but I can not think of how to get the two talking to each other without violating the Open/Closed principle.
Also, because of the nature of each View, in each command, I have made reference to the concrete version of the view instead of the abstract version -- this is for updating various fields in each view.
Please criticize my code... I am new to this, and need all the help I can get.
Below is what I have at the moment:
TopLevelController.java:
public class TopLevelController implements ActionListener {
private final Map<String,View> views = new HashMap<>();
private final Map<String,Command> commands = new HashMap<>();
private VFrontOfHouse frontOfHouse;
private Model model;
public void initiate(VFrontOfHouse frontOfHouse) {
    // Have a reference to the top level container (Front of house)
    this.frontOfHouse = frontOfHouse;
    // Iterate through the views, and initiate them with this controller as a listener
    Set<String> keys = views.keySet();
    for(String viewKey : keys) {
        views.get(viewKey).setListeners(this);
        System.out.println(viewKey);
    }
}
public void setModel(Model model) {
    this.model = model;
}
public void addView(String viewKey, View view) {
    views.put(viewKey, view);
}
public View getView(String viewKey) {
    View view = null;
    try{
        view = views.get(viewKey);
    }
    catch(NullPointerException ex) {
        JOptionPane.showMessageDialog(frontOfHouse, "No such view: "+viewKey);
    }
    return view;
}
public void addCommand(String cmdKey, Command cmd) {
    commands.put(cmdKey, cmd);
}
public void executeCommand(String cmdKey) {
    try {
        commands.get(cmdKey).execute();
    }
    catch (NullPointerException npe) {
        JOptionPane.showMessageDialog(null, "Unknown command "+cmdKey);
    }
}
@Override
public void actionPerformed(ActionEvent e) {
    executeCommand(e.getActionCommand());
}
}
Model.java
public class Model {
private String result;
private ClientSession session;
private QueryRunner runner;
public void createSession(BaseXCredentials bc) throws IOException {
    session = new ClientSession(bc.getHost(),bc.getPort(),bc.getUid(),bc.getPassword());
    runner = new QueryRunner(session);
}
public String runQuery(String query) throws IOException {
    result = runner.runQuery(query);
    return result;
}
public void importVP(String path, String dbName) throws IOException {
    // Create a new database
    runner.createDB(dbName);
    String query = "db:add(\""+dbName+"\",\""+ path +"\")";
    runner.runQuery(query);
    runner.close(dbName);
    runner.openDB("VPData");
    runner.runQuery("insert node <db>"+dbName+"</db> into ./databases");
    runner.close("VPData");
}
public String[] getDBList() throws IOException {
    ArrayList<Database> databases = new ArrayList<>();
    runner.openDB("VPData");
    result = runner.runQuery("databases");
    XMLReaderSimpleList reader = new XMLReaderSimpleList(databases);
    reader.read(result);
    String[] strings;
    Integer i;
    strings = new String[databases.size()];
    for(i = 0; i < databases.size(); i++) {
        strings[i] = databases.get(i).getDatabase();
    }
    return strings;
}
public void openDB(String dbString) throws IOException {
    runner.openDB(dbString);
}
public String getCurrentDb() {
    return runner.getCurrentDB();
}
}
View.java
public abstract class View {
/**
 * void initComponents() -- Sets up the components
 * T readFields() -- reads the fields into an object of type T
 */
protected final JDialog dialog;
protected final String dialogName;
public View(String dialogName) {
    this.dialogName = dialogName;
    this.dialog = new JDialog();
    this.initComponents();
}
public abstract<T> T readFields();
protected abstract void initComponents();
public abstract void setListeners(ActionListener listener);
public JDialog getDialog() {return dialog;}
public void showForm() {getDialog().setVisible(true);}
public void hideForm() {getDialog().setVisible(
}
A concrete view (VBaseXLogin.java)
public class VBasexLogin extends UpdatableView {
private ActionListener listener;
private JButton connectButton;
private JLabel connectionLabel;
private JTextField hostField;
private JLabel hostLabel;
private JLabel passwordLabel;
private JButton pingButton;
private JTextField portField;
private JLabel portLabel;
private JPasswordField pwField;
private JLabel titleLabel;
private JTextField uidField;
private JLabel userId;
public VBasexLogin(String dialogString) {
    super(dialogString);
}
public void initComponents() {
     Boilerplate code for view
}
@Override
public void setListeners(ActionListener listener) {       
    pingButton.setActionCommand("PING");
    connectButton.setActionCommand("CONNECT");
    pingButton.addActionListener(listener);
    connectButton.addActionListener(listener);
}
/**
 *
 * @return
 */
@Override
public BaseXCredentials readFields() {
    return new BaseXCredentials(hostField.getText(),portField.getText(),uidField.getText(),pwField.getPassword());
}
@Override
public void updateFields(String[] updates) {
    connectionLabel.setText(updates[0]);
}
Command.java
public interface Command {
public void execute();
}
A concrete command (BaseXLogin.java)
public class BaseXLogin implements Command {
private final View basexLogin;
private final Model model;
private final VFrontOfHouse foh;
public BaseXLogin(View basexLogin, VFrontOfHouse foh, Model model) {
    this.basexLogin = basexLogin;
    this.model = model;
    this.foh = foh;
}
@Override
public void execute() {
    try {
        BaseXCredentials credentials = basexLogin.readFields();
        model.createSession(credentials);
        basexLogin.hideForm();
        foh.enableQueryRunner();
    } catch (IOException ex) {
        JOptionPane.showMessageDialog(null, "I/O Exception: "+ex.getMessage());
    }
}    
}
The 'main' app tying it all together:
 package consolemvc;
import Commands.*;
import Entities.View;
import consolemvc.views.refactor.VBasexLogin;
import consolemvc.views.refactor.VFileChooser;
import consolemvc.views.refactor.VFrontOfHouse;
import consolemvc.views.refactor.VImportVP;
import consolemvc.views.refactor.VQueryRunner;
import consolemvc.views.refactor.VVPDataBaseSelector;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ConsoleMVC {
/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    // TODO code application logic here
    try {
        // Set System L&F
    UIManager.setLookAndFeel(
    UIManager.getSystemLookAndFeelClassName());
        } 
    catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
           // handle exception
    }
    // Create the controller
    final TopLevelController controller = new TopLevelController();
    // Create the front of house view
    final VFrontOfHouse frontOfHouse = new VFrontOfHouse();
    // Create the model
    Model model = new Model();        
    // Create the views
    View login = new VBasexLogin("BAESXLOGIN");
    View queryRunner = new VQueryRunner("XQUERYRUNNER");
    View fileChooser = new VFileChooser("FILECHOOSEROPEN");
    View vpImport = new VImportVP("VPIMPORT");
    View dbSelector = new VVPDataBaseSelector("VPDBSELECTOR");
    // Set the views up in the controller
    controller.addView("BASEXLOGIN", login);
    controller.addView("XQUERYRUNNER", queryRunner);
    controller.addView("FILECHOOSEROPEN", fileChooser);
    controller.addView("VPIMPORT", vpImport);
    controller.addView("VPDBSELECTOR", dbSelector);
    // Set the commands
    // The Database selector
    controller.addCommand("SHOWVPDBSELECTOR", new ShowDBSelector((VVPDataBaseSelector) controller.getView("VPDBSELECTOR"),model));
    controller.addCommand("SETVPDB", new SetVPDatabase((VVPDataBaseSelector) controller.getView("VPDBSELECTOR"),model));
    // Basex Login screen
    controller.addCommand("SHOWBASEXLOGIN", new ShowBaseXLogin((VBasexLogin) controller.getView("BASEXLOGIN")));
    controller.addCommand("CONNECT",new BaseXLogin(controller.getView("BASEXLOGIN"), frontOfHouse, model));
    controller.addCommand("PING",new BaseXLogin(controller.getView("BASEXLOGIN"), frontOfHouse, model));
    // The VP Import Data screen
    controller.addCommand("SHOWVPIMPORT", new ShowVPImport((VImportVP) controller.getView("VPIMPORT")));
    controller.addCommand("SHOWFILECHOOSER", new ShowVPImport((VImportVP) controller.getView("VPIMPORT")));
    controller.addCommand("IMPORT", new ImportVPData((VFileChooser) controller.getView("FILECHOOSEROPEN"),
            (VImportVP) controller.getView("VPIMPORT"),
            model));
    // The XQuery Runner
    controller.addCommand("SHOWXQUERYRUNNER", new ShowQueryRunner((VQueryRunner) controller.getView("XQUERYRUNNER"), model));
    controller.addCommand("RUNXQUERY", new RunQuery((VQueryRunner) controller.getView("XQUERYRUNNER"),model));
    // Set the model
    controller.setModel(model);
    // Link controllers with view, and the frontOgHouse
    controller.initiate(frontOfHouse);
    // And fire up the frontofhouse in the EDT
    SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        frontOfHouse.addListeners(controller);
        frontOfHouse.setVisible(true);
    }
    });
}
}