If you would like more details please let me know, or refer to the last lines of this question. I've already read a lot and I feel I'm turning something simple into something complicated and I still get stuck here and there, so maybe you can help me in those very specific points.
I'm using Netbeans IDE 7 and JDK 7, and no frameworks. The first Window is a JFrame and all other windows are JDialogs with modal=true.
Questions:
How do I correctly implement the MVC pattern with swing?
From the ideas bellow Which one is better: (A) or (B)? Or maybe another one... Why is it better?
(A)
Main:
MyModel model
MyView view(model)
MyView:
MyController(this, model)
(B)
Main:
MyModel model
MyView View
MyController controller(view, model)
when I click jbutton1 in MainFrame I need it to open the SettingsFrame for editing settings. where should I instantiate the View, the Model and the Controller of the SettingsFrame? In MainFrame Controller?
In terms of MVC organization and implementation, how should I handle more specific features that (apparently) lacks one or two of the MVC "legs" (either Model or View or Controller)? Should I create empty classes for them?
a. The implementation of a TrayIcon
b. A URL connection class (an HttpsUrlConnection which will update data in the main jframe and also upload/download files)
c. A Directory Monitor (which will update data in the main jframe and also use the urlconnection to download a file)
d. My own implementation of TableModel
e. json
How to correctly keep and use an object with settings through the whole application? I will need it's information in different places (Views, Models, Controllers) but it might be altered by user during the runtime). Is it a good idea to make this model a singleton?
What should I do when:
a. View needs some data from the Model?
What I'm doing: using the reference of Model which I keep in the View
b. View needs some data from the Controller?
What I'm doing: using the reference of Controller which I keep in the View
c. Model needs some data from the Controller?
Still didn't happen but I have no idea how to do correctly
d. Model needs some data from the View?
What I'm doing: pulling all my hair from my head...
e. Controller needs some data from the View?
What I'm doing: using the reference of the View which I keep in the Controller
f. Controller needs some data from the Model?
What I'm doing: using the reference of the Model which I keep in the Controller
g. One of FooModel, FooView or FooController needs data from one of BarModel, BarView or BarController?
What I'm doing: thinking of jumping from the highest building...
Any hints on how to know if I implemented MVC correctly? Should I process massive data in Model or Controller?
I'm also using a DAO, what I'm doing is: my model has a
ArrayList MyModel load()
method which creates an instance of the DAO and returns the ArrayList of Models returned by the DAO, and then sometimes I process this ArrayList of Models in the Model and sometimes I allow the Controller to process it. Is this a good practice or is there a better way? By Process I mean: iterate through the ArrayList and get the data from the models.
I Have a PasswordCheck jDialog to restrict access to some Views. How can I reuse it in terms of MVC, so that I can use the same PasswordCheck dialog for allowing/restricting access to different Views without doing a mess in the code?
Any other tips, hints, ideas, suggestions?
Context:
I'm required to develop a Java Swing MVC software in a short time, although by default I'm not a Java developer and not so used to implement the MVC pattern, specially in Java (I get the idea but sometimes it lacks me knowledge to implement the relationship between classes).
The applications is basically a monitor for local/online files with a JTable in the main frame to show this data. I'm using the new WatchService API to keep track of the local files and saving their info in a h2 database using a DAO, and them reload this data in the main frame jtable. I must also notify the user about new files (which for I'm using TrayIcon). For the online files monitoring/uploading/downloading I'm using HttpsUrlConnection and json. It may also allow Settings customization.
Thanks in advance for you time and help.
Have a look at Sun's (Oracle's) suggestions.
As one simplification, you could have each component (model, view, controller) register with a top-level application component to provide a single point of reference rather than individual references between each component (your A or B). The article I cite provides ideas for push and pull design; I'd recommend push as a more popular modern approach. Disclosure: I have experience with Java and MVC but not MVC in Swing per se.
where should I instantiate the View, the Model and the Controller of
the SettingsFrame?
Sure, yes, or in a top-level application component.
how should I handle more specific features that (apparently) lacks one
or two of the MVC "legs" (either Model or View or Controller)?
I would implement GUI-only pieces as your own GUI library. And purely algorithm/service pieces as a services library.
Should I process massive data in Model or Controller?
Data processing algorithms would fit nicely in a controller or even service library; your model should not do much processing at all beyond possibly data type conversion or validation.
How to correctly keep and use an object with settings through the whole application?
See my note on registration; a singleton may be appropriate.
Related
In my program the controller just hooks keypresses with a function.
So should ikeep a reference to it?
E.g.
keeping a reference
Model model = new Model();
View view = new View(model);
Controller controller = new Controller(model,view);
or no
Model model = new Model();
View view = new View(model);
new Controller(model,view);
Inside Controller
public Controller(Model model, View view)
{
this.model = model;
this.view = view;
view.setOnKeyPressed(this::doSomething);
}
public void doSomething(KeyEvent event)
{
System.out.println("key pressed");
}
Maybe I implemented the Controller class wrong and misunderstood mvc pattern. But with what i wrote so far there is no reason for me to keep a reference to the controller object.
I'm not sure this question is really answerable, as it is probably too broad and/or too opinion-based. However...
MVC is a very loosely defined pattern. It really goes back about 40 years (or more) to the very early days of research into GUI development at Xerox PARC. Since it's been around so long and its primary use case (GUI architecture) has evolved significantly, it has branched into a number of sub-patterns and variations. Consequently, you'll find that "MVC" means many different things to different developers. In particular, MVC in a web application environment is somewhat different (imo) to MVC in the context you are talking about, because in a web application environment it has to sit on top of the request-response cycle. The rest of this answer/discussion focuses on the original "thick client" version of MVC, in which the view and controller are both in memory within the same process,and can communicate directly (rather than via a request-response protocol such as HTTP).
For me, the definitive guide to MVC in a desktop GUI context is Martin Fowler's essay on GUI architectures.
I would say that "classical" MVC is characterized by:
Having three components:
A model, which provides access to the data, may provide mechanisms for registering listeners for notification of changes to the data, and has no knowledge of the presentation of the data
A view, which observes the data in the model and updates itself when the data changes (this distinguishes classical MVC from some forms of MVP)
A controller, which provides the "view logic": typically this means it responds to user input and updates the model (not the view) as a result
So the model should know nothing at all about the view and the controller. The view doesn't know anything about the controller, but needs a reference to the model so it can display the data, and observe the data for changes, updating the presentation accordingly. The controller also needs a reference to the model, so it can update the data according to user input. Usually, the controller also needs a reference to the view, as it typically needs to register event handlers with the widgets in the view in order to know about user input it has to process.
The driving force behind this design is to allow multiple presentations (think of presentations as a combination of a view and controller) of the data which are kept synchronized. The pattern achieves this by referring everything though the model: one presentation's controller might update the model; since all the views observe the model, they all see those changes and each responsible for updating themselves accordingly. The controller that changed the view does not need to know about any other views that may be observing the data in order to keep all views in sync.
Your application itself will certainly need access to the model; it probably needs to access the data, maybe modify it from external (i.e. not user-driven) factors, persist the data at shutdown, etc. Your application probably needs access to the view (it needs to display it somewhere, may need to dispose of it at shutdown, etc). Your application may or may not need access to the controller. In its purest form, once the controller knows how to observe the view for user events, and knows how to update the model, you never need to communicate with it again. (If you want to change states from "external" events, you do so through the model, not through the controller(s).)
Several variations of this idea have emerged (see Fowler). One popular one (which also have several variations of its own) is Model-View-Presenter. In this variation, the controller is replaced by a "Presenter" which takes on some, or even all, of the responsibility of updating the view. In one form of this (which Fowler calls "Passive View"), the view is completely free of logic and merely lays out the controls. The presenter processes user input, updating the view and the model when user input occurs on the view, and observes the model, updating the view if it changes. This variant has advantages in terms of testability and ability to debug, but there is arguably tighter coupling between the view and presenter than there is between the view and controller. (It is relatively easy to provide multiple controllers for a view; providing multiple presenters for a passive view gets much more complex, and the presenters usually have to have some knowledge of each other.)
JavaFX actually provides "out-of-the-box" support for this style of architecture, using FXML as a (usually passive) view, and providing convenient ways to hook into what it calls the controller (which is perhaps more of a presenter). JavaFX properties make it easy to write models which can readily be observed by a view or by a presenter as needed.
In practice, you'll usually find a hybrid of these works best in most cases. A medium-large scale application will use MVC/MVP-type patterns in multiple places, on multiple different scales. You will often find that it is convenient for the controllers/presenters to have some knowledge of each other and to communicate between them, in which case you will obviously need to keep references to the controllers.
So the answer to your question is probably just "it depends what you need". If you don't need a reference to the controller, there is no need to keep one. Indeed, in the standard use of FXML in JavaFX, the controller class is simply specified in the view (the FXML); the FXMLLoader instantiates the controller from that information and wires the view and controller together as needed. You often never even have a reference to the controller instance in your code at all. Though, as seen in this popular JavaFX question you can certainly get one if and when you need. In a completely "pure" classical MVC, all state change is made through the model, and the views observe it, so you would never need access to a controller. Fowler points out some nice examples where this doesn't work as cleanly as it sounds: firstly that some state, and associated logic, is really part of the view and has no place in the model, and secondly that the registration/notification mechanisms can make it very hard to debug your application.
You will need for a controller instance be created for you when a key is pressed on the GUI. So you will need it to be a Listener which listens to key presses.
Once you have a GUI listener registered, its the framework's responsibility to instantiate that controller and pass the view to that controller.
(So, you never need the handle to a controller - its handle is always with the framework.)
Next, when you are in the controller with the view, you determine which model to create or fetch based on the values in the view...
This is how all MVC's work...
I am trying to create a graphical flashcards app from scratch. I have a few questions:
a. I have used Swing to build some apps in the past, calculator app. But I felt that was a trivial application so I want to ramp up my skills as a Java developer.
b. I have been told that a gold standard is to build a small application that uses one of these: MVC, MVM, MVVM and so on.And since I am learning design patterns, I was hoping to use it in the application.
c. My classes are such:
A model: Flashcard.java(It has a list of answers, a list of
pictures, a question), A FlashCard Manager(to perform CRUD)
Different view classes: GUI interface
Controller: All the event listeners
App: To initialize the app
d. I have tried to read online examples of such a combination and what was proposed in for the Manager or DAO, was to have it connect to JDBC for the database. I am trying to simulate that by using a HashMap> for the same purpose.Is that correct or do I have to use JDBC or SQLite?
e. Also am I supposed to have a controller-view pair, that is for every JComponent that uses an event listener or a controller for windows( startup window, main application window, child windows)?
f. Also should the controller class be an interface for all these controllers?
I do not have code because I am still developing it but I just wanted to get a general idea. Thanks for answering my questions.
b. I have been told that a gold standard is to build a small application that uses one of these: MVC, MVM, MVVM and so on.And since I am learning design patterns, I was hoping to use it in the application.
This both right and wrong. Some API's simply don't support the notion of a pure MVC (or variation). Swing for example implements a form of MVC of it's own which is more like M-VC, where the model is separate, but the view and controller are bound.
Think about a JButton. Do you ever apply a controller to it? You can add listeners to it, you can even add listeners directly to it's model, but it has it's own internal control mechanism, which generates events based on keyboard and mouse interaction.
You need to beware of when a MVC might not be suitable or where the amount of work to implement a pure MVC is not worth the effort.
Having said that, you can wrap Swing UI's in another MVC layer, but you need to think about it at a different level. Instead of each controller been considered a "view", you look at the container, which might contain multiple controls and see it as the "view", which a controller then manages.
d. I have tried to read online examples of such a combination and what was proposed in for the Manager or DAO, was to have it connect to JDBC for the database. I am trying to simulate that by using a HashMap> for the same purpose.Is that correct or do I have to use JDBC or SQLite?
This is not an unreasonable idea, however, you want to ensure that the public interface remains constant. This would allow you to change the implementation at a later date to use JDBC or a web service without having to rewrite the code that depends on it
e. Also am I supposed to have a controller-view pair, that is for every JComponent that uses an event listener or a controller for windows( startup window, main application window, child windows)?
This will depend. I tend to avoid exposing individual components, as this exposes them to unwanted modifications (you may not want a controller to be able to change the text of a button for example)
As a general rule of thumb, I try to make the relationship between the controller and the view as vanilla as possible, meaning that the controller shouldn't care about how the view is implemented, only that it upholds the contract between the it subscribes to.
This generally means I have a functional view, which is contracted to produce certain events/data and allows certain interaction (from the controller)
f. Also should the controller class be an interface for all these controllers?
IMHO, yes. This allows a view/controller/model to be implemented differently, but allows the rest of the code to continue working with it without the need to be modified.
The bottom line is, implementing a MVC over Swing is not as simple as people think it is. It takes some planning and consideration, but it is doable.
For a more detailed example, have a look at Java and GUI - Where do ActionListeners belong according to MVC pattern?
Consider the below screen shot showing a custom application built using Java.
1) In this custom application, we can add People and Cars as shown in above screen in a "View Port".
2) I am trying to write a Plugin for this custom application which does the below
Reads all the Person object in view port
Reads all Car objects in view port
Reads all the attributes of person and car to see if there is a link, and produces
output if there is a link.
Now, i am trying to implement the plugin using below MVC model
Based on this model, i have placed all the view like JPanel, Buttons etc., in view file,
Button click actions in Controller. But when creating Models, i met up with a confusion.
In the plugin i create, i donot have direct access to any of the database tables. Instead the
custom application provides me below functions
- getObjectsInViewPort()
- getObjectType(object)
- getProperties(object) etc.,
Now, how do i design my model? should i just create some method in model which would use the above
inbuilt models and returns some result to my controller which then sent to view for update?
or please provide me how should i do the MVC in proper way in this scenario.
Simply start writing the model providing listeners, concentrate on the controller listening, invoking. Make abstract (mock-up) view classes that trigger events and such. Scenario based, with a "stories".
That would allow to write unit tests that play a scenario.
In a next phase take such a view class and extend it from JFrame or other GUI class. Or embed the abstract view class.
You are on a right track. To build a model, you don't have to have access to database.
1) Build your model
2) Call API functions from your model
3) Get the return result in your model
4) Give it to controller
5) Which in turn will present it to view.
Answer Updated
All business processing functions too will go in your model because this is your business model and not a POJO. Use data layer design pattern where you create POJOs to store your business data(API returned data) and then use them in your model classes to exchange with controllers.
I'm already using Guice for the data model of my app, and so far I'm quite happy with it. However, the GUI part is about to become a Big Ball of Mud. I find it hard to use Guice here, because Swing components and models are tightly coupled, and often force a certain initialization order.
My application consists basically of a header with a lot of filters, a central and quite complex JTree component, and a lot of actions (e.g. from a JPopup), menus, dialogs, wizards etc. The main problem is that I have a lot of coupling between the components and actions (e.g. complicated validations, tree updates...). Could you give me some advice how to structure that GUI with Guice?
I'm aware of libs like GUTS, but the documentation is really thin, I'd rather avoid to add another dependency to my project and to learn another API (e.g. I don't know the Swing Application Framework).
I'd rather suggest a proper MVC, even better Presentation Model - View - Controller. Separate your code properly and Guice will fit in naturally. For example:
View classes should have a building part which draws the static content (labels, the tree, buttons, etc) and updating code which reacts to changes in the Presentation Model. All the action listeners should invoke some code on the controller. Both the Presentation Model and the controller should be injected by Guice, like all the other dependencies.
This organization would allow for easy testing with replacing the View with some testing code which will listen to changes in the Presentation Model and invoke actions on the controller.
I would advise to look at Guts-GUI.
It is a Swing UI framework based on Guice dependency injection model.
I think the problem is probably the overall architecture. You probably want to see if you can refactor the application to be simpler and more modular. Like Boris recommended, I would also suggest using the Presentation Model pattern - search for Martin Fowler and Karsten Lentzsch - and the JGoodies library.
For the problem with Actions, see how the Swing Application Framework and Netbeans Plaform handle them. For example, if an Action is used in both a view and a menu, you might want to make it available through a global map.
We have recently started on GUICE with swing. Here's what we have done which may be of help to you.
a. When you want to inject a model into a table/tree you could inject a model provider instead and do a provider.get() to get the model in the contructor.
for example
public class Mytable extends JTable {
public Mytable(Provider<MytableModel> modelProvider) {
this.setModel(modelProvider.get());
}
}
b. You could make a model generic and make use of the same model in different tables.
c. The model could have a handle to datasource which could be injected by a factory where necessary with assisted inject. Number of examples available in stack overflow.
d. Your model could be a flexible data structure which uses model to return the relevant cell/leaf/other value.
e. When you have actions, you inject actions in your component builders and attach them to relevant components.
f. Use #Singleton annotation where you have a shared object such as model injected in 2 different objects, such as action and the component.]
g. Use custom scope when you need to use number of instance sets of objects. Custom scopes are great for this as it keeps the code really clean.
Hope the above helps...
I would like to start a discussion on separating pure model and UI model in Spring 3.
By pure model I mean main object/objects that I retrieve from database, let's say some "user account". It contains enough info to display it in HTML view or to pass it to web service.
By UI model I mean all the auxillary stuff I need in UI to work with that object. E.g. if a "user account" has "state", then I need to fetch all the "states" from the database for, say, a combo box. The views are tricky and in some cases they require more information, in others - less. It would also be nice to be able to alter some lists by adding items like "Select all", which is pure UI stuff (and not quite conveniently done from view template).
I heard there's so called Model-View-ViewModel pattern, which seems to address these issues, but I have never tried its implementations.
The solution I use right now is to break logics into two services - one for pure model and one for UI model. It looks like this:
#RequestMapping(value="app/user_accounts/{id}")
public String getUserAccount(#PathVariable("id") String id) {
service.getUserAccount(id); // Gets main object and puts it into model
presenter.formUserAccount(); // Gets all classifier for main object's properties
return "user_account";
}
What I dislike about this is that the view and its so-called view model are not attached to each other. I can call presenter.formUserAccount() and return totally unrelated view name.
Another approach I see is similar to Spring controller annotation. We have classes annotated as #ViewModels and methods which map to view names. An interceptor finds and executes these methods before rendering a certain view. These seems elegant enough, but requires much code writing.
How would you solve this problem?
I have been thinking about this in the context of Grails, which is based on Spring MVC. My approach is to use Command Objects as View Models as it gives you the data binding and validation features that you would want in a View Model. With Command Objects you can abstract your "Pure Model" (or Domain Model) out of your View by using the Command Objects to map the view properties onto you domain objects.