Java MVP and Biscotti

December 13th, 2010 by Kevin Spaeth Leave a reply »

The Difference Between MVC and MVP

MVC was first described in 1979 by Trygve Reenskaug, then working on Smalltalk. Trvgve found a way to separate the applications he was writing into different layers. Each of these layers had a singular responsibility. In the same way as organizing your closet brings order into your bedroom, Trvgve brought order to his applications. The shoes went on the shoe rack, shirts were hung on the rack, pants were folded in a drawer. Getting dressed in the morning becomes so much simpler when you know where everything is and don’t have to hunt for a belt!

The basis of MVC is to separate an application into a Model, a View and a Controller. In the web world, there are several frameworks that operate on this principle. If you’ve used Struts or Struts2, or if you’ve used JSP pages with controller servlets, then you’ve written an application that uses MVC principles. The view is the JSP page that has html, buttons, input fields, checkboxes etc. The controller is the Struts action, or the controlling servlet that does things when a form is submitted then forwards the request to a new view to be displayed. Finally, the model is the data that the view displays. In Stuts, this would be your form object.

The key with MVC is that the controller does something to manipulate data in response to the user submitting a form. The view page then reads the new data from the model and displays it on a page. So there is this love triangle where everyone deals with everyone else. This is called coupling – no pun intended.

Recognizing that this coupling is bad, in 1990 new pattern emerged called MVP or Model View Presenter. This pattern does not let the view talk to the model. The controller will update the model, then it will take the data from the model and give it to the view. The view knows nothing about the model and vice versa. Since the controller has so much more responsibility, it gets promoted to title of presenter – if only it were that easy to get a new title in corporate America! The major advantage to using MVP is that the reduced coupling makes it easier to pull the layers of code apart and test them separately to find bugs. More about this later.

The Observer Pattern (and why it’s overused)

Implicit with MVC is also a pattern called the Observer Pattern. Java uses the Observer pattern extensively with their GUI’s. You have a class that registers to receive notifications when anything changes with a widget. This is sort of like following someone on Twitter. Whenever someone Tweets, all 100 of their followers get the Tweet, the Tweeter does not have to know who is following them for this to happen, it’s automatic.

In the same way, the view in the MVC would become an observer of the model layer. When data in the model layer changed, the model layer would “Tweet” to anyone who was listening that it changed (remember the view is following the model on our Twitter). The view then knows that the model changed and will pull a fresh copy of the data.

This is a great pattern and highly popular just like Twitter is popular. However, the challenge is that we don’t have an easy to follow execution path. The person doing the Tweeting doesn’t know explicitly who their Tweets are going to unless they check their followers, but they have oh so many followers… How do we know that Grandma got the message the we need $100 for Christmas this year? The easiest way is to just call Grandma and tell her that.

In the same way, use the Observer pattern, but don’t rely on it for everything. If so, you will have to exert extra effort in debugging to figuring out who gets notified of changes and when. Sometimes you need to just pick up the phone and call Grandma.

Developing in MVP

There is a great article on using MVP with Java GUI (Swing). Don’t let the heading of the article fool you, the presenter updates the view, so it is an MVP pattern. The writer has a great sample application that spells out the MVP pattern in action. The only problem I have with this code is that it isn’t as clean and extendable as I would like to see it. I think it’s a great start, just not the end of the path.

Bringing Web Applications Back to Swing

You will read it over and over again that MVC (and MVP) naturally lends itself to web applications. The act of clicking on a link or submitting a form makes the browser go to a new url or call a url with new parameters. The act of calling the url invokes a controller that will do something with the request. The controller then forwards the request to an html page that will display some data it got from your data layer (or that your controller gave to your view layer). Java has matured to the extent where this process happens really easily without much effort from the programmer.

Not so fast with Swing. There aren’t urls that connect to controllers, or jsps being return to a browser for views. In Swing, you have widgets that act as a view and you mostly write controller code to respond to events and change what the widgets display. But this is messy. There is no clear separation of converns. You have one class doing some of everything.

So, one solution is to bring the web back to swing. Have something like a url that you can call with your forms and buttons. Have a good presenter that automatically passes data to a POJO model object just like Tomcat or JBoss or any other web server does.

This is where Biscotti comes in. It is a very light framework that centers around the concept of control and automatically passing data between your well defined layers of an MVP pattern. In Biscotti, you have a models, views, and presenters. I’ve also added an extra player called the Director. The Director’s job is to perform as a web server, or a director on a movie set. It tells a presenter to handle a request. When the Presenter is done with the request, it tells the Director and the Director will decide if any other Presenter needs to do anything.

Getting Started with Biscotti

Programming with Biscotti is really easy. There are only a few special interfaces and classes that you will need to implement. You should be able to have a basic application with a few screens running within 30 minutes. Let’s get started…

Biscotti Test PackageOn the right, you will see will see the main Java files for the TestBiscotti application that we’ll be going through. There are model, view, and presenter classes which you already know about. Finally, there is a director class that we’ve added as we port over our web ways of thinking.

Here’s a quick synopsis of the application. When you start the application, you’ll see a login dialog prompting you for a username and a password. Enter whatever you want and click on the submit button. The login prompt will close leaving you with another window displaying a congratulations message. That’s all there is to this sample application to keep it short and sweet. Because we have two views, the login and main screen, we will have two view classes, LoginView.java and MainView.java. Think of these files as your html or jsp files in a web application, they contain your elements and layout information.

I’ve also chosen to have two presenters and two models, one for each view, to keep things simple. There is nothing preventing me from having just one view or one model, so feel free to find what number of presenters and models work for you.

Main.java

I hid it from you in the package view, but yes, there is a Main.java which starts the application. See the code below. I know, super-complicated right? The main method’s only job is to let the Director have at it.

public class Main {

    public static void main(String[] args) {
        Director.doInit();
    }

}

Director.java

Here is where the fun starts. The Director’s job is to direct. Make sure the actors are all on set when needed and to tell them what to do.

public class Director {

    static MainPresenter main;
    static LoginPresenter login;

    public static void doInit() {
        initMain();
        main.doInit();

        initLogin();
        login.doConnection();
    }

    public static void doMain() {
        main.doMain();
    }

    static void initMain() {
        if(main == null) {
            main = new MainPresenter();
            main.addView("main", new MainView(main));
            main.addModel("main", new MainModel());
        }
    }

    static void initLogin() {
        if(login == null) {
            login = new LoginPresenter();
            login.addView("main", new LoginView(login));
            login.addModel("main", new LoginModel());
        }
    }

}
  • Job #1 – make sure everyone shows up – notice that lines 20-22, and 28-30 create the required presenters, views and models if they don’t exist.
  • Job #2 – direct – lines 8 and 11 are the Director telling our presenters what needs to happen. The Director tells the presenters what to do, not how to do it. Anything that looks like doThis() in this file is the Director giving the presenters commands.

LoginModel.java

The LoginModel.java is just a POJO (plain old Java object) that has a username and a password. Nothing complicated there.

public class LoginModel implements Model {

    private String username;
    private String password;

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

MainModel.java

The MainModel.java is also really simple. I put a dummy variable in there called someData that will hold our welcome message. Put something more meaningful in there when you build your application!

public class MainModel implements Model {

    private String someData;

    public void setSomeData(String someData) {
        this.someData = someData;
    }

    public String getSomeData() {
        return someData;
    }

}

LoginView.java

The LoginView.java is a little bit fancier, but if you’ve worked in Swing it will be a piece of cake too. Lines 16-26 build the form elements and add them to our form. Lines 28-30 handle creating the JFrame or the window that will popup with our form. The special thing I do here is set the LoginView as the target of the submit button on line 20. So when the button is clicked, the method on line 46 will fire. This method submits the form back to the presenter – remember presenters handle user actions – and on line 48, tells the presenter to login. This is similar to a form posting to the url, the url is login – this will cause the presenter to fire it’s login method. More on this in a bit.

public class LoginView extends JPanel implements View, ActionListener {

    JTextField username;
    JPasswordField password;
    JButton submit;

    LoginPresenter presenter;
    JFrame displayFrame;

    public LoginView(LoginPresenter presenter) {
        this.presenter = presenter;
    }

    public void show() {

        setLayout(new GridLayout(3,2));
        username = new JTextField();
        password = new JPasswordField();
        submit = new JButton("Submit");
        submit.addActionListener(this);

        add(new JLabel("Username: "));
        add(username);
        add(new JLabel("Password: "));
        add(password);
        add(submit);

        displayFrame = new JFrame("Login Form");
        displayFrame.getContentPane().add(this, BorderLayout.CENTER);
        displayFrame.setSize(new Dimension(600, 130));
        displayFrame.setVisible(true);
    }

    public String getUsername() {
        return username.getText();
    }

    public String getPassword() {
        return new String(password.getPassword());
    }

    public void close() {
        displayFrame.setVisible(false);
    }

    public void actionPerformed(ActionEvent e) {
        presenter.submit();
        presenter.login();
    }

}

MainView.java

MainView.java is a very similar format to the LoginView.java. It isn’t submitting any forms, so it is actually a bit simpler. It has a label called dataLabel that will show our output message. Like LoginView, MainView also creates its own frame to show itself in.

public class MainView extends JPanel implements View {

    JFrame displayFrame;
    JLabel dataLabel;
    MainPresenter presenter;

    public MainView(MainPresenter presenter) {
        this.presenter = presenter;
    }

    public void setSomeData(String data) {
        dataLabel.setText(data);
    }

    public void show() {
        dataLabel = new JLabel();

        setLayout(new GridLayout(1,2));
        add(new JLabel("Here is the data: "));
        add(dataLabel);

        displayFrame = new JFrame("Main Pane");
        displayFrame.getContentPane().add(this, BorderLayout.CENTER);
        displayFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        displayFrame.setSize(new Dimension(600, 100));
        displayFrame.setVisible(true);

    }

    public void close() {
        displayFrame.setVisible(false);
    }
}

LoginPresenter.java

Here comes the most complex code in this example. Presenters do the most, and tend to have the most stuff going on in any MVP application. LoginPresenter has this Connection object which in this example is a dummy object, but has the ability to represent a connection to some data source, a data source that requires a login — like email.

LoginPresenter doesn’t have anything to do until we are logged in. So when the Director calls the doConnection method on startup, the LoginPresenter just shows the form.

public class LoginPresenter extends Presenter {

    Connection connection;

    public void doConnection() {
        views.get("main").show();
    }

    public void login() {
        LoginModel model = (LoginModel)models.get("main");

        if(connection == null) {
            connection = new Connection();
        }

        connection.setUsername(model.getUsername());
        connection.setPassword(model.getPassword());

        if(connection.isValid()) {
            // Bind the connection
            Session.set("connection", connection);

            // Close the view
            views.get("main").close();

            // Return control to the director
            Director.doMain();
        }
        else {
            // TODO: display the error message in the view
        }
    }
}

You probably remember seeing that when the submit button in LoginView is pressed, it called the submit and the login methods on this presenter. Where is the submit method? The submit gets handled by Biscotti. Just like submitting a form on the internet is different than just accessing a url, you must submit in your code from a view for Biscotti to copy the data from your view to the model, if you don’t call this method first, your data will be lost!

So, what does the login method do? It reads data from the model and sets up the connection object. Just as in above, it will bind the connection object to the session so other presenters can use it, then tells the Director to take control again.

MainPresenter.java

Finally the MainPresenter file! There are two methods here that the Director will call. The Director calls the doInit at the beginning. MainPresenter knows to show its view on startup with the code on line 4.

The second method is doMain. You will notice the Director calls this after LoginPresenter has done it’s work setting up the connection. MainPresenter will take that connection from the session and will copy some data from it into MainModel. The final step is to call the display method which copies the data from the model to the view (yes, Biscotti does this for you). No need to show the view, since it has been showing since startup.

public class MainPresenter extends Presenter {

    public void doInit() {
        views.get("main").show();
    }

    public void doMain() {
        // Populate our model with the data from the bound connection
        Connection connection = (Connection)Session.get("connection");
        MainModel model = (MainModel)models.get("main");
        model.setSomeData(connection.getSomeData());

        display();
    }
}

Conclusion

This is a simple application using the MVP design pattern and Biscotti. I’ve tried to highlight basic code flow and hit 90% of the code in these examples. If you have questions about the code I glossed over, submit a comment and I’ll get it answered.

Downloads

Biscotti library (jar file)

Biscotti example application (zip of Netbeans project)

Advertisement

Trackbacks /
Pingbacks

  1. Casinogamesfree.us
  2. Bustamante

Leave a Reply

You must be logged in to post a comment.