Swing MVC - Event Propogation and Data Sharing - java

I am trying to apply MVC pattern in swing application. However I am facing two major issues given that you have nested hierarchy of panel e.g. Parent -> Child - > Grand Child -> Grand Grand Child.
Issue 1: How to transfer the data between controller and view when you have such a hierarchy? If I go and pass data from parent to child then there will be lots of duplication and if I change one child all the parents will require change. I don't want views to directly access data from db and I want the data to be transferred to views through controller only.
Issue 2: How to propagate the events from view to controller in such a hierarchy?
I am thinking of using PropertyChangeListener. View will firePropertyChange event if any action has to be taken by controller. Controller will listen for these events and perform some action. But again if I do this for hierarchy then there will be code duplication.
I have three ideas that could be useful:
To use controller for each Panel but this in this way I will end up with lots of controllers.
Use Mediator design pattern that will provide the communication between views and controller.
Use a Central Reciever & Notifier that will listen for all property change event from views and will notify controllers who are interested. but this will only solve my second issue:
Please refer to below diagram to have a picture of 3rd idea. In case of 2nd one, Mediator will come in center.
Please evaluate and let me know if anyone has implemented such issue in a better way.

I have a suggestion for your issue 1:
You can have a ViewModel that contains a property of another View Model. And on your controller method you just need to receive the parent ViewModel because the model binder will bind all properties for you.
public class GrandChildViewModel{
public Int32 SelectedDropDownItem { get; set; }
public List<Foo> ListOfFoo { get; set; }
}
public class ChildViewModel{
public String Name { get; set; }
public Int32 Age { get; set; }
}
public class FatherViewModel{
public ChildViewModel Child { get; set; }
public GrandChildViewModel GrandChild { get; set; }
}
This is an example of the hierarchy. Your View will reference FatherViewModel only. And your controllers will receive FatherViewModel also.
The modelBinder will automatic do its job, if you create the HTML like:
#Html.TextBoxFor(m => m.Child.Name)
It will render the input:
<input type="text" id="Child_Name" name="Child_Name" />

Issue 1: How to transfer the data between controller and view when you
have such a hierarchy? If I go and pass data from parent to child then
there will be lots of duplication and if I change one child all the
parents will require change. I don't want views to directly access
data from db and I want the data to be transferred to views through
controller only.
How about ignoring the hierarchy and going for a more linear approach by registering views with a relevant controller ? The data could be had through a model from where changes would be triggered through an Observer or Listener pattern.
With this you won't have any duplication occurring. Everything would be centralized in a model or a series of models. The controller, or controllers could run a notify on a list of registered views after a user action or outside event has occured.
Also, views should definitely not access the data source as you say. There should be at least one layer of abstraction here. If your controller uses the mediator pattern what I'd do is handle this by forwarding requests to an interface in an extra data layer.
Thinking further, I don't think if it would be a good idea to have registration done through the view. So I'd keep this separate. Initialize views by hand or find a way to iterate through views that you need. Perhaps get your views through a kind of factory which automate this step.
Issue 2: How to propagate the events from view to controller in such a
hierarchy? I am thinking of using PropertyChangeListener. View will
firePropertyChange event if any action has to be taken by controller.
Controller will listen for these events and perform some action. But
again if I do this for hierarchy then there will be code duplication.
Again, you could adopt a linear approach. When a view is registered the Controller could add it's listeners to it. Or you could have the view send some semantic style messages (ex: doAction("Save")) which can be handled through a dispatch mechanism. Will leave you to decide how parameters could be forwarded.
Would PropertyChangeListeners be needed ? I mean, do you need that kind of granularity ?
I have three ideas that could be useful:
To use controller for each Panel but this in this way I will end up
with lots of controllers. Use Mediator design pattern that will
provide the communication between views and controller. Use a Central
Reciever & Notifier that will listen for all property change event
from views and will notify controllers who are interested. but this
will only solve my second issue:
This sounds vaguely like HMVC. With this approach you have triads of model-view-controller for each subsystem. It's an interesting idea but could be messy and it's not clear how the hierarchy is supposed to work out and how coordination/subordination is achieved.
Perhaps you could have a fourth neutral class for each module/subsystem of your app where you could plug in a view, model and controller with an Exception thrown if one of them is missing or incorrect.
Or, following this idea of a central notifier, you could have a central Controller acting as a routing mechanism to other feature-specific controllers or more elementary actions. How a message is rerouted to these is up to you. Watch out for threading as centralization will make the design of this class essential.
Whatever you do, try to make things as simple as possible. You should be able to have a test view with model and controller up without too much fuss.

I was facing similar issue when I ended up using this HMVC Pattern. Yes you are right in the sense that there will be lots of controller. But it is also true that it will provide you clear separation of concerns in the code. You can limit number of controllers by creating some application specific, high-level composite widgets. In this case, hierarchy can be limited upto 2 or 3 level at max and controllers can be chained to delegate events to any of the parent/child.
Once you load the data from server, you could also maintain Session map to get some relief to have quick and easy access to frequently required data - however I don't favor it much.
The pattern works quite well if the developments team understands and follows it properly.

Related

JavaFX, FXML and controllers: switching scenes, maintaining scene data

Hello programmers and architects!
I'm new here and... I think my english could be... terrible! :-D
So... be careful with me... please.
I have an architectural question about JavaFX, FXML and the various methods to switch scenes, mantaining data among all scenes...
I have used a personal solution and I need to know if it's an acceptabile solution or not (at the architectural level).
I'll try to explain my solution.
I have used a sort of "inverse" of Observer Pattern: instead use many observers for each observable, I've used one observer (a specific Class) and many observables (all controllers).
So, when it's time to change scene, the Controller of the current scene notifies to Observer to do that. Observer removes old scene and loads the new one.
Some details.
I have created a class named SceneObserver that implements java.util.Observer.
I use SceneObserver in order to:
register SceneObserver as observer of all my controllers
load a specifc FXML file
create a new Scene with only an AnchorPanel as root element ad use the root.getChildren().add() method to append to the root element the loaded FXML
set a specific controller for the FXMLLoader (I have NOT used "fx:controller" inside the various FXML.)
All my Controllers extend java.util.Observable (this is an example).
When a certain type of situation happens in a scene and it's necessary to switch scene, the scene notifies to SceneObserver the change (Observer Pattern), SceneObserver destroys the old scene and loads the new one.
In other words I'm using only one observer to observe all controllers (the inverse of the Observe Pattern).
All works, but I know that this is not enough!
So, the question is: speaking at the architectural level, is this one an acceptabile solution?
I know, this is not the only one and surely there are others better ways, but... what about this one?
Why have I used this solution?
Well, two reasons:
load only necessary FXML (more rapid application)
leave controllers decoupled
Thanks to all and... sorry for my english :-(
Well...
after that I've read and tested different solutions, that I recommend to read:
https://web.archive.org/web/20160316234709/
https://blogs.oracle.com/acaicedo/entry/managing_multiple_screens_in_javafx1
https://github.com/google/guava/wiki/EventBusExplained
http://eventbus.org/
I've decided to realize my own solution, using a more simple approach: a Router Pattern.
My goal was to decouple the various controllers in my JavaFX application, leaving possibility to communicate among their.
Instead to use event handler, parameters or obsolete event-bus, it seems that a simple Router Pattern can solve the issue.
Every controller must know the Router (obviously a singleton) and Router must know every controllers. In this way I have simply trasformed a many-to-many class relation to one-to-many without nothing of "too magic" and I can send every kind of messages among controllers. In the small:
In the Router I declare one property for each controller and a set method in order to link exactly that instance of controller, like this:
public class Router {
private MainCtrl mainCtrl;
...
protected void setMainCtrl(MainCtrl mainCtrl) {
this.mainCtrl = mainCtrl;
}
}
Then, in each controller I declare a Router object (router) and in the initialize() method of each controller I write this (router must be a singleton!):
public void initialize() {
router.setMainCtrl(this);
...
}
That's all.

mvc where to keep the reference to controllers?

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...

Does the View observe the entities or does it observe the services?

I am used to Web MVC and I am now implementing it for the first time in Java and I am a bit confused as to what the View should observe, should it observe the individual entities or should it observe the service layer which obviously sit on top of the entities so when there is a change the service can notify the view and then my entities would not need to also be observable?
Thanks.
Your view should just be a representation of your objects and services. It should not have too much logic on it, just a way of representing your models. What framework are you using? As some encourage more some practices than others. If done correctly you could have two different views for example, displaying the same data but with a different presentation.
The view should only interact with a controller to prevent too much entanglement. The controller can be an observer of the view reacting to events happening inside the view and delegate it to the model layer. In no way should the view be able to modify/manipulate anything in the model layer. The view should be updated with data the controller provides. You shouldn't try to circumvent the controller and go directly to the model layer from inside the view. It might be tempting and seem logical, but at the end you will pay the price for it. Ending up with to much logic inside the view and the controller not having any real control at all.

In HMVC how to send model change event to multiple views?

I can see several ways of doing this.
Have a reference to a single controller in the model. Model sends event to this controller and other controllers get to know it through the hierarchy and passes on to views
Have all interested controllers be listeners on the model (the model has a list of listeners ). The view gets to know the change through the controller
Have all interested views be listeners on the model. ( The view gets to know the change directly)
Which is appropriate and why?
your third Option is old school. The views get notified by the model, and the view decides how to handle this. It's okay but other options are better.
your second option sounds good. The views get notified by the controller(make sure you have different controller for updating the views and updating the model). So the controller can modifiy the events before passing them to the view. The controller can hier customise the Data for the views. the View shouldn't do this, there job is only to show something(in option three the views have to do this).
your first option is a small improvment of option two with a hierarchy. It's may be better in a complex scenario, to filter the event passing. But normaly this will blow up the overhead. So it is harder to read.
I would choose option two. It's the best trade of simple code and the option for complex actions.

Apply the MVC pattern to an existing application

This is a follow up question to The MVC pattern and SWING. I am trying to implement the MVC pattern in an existing piece of code. The existing code creates a JFrame which acts as both the view and the controller. The JFrame has a table, and the table's model is an adapter to a custom data model. Whenever the user performs an action, the model would be updated by doing something like the following:
CustomDataTableModel cdtm = (CustomDataTableModel) DataTable.getModel();
CustomDataModel cdm = cdtm.getModel();
cdm.delete(1);
I've tried to visualise how it currently works, but I've also visualised how I imagine the relationships with the future controller and model should be.
Now, my question is simply whether I can continue using the model as it is now? Could I implement the following and still "adhere" to the MVC pattern?
The user selects an element in the table, and clicks on a delete button.
The view delegates the action to the controller.
The controller access the table through an accessor on the view, and performs the update.
The model, when it is updated, notifies the JTable that it has been changed.
If any other components in the view displays data from the table, then this could be solved by registering listeners on the JTable's table model.
Update 1
I've been thinking about the existing code in light of the MVC pattern, and I've redrawn the relationships a little. The point is that the controller is the behaviour of the view, thus the controller updates the model when users do stuff, and the view listens for changes in the model. However, nothing in the MVC pattern stops the view from listening to the model through a tablemodel - right?
Now, the user clicks the add button. The view notifies the controller that the add button has been clicked, and the controller takes care of creating a new item by invoking some method on the model. The view is registered as a listener on the model (through a table model) and updates its view. The controller may also be a listener on the model in case it needs to take care of disabling or locking fields. Have I not achieved what the MVC is all about; separation of concerns? As far as I can see, I've even introduced the adapter pattern to decouple the view even more from the model? It is late and I am tired, so that might be why it makes sense :-)
In the general sense, I would advise you the following:
take a look at JGoodies Binding,
it is not MVC but uses the
"PresentationModel" pattern
which is, in my opinion, better
adapted to a whole application than
MVC (which I find suitable for
individual widgets only). This should
solve your problem between your
Domanin Model and the TableModel
if your application has only tables,
then GlazedLists also makes a
lot of sense: it will also isolate
your Domain Model from your
TableModel (but it doesn't enforce
any global pattern, MVC or PM)
Regarding the current design you show, I would rather suggest that the View asks the Controller for an Action that the View will assign to the Delete button. Then the Controller can act on the Domain Model.
That gets messy and confusing fast, alas, and the code base is already confusing due to lack of separation.
I suggest instead migrating distinct components to a clean, simple MVC design. Such a component (which is currently a view, controller, and model all mixed up together) would then be separated in a clean fashion, however you will then have the difficulty of how to handle the controller and model?
As a temporary workaround, you'll be forced to designate the owner view as the controller, so the owner arguably has more responsibility. I think that this is a suitable workaround, because you will eventually separate more and more components into an MVC design, and the views that are also controllers will eventually become refactored as well.
In other words:
For a large application, identify a small component. (The low-hanging fruit).
Identify what code effectively controls that component. This is probably another 'view' class in this case.
Separate the component identified in step one into a clean design.
Explicitly configure the owner (view) identified in step to as the controller for the newly refactored component.
Repeat until there is clean separation between ALL views and controllers.
Be careful to ensure that the application is still working at the end of every 'step 4' above, otherwise, you'll find yourself in a mess that just gets longer and longer to fix. (Even if the end result is nice and clean, you may have missed your deadline).
Keep in mind that it may be difficult to extract the 'model' from the code at first - the controllers and views will be easiest to separate, but eventually, the models will become easier to separate as well. Whenever you manage to extract a model, write unit tests that test that model in isolation.
The presence of a well written suite of unit tests will help ensure that the application continues to have well-defined separation of concerns. (If concerns are not separated, then it becomes very hard to unit test), so the unit testing approach serves as a motivator.
I hope that makes sense.

Categories

Resources