<< "Best Tool for the Job" is a Myth | Home | Choosing the right Tech for a New Project >>

Some Thoughts on Swing, MVC, and Available Application API's

Seperating Behavior From Markup

Sometimes while developing I get crazy thoughts and decide to completely go against the norm, mix things up, and do something that someone else at some point tried and already realized what a horrible idea it was. I just feel like I have to put myself through that same pain to learn, I suppose. Of course, I'm developing a large Swing application so my pain threshold is already pretty high.

It seems that as of late there has been a bit of a surge in the Swing application framework scene. Probably the two most notable and newest contributions are JavaBuilders and Griffon. Of course one cannot discount Spring-RCP, Swing Application Framework, or even JIDE Software's Desktop Application Framework. Notable mentions go out to Eclipse RCP and The Netbeans Platform although I'd put these in a separate category from the rest. They seem to me like they are targeting a bit of a different audience than the others. There is a decent article on selecting the best framework for your task here. But I don't want to talk about each of these are try and decide which to use. Speaking specifically about the first few mentioned, as they are so new, it would be tough to commit to one for any serious project until they have proven themselves and gained more traction as at that point their development would be less likely to stall.

What I want to discuss is how can we benefit from some of what these frameworks offer without buying into the whole thing. And the main concept I am choosing to talk about today is separating behavior from markup. That sounds a bit like webapp-speak as you'll generally hear JQuery fans (I am one of them) say the same thing. But in Swing, I feel like it is as important and both JavaBuilder and Griffon attemt to do just that; remove the markup, or UI generation code (View), from the (C)ontroller and (M)odel.

JavaBuilder uses a YAML file for UI declaration. See this for an example of the YAML markup. It works very well and completely removes all the new JTextField()'s and new JButton()'s and all the nastiness that can be laying out components. Although with MigLayout, which JavaBuilder uses by default, and Design Grid Layout, which I used today and found it quite cool but somewhat limiting, layout issues are close to being behind us.

Griffon uses Groovy's SwingBuilder and all the UI generation code is done in a FooView.groovy file while actions are defined, generally, in a seperate groovy file, as well as controllers. Geertjan Wielenga has a slew of Griffon articles. One of his first can be seen here. It will give you a great overview of Griffon if you are unfamiliar with it.

But how can we remove the view code from controller code without these frameworks? And how important is it that the two areas of concern are really separate from each other or how loose or tightly coupled they may be. My quick answer is with inheritance and tightly coupled is ok. Blasphemy! Tightly coupling view and controller code is so 1990's. Composition is the way to go. Well, this is where me learning from my own painful experiences comes into play. And quite possibly where you stop reading.

So I'll drum up a quick sample to try and get my point across.

public abstract class AbstractLoginForm extends JPanel { private JTextField usernameTextField; private JPasswordField passwordTextField; private JButton loginButton; public AbstractLoginForm() { DesignGridLayout layout = new DesignGridLayout(this); setLayout(layout); buildUI(layout); } private void buildUI(DesignGridLayout layout) { usernameTextField = new JTextField(20); passwordTextField = new JPasswordField(20); loginButton = new JButton("Login"); loginButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { login(); } }); layout.row().label(new JLabel("Username:")).add(usernameTextField); layout.row().label(new JLabel("Password:")).add(passwordTextField); layout.centerRow().add(loginButton); } public abstract void login(); public JTextField getUsernameTextField() { return usernameTextField; } public JPasswordField getPasswordTextField() { return passwordTextField; } public JButton getLoginButton() { return loginButton; } }

The things to notice about the above class is that it is abstract. There is no behavior in the code at all. It is markup/view code and the event method for login is abstract. This is because the behavior will be implemented in the implementing class which is what we have next.

public class LoginForm extends AbstractLoginForm { public LoginForm() { } public void login() { String username = getUsernameTextField().getText(); String password = getPasswordTextField().getText(); // do some login stuff here } }

In the real world you wouldn't get password text with getText() and you would probably pass the info to a service class that checked the credentials. The thing to notice about this class however is how much simpler it is to see what the behavior will be. We don't have to wade through mass amounts of UI creation code to really see what is supposed to happen. I know, all this build up for this tiny example. In retrospect this isn't even that tightly coupled. The view (abstract class) could easily be reused for a different login implementation. The nice thing is no reflection was used, no extra IO reading external markup files, and everything is Java. And the best part? No third party libraries to make this happen. I did use Design Grid Layout for this example only because its what I have been testing with today. But you could just as easily used GridLayout.

My point isn't that all these other frameworks are useless. My point is that most of them are too new to invest in when you need to get something done now and there are alternative viable solutions that just use core Java. I'm hoping for some feedback, good and bad, regarding this. If anything could be done better but with the same principles in mind I am all ears.

Tags :


Re: Some Thoughts on Swing, MVC, and Available Application API's

What about using an action instead of an ActionListener and injecting them?

Re: Some Thoughts on Swing, MVC, and Available Application API's

What about that? In my trivial example that would completely negate the need for a separate class to create the UI since the Action implementation would be all you need to perform the login.

For menu items and tool bar buttons, action classes make a lot of sense. For form actions, I prefer anonymous inner classes that call event methods because you typically won't need to reuse that particular event.

Re: Some Thoughts on Swing, MVC, and Available Application API's

You're talking about MVC but I don't see any reference to your Model. Your controller code is in the UI which isn't great. In a clean MVC solution your UI sends an event to your controller which then uses the model to manipulate the UI.

Re: Some Thoughts on Swing, MVC, and Available Application API's

Well, it is sort of in the UI. It is technically in the implementing class of the Abstract class that creates the UI, and that is sort of my point. How important is this seperation and how can we get something close in existing apps without buying into frameworks?

I don't believe in total manipulation of the UI through the model anyway. But in kind of depends on what "model" we are talking about. In web dev, the model is generally POJOs or Value Objects, or Java Beans. In Swing a model is generally a mediator between your POJO and your controller/view. ListModel, TableModel, TreeModel, etc.

This might make for another good article.

Re: Some Thoughts on Swing, MVC, and Available Application API's

I have been working on an Open Source EMR/Healthcare Information System for 2.5 years and as a Swing application (RMI/JBoss/Hibernate/PostgreSQL) all the business logic is completely separated from the GUI.

The UI is defined in the database and the Swing clients are built on the fly using a hierarchy of panels, menus, toolbars, controls.

All of the client side business logic is written in a Controller which never directly refers to the swing components - instead there is a Model (which can be persisted) bound to each set of UI components and the Controller either interacts with the Model or uses a Mediator pattern to send any commands to the UI. But for the most the controls are bound to the model so that interaction is minimal and just for important actions like populating a table or closing the form.

JGoodies does all the hard work to layout the controls on the form in well aligned columns

So a controller that for instances places a patient order looks like this Controller

Re: Some Thoughts on Swing, MVC, and Available Application API's

I've tried this approach once also. A layer that does the UI and one that does the logic. I'm not sure about the results. It at least removed, as you state, all the hassle around the separation while allowing separation. On the other hand... You could also separate horizontally by using action methods and thus moving the code to a separate area. I wrote a utility clas called "SwingEventDispatcher" that automatically wires-up components and methods based on the component's name and event. This completely removed the need for inner classes. E.g. SwingEventDispatcher.wrap(new JTextField(), "name"); SwingEventDispatcher.wrap(new JButton("ok"), "okButton"); public void name_changed(...) { ... } public void okButton_clicked(...) { ... } But then you end up with a visual basic style of coding. And you still have to do all the resource handling yourself. I'm simply not sure (still after 8+ years of developing a large ERP swing application) where to go. Same goes for layouting; still haven't found the wholy grail.

Re: Some Thoughts on Swing, MVC, and Available Application API's

One major problem with this approach is that it does not make testing easier than having both view and controller in one class: unit testing is exactly as difficult in both cases.

One main advantage in separating View and Controller is that you can easily unit test the controller code without needing the UI, but this is possible only by composition...

Or one other option could be (I try to follow the same strange path you mentioned at the beginning of your post;-)) to reverse inheritance: have the controller has the abstract parent and the UI as the child. Thus you can unit test the controller by subclassing it and hard-code mocks for all abstract methods.

Would it make sense?

Re: Some Thoughts on Swing, MVC, and Available Application API's

Clean and simple solution for "not-so-enterprise" applications. I find the approach very useful - as long as one can't use a ui-framework and maybe additionally a injection-framework for some reason.

Add a comment Send a TrackBack