If I am using the MVP pattern with GWT, as in the GWT architecture best practices talk from Google I/O from 2009, but have spread out the information into multiple widgets, how should the value object be populated?
Say I have a EditPersonView/Presenter, a EditPetView/Presenter and an EditAddressView/Presenter and the last two are widgets as a part of a panel in the EditPersonView. With these I have the following class:
class PersonDetails {
private PetDetails pet;
private AddressDetails addressDetails;
// ...
}
The PetDetails and AddressDetails instance variables are managed in their presenter counterparts. When the user clicks the "Save" button in the EditPersonView, how should the communication between the widgets be done so that the PersonDetails is filled with information from its child widgets?
If you look at page 42 of the presentation by Ray Ryan from Google IO 2009 you should find the solution to your question. You use an "event bus" (shared instance of HandlerManager) and fire your custom PetDetailsChangedEvent event and listen for that event from your child widgets (page 45). Also, remember that while decoupling, etc is great and all, some coupling is not a bad thing and might actually be a better solution than trying to force everything to be loosely coupled - RR says so in that presentation himself :)
I've faced this same problem in a few different GWT applications that I've designed using Ray Ryan's approach.
My preferred solution is to create a Singleton "session object" that stores the state of that part of the application. In your example, it might look like this:
interface EditPersonSession {
void fetchPerson(PersonId id);
PersonDetails getCurrentPersonDetails();
void updatePersonDetail(PersonDetail<?> detail);
void updatePetDetail(PetDetail<?> detail);
void updateAddressDetail(AddressDetail<?> detail);
void save();
}
All three presenters contain a reference to the session object (perhaps injected by Gin). Whenever the UI (view) is manipulated by the user, the presenter associated with that view immediately pushes the state to the shared session object. For example, inside EditAddressPresenter:
view.getStreetNameTextBox().addValueChangeHandler(new ValueChangeHandler() {
void onValueChange(ValueChangeEvent<String> event) {
editPersonSession.updateAddressDetail(new StreetNameAddressDetail(event.getValue()));
}
}
When it is time to save, the state object is told to save the state to the server. At this point, the session object has up-to-date representations of the data, and can save it all at once. So, in EditPersonPresenter:
view.getSaveButton().addClickHandler(new ClickHandler() {
void onClick(ClickEvent event) {
editPersonSession.save();
}
}
This way, the presenters need not contain any references to each other, but can send consistent information to the server.
If the presenters need to know when information that they display has been updated (either by other presenters, or by the server), the session object can notify them by firing events on the event bus (shared Singleton HandlerManager). The presenters can then pull the most current PersonDetails from the session object.
I've also come to the conclusion that I can have one model that corresponds to each presenter. So a PetWidget may create a Pet instance and a PersonWidget may create a Person instance. The PersonWidget may then contain one or more PetWidgets which in turn means that the Person class can have a list of Pet instances.
Related
This question more towards paradigm. Why is that we don't use Event Bus instead of listeners in an MVP environment ? Typically, the "P" part has dependency injection of view and model references. Sure this has an advantage of showing explicit contract between the view and model via presenter, which is more readable.
However, wouldn't it be a cleaner approach to have presenter listen to events from views and events carry the view payload (eg: json representation). Same is the case with presenter talking back to the view. View will listen for events from presenter. Major advantage is, we don't have to write interfaces for each contract between view and presenter. If you look at the code you will see that presenter is getting exposed to view details like Text Fields, which i believe is increasing coupling between view and presenter. Say, if i'm replacing front end JavaFx instead of Vaadin, i will have to alter presenter as well.
This class is an example from a live project. Here we have different types of events ie i don't create event class for different cases. Eg: LoginViewEvent , DashBoardEvent etc which i believe is a maintenance pain.
public class UrayEvent {
public static enum EventType {
SESSION_SELECTED(1),
DOCUMENT_SELECTED(2),
DOCUMENT_EDIT_COMPLETE(3),
DOCUMENT_EDIT_CANCELED(4),
SHOW_SESSION_TABLES(5),
SHOW_SESSION_DOCUMENTS(6),
SHOW_SESSION_COLLABORATORS(7),
USER_REQUESTED_REFRESH(8),
AUTO_REFRESH(9),
TABLE_SELECTED(10),
DETACHED(11),
SCHEDULER_NAVIGATION(12),
JIRA_USER_SELECTED(13),
DOCUMENT_SAVE_SUCCESS(14),
DOCUMENT_SAVE_FAILURE(14);
private final int value;
private EventType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
public static class Event {
private final EventType type;
private final Object payload;
public Event(EventType type, Object eventPayload) {
this.type = type;
this.payload = eventPayload;
}
public EventType getEventType() {
return type;
}
public Object getEventPayload() {
return payload;
}
}
}
Simple enough, the view send the event DOCUMENT_EDIT_COMPLETE .The presenter layer handles this event. I found this way, a better way to decouple views from presenter.
#Subscribe
public void handle(UrayEvent.Event event) {
switch (event.getEventType()) {
case DOCUMENT_EDIT_COMPLETE:
// event payload contains document model data
// like document id etc
saveDocument(event.getEventPayload);
break;
default:
break;
}
}
Advantage
Less boiler plate code, for n-views we don't need n-interfaces
New event means adding event element to enum and updating respective
subscribe methods handling this event.
Disadvantage
Memory leak if we forget to unregister from eventbus (faced it plenty of time)
Questions
1) This approach means, there would larger set enum elements as the application grow. Is this approach an anti pattern ?
2) As we saw it uses Event Bus extensively are there any drawbacks of
using bus system instead of interface-listener pattern ?
Wanted your valuable suggestion on this regard. The main issue is, if i blindly apply this pattern extensively across the project i shouldn't regret doing so, what would be a possible pitfall in this approach.
1) This approach means, there would larger set enum elements as the
application grow. Is this approach an anti pattern ?
If there are many events you need many event identifiers. They can be simple ints or enums or Interfaces.
The mechanism you demonstrated is simple and works well with small applications. It has been proven many times over with multiple frameworks. Take for example Microsoft's Win32 API and MFC.
In some projects I have seen the event interceptors implemented with Annotations which provides an elegant way for handling the events. The previous time was in a project utilizing the Apache Wicket framework.
2) As we saw it uses Event Bus extensively are there any drawbacks of
using bus system instead of interface-listener pattern ?
It is basically the same thing in a different package. In Java world it is de facto standard to use listener interfaces. Take for example Swing and Android.
The event bus approach is used in Facebook's Javascript based React framework. It is interesting to notice the similarity of Model-View-Presenter and Flux design patterns. Particularly the unidirectional data flow is highlighted in both architectures.
You mentioned the use case of replacing JavaFx with Vaadin as the UI framework. In my opinion, changing the UI framework so that you are able to reuse even some portions of it very rarely happens. I would not pay the price of added abstraction layers and complexity upfront just because the framework might change. Rather you should start with KISS and YAGNI principles. If you want to change the UI framework later, then you just implement the UI layer again from scratch.
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.
I have to fulfill the following requirement:
[...]if the logged user is idle for more than 30 minutes, he has to be logged out.
where idle means "doesn't press mouse nor keyboard".
Now, I was pretty sure about how to achieve this when I first read it: to me it sounded like a requirement that has to do with business logic, so I should have realized it in the business layer (having a 3-layers architecture).
Here some code:
// simplified and generalized version of my login method
public boolean login(String email, String password) {
user = dao.read(email, password); //returns either null or the user
boolean logged = user != null;
if (logged) {
// initialize Session somehow, let's say for example:
Session.start();
}
return logged;
}
// simplified and generalized version of my logout method
public void logout() {
operatore = null;
// terminate Session somehow, let's say for example:
Session.destroy();
}
This would be ideal, but there's one problem: Session should know how to detect user inactivity (and then fire logout() method)... but unfortunately this entirely depends on how the GUI is made!
[just to be clear: I know I to achieve this, but I'd like to do it independently on how I realize UI (e.g. Java Swing, command-line, web-based, etc)]
I mean, business layer can't (and shouldn't imo) catch user events/interaction so I should necessary realize Session in the GUI package and use it from there: in my design a layer should only interact with its strictly lower layer's interfaces and should not know anything about any higher level (Data Access Layer is indipendent (well, it depends on DB and other persistence mechanism), Business Layer only depends on Data Access Layer interfaces, Presentation Layer only depends on Business Layer interfaces).
The problem is that just sounds wrong to me realize part of what I consider to be a business logic requirement in the presentation layer.
Btw, session expiring probably has to do too much with presentation logic since has to "listen" user inputs.
This reminds me of another pertinent question which I answered myself some time ago, but I'm going to ask this one too just to avoid any doubt: link to the question.
I'd like to hear some opinion in merit, mainly focused on good design practices.
As the requirement says
if the logged user is idle for more than 30 minutes, he has to be
logged out.
So here inputs are key board or mouse activity. Of course this belongs to Presentation Layer.
In web application scenario, the Mouse/Keyboard activity (Utility) module trigger session time out.
We can use Observer/Listener pattern. If it is in java
http://www.vogella.com/articles/DesignPatternObserver/article.html will be helpful
Using httpsession listners we can pass this activity into Business Layer. That means you can call Business Layer functionality to do the clean up.
In desk top scenario, we can use Swing application where similar pattern can be used.
So the point is Presentation layer informs the other layers based on the input provided by the Utility Class.
It can even get more exciting. Different timeouts on different screens (maybe screens that show a video, so the timeout is put aside while the video is on). Different timeouts for different users (for some it should never timeout). Screens that are accessible without login-in first, yet the application should "timeout" and take back to the "main" screen.
I ended up registering the business layer application to "activity" in the presentation controls. Not a beautiful site. Would be happy to see a good solution.
Both.
Your business layer just needs to know that there has been some user activity -- it doesn't necessarily need to know what that activity is or how that activity was triggered (or even where it came from).
public class Session {
...
public static void keepAlive() {
// update last activity fields with new timestamp
}
....
}
Whenever your presentation layer receives input of some sort (mouse movements, mouse clicks, key presses, and so on), it's up to the objects in that layer to notify the business layer that something has happened.
To keep things separated, you'll probably want to add some events to your Session object.
public interface SessionExpiringEventHandler {
void sessionExpiring();
}
public interface SessionExpiredEventHandler {
void sessionExpired();
}
public class Session {
...
private List<SessionExpiringEventHandler> expiringHandlers;
private List<SessionExpiredEventHandler> expiredHandlers;
...
public static void addExpiringEventHandler(SessionExpiringEventHandler h) {
expiringHandlers.add(h);
}
public static void addExpiredEventHandler(SessionExpiredEventHandler h) {
expiredHandlers.add(h);
}
....
}
That way when the Session object expires (or is about to expire) the session, it can loop through all of its event handlers for the respective event and invoke them. This will let you keep your layers separate.
I am developing an editor following the general MVC design: the model holds the data, the controller knows how to change it, and the view issues calls the controller to query and modify the model. For the sake of argument, let us use
public class Model {
public Object getStuff(String id);
public void setStuff(String id, Object value);
}
public interface Controller {
public void execute(Command command);
public void redo();
public void undo();
public void save();
public void load(File f);
}
The class that actually implements the controller holds a reference to the model; commands need to access it too, so they must all provide a void execute(Model m); interface that actually grants them this access only when needed.
However, views generally need access to the model - when building themselves and, later on, to listen for changes and refresh themselves accordingly. I am afraid that adding a "Model getModel()" call to the Controller will result in a great temptation to bypass the execute() mechanism; and I am not the only developer working on the project. Given this scenario, how would you enforce an "all changes go through the controller" policy?
Two alternatives I am considering:
An interface called "ReadOnlyModel", returned by the getModel() call instead of the real model, that catches any such attempts.
Lots of comments to clue incoming developers as to the Correct Way of Doing Things
I recommend modeling the access to the model as a set of classes. For example, if the view needs to modify a customer's attributes, there would be a ModifyCustomerCommand class that would have as properties all of the information needed in order to perform the update. The view would construct an instance of the class with values and pass it back to the controller which, in turn, would pass the command back to the model for the actual update.
A benefit from this approach is that each of these model access commands can implement undo behavior. If the controller keeps an ordered collection of these commands as they get sent back to the model, the controller can back off the changes, one at a time, by invoking the undo method on the most recently executed command.
What if you take a look at Observer Pattern http://en.wikipedia.org/wiki/Observer_pattern, your view only listen for events from model.
Hope it helps.
I've been reading about MVC a lot recently, because I need to learn how to separate model and GUI for a project in school. (The teacher has said nothing about it, so I'm trying to learn it myself.)
I believe I understand the bacis principles with the view "registering" with the model with actionlisteners, or something along those lines. But I just can't get it into code. I've looked at several small programs, but they are somehow still too big for me to understand the basics.
Could someone please explain it as if explaining to a 5 year old, or give me some links or a really simple example program or something? Thanks a lot!
First, you need to understand the Observer pattern.
The basic idea is that you define an object that notifies interested parties when it changes. (Note that the Observer pattern is a bit more general - Observables notify Observers about "some event". For MVC, that event is "something changed")
First you define a contract between the OBSERVABLE and OBSERVER
package aaa;
// AN OBSERVER INTERFACE
// This is a contract between an interested party (the OBSERVER) and
// the thing it would like to know has changed (the OBSERVABLE)
// The OBSERVABLE will call this method whenever its data changes
public interface SomethingChangedListener {
void somethingChanged(String name, Object newValue);
}
Then you define the OBSERVABLE
package aaa;
import java.util.ArrayList;
import java.util.List;
// An OBSERVABLE class
public class Person {
// STEP 1: keep track of "who cares"
// outsiders with interest implement the observer interface
// and register with the person to indicate that they care
private List<SomethingChangedListener> listeners = new ArrayList<SomethingChangedListener>();
public void addSomethingChangedListener(SomethingChangedListener scl) {
listeners.add(scl);
}
public void removeSomethingChangedListener(SomethingChangedListener scl) {
listeners.remove(scl);
}
// STEP 2: be able to notify those observers by calling a method in the observer interface
protected void fireSomethingChanged(String name, Object newValue) {
for (SomethingChangedListener scl : listeners) {
scl.somethingChanged(name, newValue);
}
}
// STEP 3: whenever the data changes, notify the observers
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
fireSomethingChanged("age", name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
fireSomethingChanged("name", name);
}
}
This allows any other object to "listen" for changes on the thing it's interested in, as long as it implements that observer interface.
For example:
package aaa;
public class Test1 {
private static class TestObserver implements SomethingChangedListener {
#Override public void somethingChanged(String name, Object newValue) {
System.out.println("Property '" + name + "' changed to '" + newValue + "'");
}
}
public static void main(String[] args) {
Person p = new Person();
p.addSomethingChangedListener(new TestObserver());
p.setName("Scott");
p.setAge(43);
}
}
Creates an instance of the observable (the Person), registers an observer (TestObserver), and then interacts with the Observable. When run, we see
Property 'name' changed to 'Scott'
Property 'age' changed to 'Scott'
So far so good.
Now let's call the Person our MODEL. The MODEL represents the data that we want to manipulate and view.
We can do this in a "user interface". The user interface can be, but is not limited to:
A Graphical User Interface (GUI)
A Command-Line Interface (CLI)
A Web Application (HTML, JSP, ASP, etc)
A Web Service (SOAP, REST, etc)
The code for each of these types of user interfaces (UIs) can be drastically different, but the concepts are the same.
The user interface (UI) allows a user (a person or another computer for example) to see information about the model and make changes to that information.
The "View" is the part of the UI that displays the information for the user. It reads data from the model and formats it in some way to present it.
If the model changes, the View must be updated. To accomplish this, it registers observers with the model. Those observers simply refresh the relevant parts of the presentation in the View.
Now what happens if the user wants to make a change?
We define a "Controller" in the UI as code that interprets user interaction with that UI. For example, if the user types in the "name" field, the controller may interpret that as "change the value of 'name' to the text the user has typed. The controller makes a
person.setName(textFromField);
call to update the model.
Remember what that setName() method does? It notifies the observers of the change. This will cause the UI to update its view.
Note that "view" and "controller" do not need to be separate classes; they're often combined. It's really the roles of "view" (the part of the UI that displays model data) and "controller" (the part of the UI that interprets user interaction and updates the model) that are important to understand.
In some settings, such as Web Applications, the view and controller are very separate. The controller interprets the HTTP requests that are made to the server and updates the mode. The view renders HTML responses to the user. (If you're doing an AJAX application, the design is a bit more similar to a GUI)
The cool thing about the MVC separation (Model vs UI) is that you can add or remove UIs from the Model at any time, and can have multiple UIs on the same model. If data is changed in one UI, all other UIs are updated to reflect the change.
Cool, eh?
Now, the very basic thing about MVC is to separate M, V and C.
On one side you have your classes, and code that does something, like calculate sum of two input numbers, or does something with database, whatever. That's your Model.
On the other side you have some other classes which are responsible for forms, text inputs, buttons and things visible on the screen. That's the View.
Now, Controller is the one linking these two. Usually (in say Swing) you would have your controller implement the Listener interfaces, then you would add the controller as your listener to the screen components you want your software to react on, like buttons. And the implemented handler method wouldn't do anything else except calling whichever method you have implemented in you Model.
I hope this made it more clear..
This diagram might help you to understand the relationship of MVC in Java
UI component is the View, Control servlet (just catch all the incoming requests here and redirect them to the correct business object) is the Controller and the business objects is the Model.
That is my interpretation of MVC in java. Other answers are welcome.