Skip to main content

Home/ GWT - MVP/ Group items tagged model

Rss Feed Group items tagged

Esfand S

overlook - Tech Blog - 2 views

  • The main issue in MVC is that these three elements are tighly bound together: the controller has to register to both the model and the view (and unregister if either changes), and when a view serves multiple controllers or a controller uses multiple models, that becomes quickly a mess.
  • MVP approach is more message-oriented. All messages (events) are fired on a single EventBus that is shared by all Presenters. Each presenter listens to events of interest, and fires new events according to actions. So a change in the in the EmployeeModel may be fired with an EmployeeModelChangedEvent, instead of attaching a listener to the model object. And we can easily create new Presenters that receive that same event and react accordingly.
  • The magnitude of such a shift is great: the model is no more the center and source of events (which would require special care in attaching and detaching to a specific instance), but it more a passive container of data, which may be copied, proxied, transformed, cached, without the GWT appliction any special care.Since the model is more a container of data ment for communication, I've highlighted the fact that it needs to be Serializable.
  • ...11 more annotations...
  • It is now the time to introduce the Model in GWT 2.1. The direction taken in 2.0.x has been pushed one step further, so that the Model is, in fact, only a Data Transfer Obejct (DTO). A DTO is an object whose main purpose is to be transferred, usually from one Tier to another Tier of a layered architecture such as Browser/Server/Database.
  • Value Store, the package that defines the Model/DTO programming interface.
  • Valuestore is the management interface that performs CRUD (Create, Read, Update, Delete) operations on the Records, like Entity Manager in JPA and Persistence Manager in JDO.
  • The first interface to discuss is Record, the base interface to implement to define a DTO class. A Record holds data for a single instance of an entity. Let's suppose that in your server-side business model there's an entity called 'Employee' to represent a company employee list.  To use it on the client side, you would need to define an EmployeeRecord class to hold the values of one of your employees, e.g. the employee name, birth date, etc.
  • A Record is able to provide values using Property objects as keys. The properties are type-aware, so that the employee name is a Property<String>, the employee birth data a Property<Date>, and so on. The following table reports these elements in a single example:
  • The Record interface doesn't provide a generic reflection mechanism, so it's not possible to inspect a Record to know what kind of Properties it is made of. The current implementation RecordImpl, which delegates to JavaScriptObject implementation and provides JSON serialization, is actually holding a schema of the record properties in a RecordSchema object.
  • note the annotation @DataTransferObject, that GWT uses to map the record to the equivalent server-side class. By declaring the connection, GWT is capable of binding automatically the interface properties with the JPA-annotated properties, thus greatly reducing the amount of boilerplate mapping work to be performed.
  • Of course, when you add or modify a property in your real Model, appropriate changes must be applied to the equivalent Record. That's where the teamwork with Spring Roo comes handy: Spring Roo generates and keeps aligned a lot of these elements, and would reflect (overwrite) your EmployeeRecord java file every time you change your domain model definition.
  • As a general rule, you are encouraged to define specific interface methods to extract data from you Record, e.g. getName() to get the Employee name. Record exposes also method to retrieve a value given a property. For instance, in a Renderer of a CellTree, when you are given an EmployeeRecord you should access its data through public getter methods.
  • The model-agnostic way that GWT uses to access a value is the Record.get(Property<V>) method. There's also a way to get not the value itself, but a PropertyReference<V>, which is just the property of a specific record, e.g. the Property 'name' of Record 'r2' in the example table above. In a few words, a property reference is just a value, which is exactly how Value<V> is defined. That is most useful to perform late bindings during RPC calls when the data is not yet available.
  • The DeltaValueStore is also worth mentioning a few words: as your model is now decomposed in Records and Properties, it is also possible to transfer only the data you need to. Hence the retrieval requests can dowload only a few properties of the Records. Furthermore, 'Update' operations can transmit back only the user changes (delta) instead of whole objects, which may give a nice performance boost.
Esfand S

MVP vs MVC - 0 views

  •  
    In MVC, the model is heavy with business rules and data access, the view contains the presentation logic, and the controller is typically a framework component with an XML configuration to drive it. In MVP, the model is lightweight POJO value objects, the view is mockable, and the presentation is specific to the model and the view. It is the presentation that has all the dependencies and glue code for the model\nand the view. You get more code coverage in your unit testing with MVP so MVP and TDD go together.
Esfand S

Large scale application development and MVP - Part II - 0 views

  • segment the code that declares the UI from the code that drives the UI.
  • we want the our ContactsPresenter to implement a Presenter interface that allows our ContactsView to callback into the presenter when it receives a click, select or other event. The Presenter interface defines the following:   public interface Presenter<T> {    void onAddButtonClicked();    void onDeleteButtonClicked();    void onItemClicked(T clickedItem);    void onItemSelected(T selectedItem);  }
  • The first part of wiring everything up is to have our ContactsPresenter implement the Presenter interface, and then register itself with the underlying view. To register itself, we'll need our ContactsView to expose a setPresenter() method:   private Presenter<T> presenter;  public void setPresenter(Presenter<T> presenter) {    this.presenter = presenter;  }
  • ...8 more annotations...
  • Note that our ContactsView is now ContactsViewImpl<T> and implements ContactsView<T>. This is so that we can pass in a mocked ContactsView instance when testing our ContactsPresenter. Now in our AppController, when we create the ContactsView, we can initialize it with the necessary ColumnDefinition(s).
  • With the ColumnDefinition(s) in place, we will start to see the fruits of our labor. Mainly in the way we pass model data to the view. As mentioned above we were previously dumbing down the model into a list of Strings. With our ColumnDefinition(s) we can pass the model untouched.   public class ContactsPresenter implements Presenter,    ...    private void fetchContactDetails() {      rpcService.getContactDetails(new AsyncCallback<ArrayList<ContactDetails>>() {        public void onSuccess(ArrayList<ContactDetails> result) {            contactDetails = result;            sortContactDetails();            view.setRowData(contactDetails);        }        ...      });    }    ...  } And our ContactsViewImpl has the following setRowData() implementation:   public class ContactsViewImpl<T> extends Composite implements ContactsView<T> {    ...    public void setRowData(List<T> rowData) {      contactsTable.removeAllRows();      this.rowData = rowData;      for (int i = 0; i < rowData.size(); ++i) {        T t = rowData.get(i);        for (int j = 0; j < columnDefinitions.size(); ++j) {          ColumnDefinition<T> columnDefinition = columnDefinitions.get(j);          contactsTable.setWidget(i, j, columnDefinition.render(t));        }      }    }    ...  } A definite improvement; the presenter can pass the model untouched and the view has no rendering code that we would otherwise need to test.
  • Code Splitting is the act of wrapping segmented pieces of your application into "split" points by declaring them within a runAsync() call. As long as the split portion of your code is purely segmented, and not referenced by other parts of the app, it will be downloaded and executed at the point that it needs to run.
  • We've figured out how to create the foundation for complex UIs while sticking to our requirement that the view remain as dumb (and minimally testable) as possible, but that's no reason to stop. While functionality is decoupled, there is still room for optimization. Having the ColumnDefinition create a new widget for each cell is too heavy, and can quickly lead to performance degradation as your application grows. The two leading factors of this degradation are: Inefficiencies related to inserting new elements via DOM manipulation Overhead associated with sinking events per Widget To overcome this we will update our application to do the following (in respective order): Replace our FlexTable implementation with an HTML widget that we'll populate by calling setHTML(), effectively batching all DOM manipulation into a single call. Reduce the event overhead by sinking events on the HTML widget, rather than the individual cells. The changes are encompassed within our ContactsView.ui.xml file, as well as our setRowData() and onTableClicked() methods. First we'll need to update our ContactsView.ui.xml file to use a HTML widget rather than a FlexTable widget.
  • The above code is similar to our original setRowData() method, we iterate through the rowData and for each item ask our column definitions to render accordingly. The main differences being that a) we're expecting each column definition to render itself into the StringBuilder rather than passing back a full-on widget, and b) we're calling setHTML on a HTML widget rather than calling setWidget on a FlexTable. This will decrease your load time, especially as your tables start to grow.
  • To reiterate, we're reducing the overhead of sinking events on per-cell widgets, and instead sinking on a single container, our HTML widget. The ClickEvents are still wired up via our UiHandler annotations, but with this approach, we're going to get the Element that was clicked on and walk the DOM until we find a parent TableCellElement. From there we can determine the row, and thus the corresponding rowData.
  • Our current solution is to have our presenters pass a dumbed down version of the model to our views. In the case of our ContactsView, the presenter takes a list of DTOs (Data Transfer Objects) and constructs a list of Strings that it then passes to the view. public ContactsPresenter implements Presenter {  ...  public void onSuccess(ArrayList<ContactDetails> result) {    contactDetails = result;    sortContactDetails();    List<String> data = new ArrayList<String>();    for (int i = 0; i < result.size(); ++i) {      data.add(contactDetails.get(i).getDisplayName());    }    display.setData(data);  }  ...} The "data" object that is passed to the view is a very (and I mean very) simplistic ViewModel — basically a representation of a more complex data model using primitives. This is fine for a simplistic view, but as soon as you start to do something more complex, you quickly realize that something has to give. Either the presenter needs to know more about the view (making it hard to swap out views for other platforms), or the view needs to know more about the data model (ultimately making your view smarter, thus requiring more GwtTestCases). The solution is to use generics along with a third party that abstracts any knowledge of a cell's data type, as well as how that data type is rendered.
  •         // TODO: Really total hack! There's gotta be a better way...        Element child = cell.getFirstChildElement();        if (child != null) {          Event.sinkEvents(child, Event.ONFOCUS | Event.ONBLUR);        }
Esfand S

GWT MVP - Google Web Toolkit | Google Groups - 0 views

  • For your convenience, here is the net of it. With MVC, the model is thick with business rules and glue code to a data access layer. The view has lots of dependencies on the model. The controller is usually a framework component driven by some kind of configuration, usually XML based. With MVP, the model is lightweight POJOs. The view is mockable. It is the presenter that is heavy with glue code and business rules. The thinking here is that MVP is more suited for TDD than MVC. Another notable feature of MVP in GWT apps is the use of an event bus instead of hard coded event handler dependencies. Typically, that event bus is implemented as either the HandlerManager from GWT itself or the PropertyChangeSupport class from the GWTx library.
Esfand S

Ray Ryan, best practices and embracing asynchronicity - Google Web Toolkit | Google Groups - 0 views

  • there is a clear distinction between *what the browser needs* (DTO) and *what the business needs* (domain objects). When you send JDO objects across the wire, you are sending your domain model. Its not what the browser wants, and that is a problem. Soon, you will have a presentational information in your domain model, and you will have restricted information being sent to the browser, and it will be a big mess. So, take a step back, and separate Domain objects from Presentation objects (or DTOs). Make your RPCs revolve around a particular view, and send all necessary information for that view in one RPC call. Note that now your Person would include company name and company id, but not the entire company object. Now, when the user clicks the company in the view, you make a RPC call to get company information (because you have company id). That's it. Works nicely, without having to make multiple calls.
Esfand S

What's Coming in GWT 2.1? - Google Web Toolkit - Google Code - 0 views

  • The MVP Framework is an app framework that makes it easy for you to connect Data Presentation Widgets with backend data. Using this framework you create views that are focused on displaying data, Activities and an ActivityManager which are the "presenters", responsible for handling self-contained actions, and RequestFactories that fetch and propagate model changes throughout your app. To make developing apps of this style easier, the 1.1 M1 release of Spring Roo, can generate and maintain the boilerplate code associated with connecting your app's components with GWT's MVP Framework.
Esfand S

MKDev » Blog Archive » Comments on GWT MVP - Technical yabberings from me to you - 1 views

  • keeping History management abstracted in it’s own right
  • the need for Presenters to be capable of responding to History tokens
  • Presenters are decoupled from token managemen
  • ...3 more annotations...
  • History system is no longer required for unit testing
  • Presenters now have a clear opportunity to be lazy-loaded from a RunAsync call!
  • By adding this ViewModel (basically a Map<String, Object>), Presenters can now pass information from one to the other with zero knowledge of each other. They can also look in the model for information necessary to render the current Location properly.
Esfand S

History and server call. - Google Web Toolkit | Google Groups - 0 views

  • First, though, I think you shouldn't call it MVP. In my opinion it seems that what you're doing is MVC where the model is helped out by RPC. There is already so much variety in the meanings of this (MVP, MVC, etc...), especially with Activities and Request Factory coming into the picture that terminology is becoming important. Not because I don't know what you're describing, but because someone new to the frameworks will get thoroughly confused.
Esfand S

MVP questions - Google Web Toolkit | Google Groups - 0 views

  • What is the best way to implement that ? 1) only one couple of presenter/view for object1 and this couple manages the display of object2 in each tab 2) one presenter/view object for object1 and one presenter/view for each instance of object2 ? in other words, do I have one couple of presenter/view by object model ?
Esfand S

How to avoid Spring Roo GWT support? - Stack Overflow - 0 views

  • you can separate your project into two modules: A module containing model and persistence code that is created by Spring Roo A GWT web application that you create by hand. Make the first (Roo) module a dependency of the second (GWT) module. Basically you're using Roo to create a JAR library that's used by your web application. As long as you don't run the controller command the Roo won't add any web application code to your module.
Esfand S

Nested Views in MVP - Google Web Toolkit | Google Groups - 0 views

  • I believe the reason we've not created View and Presenter interfaces to date is because there are two different styles of MVP widely in use, only one of which allows the view to call the presenter as in your example. Which leaves us in the funny position that the new MVP framework is missing *formal* definitions of View and Presenter. Personally, I think it's a good thing that GWT Activities and Places are independent of views and presenters so as not to force you into one model. I think View and Presenter as you've described would fall in the category of things that are not quite core code, but are nevertheless useful abstractions that probably need a home in the GWT source somewhere for reference. We'll chew on this a bit for 2.1.1...
Esfand S

new GWT MVP article (part 2) - Google Web Toolkit | Google Groups - 0 views

  • > 2- when google wants to address problem of Nested/Layered presenters ? > header/body/footer, and body having its own dockpanellayout structure. We use the technique described in part II. Composite views are responsible for instantiating their own children, and making them available for the parallel composite presenters.
  • If you're referring to the ColumnDefinitions, we know they'll scale. One, it requires minimal widget overhead and is fast. No more embedding hundreds of widgets within a table. Two, it's extensible, and testable. As your model grows, your ColumnDefinitions grow, not your views.  ColumnDefinitions are quite trivial, the bulk of the code dedicated to generating HTML, and don't require a GwtTestCase.
Esfand S

new GWT MVP article (part 2) - Google Web Toolkit | Google Groups - 0 views

  • originally the MVP pattern was design for separating the view from its logic and the model it is displaying (as the MVC). Since the arriving of UIBinder I found the word View misused. Actually, strictly speaking the View is contained in the ui.xml file and the "Controller" is the corresponding java file which is implementing the corresponding logic and instanciation. This file merely represents a kind of Controller. The Presenter used in this tutorial is (for me) nothing more than a ControllerProvider which enable the ability to provide differents implementations of the view logic. What I'm founding strange is the fact that their are using the same acronym (MVP) for two differents approaches :  - first one was Presenter centered as the abstraction was done on Display and aggregation were done against the presenter  - second one was Display AND Presenter centered as the abstraction is done on Presenter and Display the both referencing each other. But this approach is mainly due to the fact that UIBinder is removing a lot of boiler plate code from event handling (and first MVP tutorial was not using it), but in the same way UIBinder tends people to adapt the original MVP pattern to be able to use all its power ! That why there is so much reflexion to mix UIBinder and MVP together.
1 - 20 of 22 Next ›
Showing 20 items per page