Custom Composite GWT Widgets using MVP

954 views
Skip to first unread message

BM

unread,
Sep 12, 2012, 10:04:18 AM9/12/12
to google-we...@googlegroups.com
Hello,
I have a thorough knowledge of GWT MVP with Activities and Places. With Eclipse GPE, I can create GWT MVP view with ease which basically creates Place, View files(UIBinder XML, View interface, UIBInder XML Implementation file), Activity class and reference in ClientFactory to create the view. 

I know I have seen this before and not sure how to find it again but I am looking for creating my custom GWT widgets with UIBinder and have MVP capabilities with that. The problem I am facing here is when I create a Composite View using UI Binder I get only "UIBinder XML template" file and the "UIBInder Implementation" file. There is no "Presenter" class available for me. So all my code kind of goes inside that "UIBInder Implementation" file. 

Anyone have a suggestion on how to solve this issue? I really want my "custom composite" GWT Widgets (basically doesn't have it's own Place component) to be highly testable and provide clear code separation making my view portion as dumb as possible. 

One way I thought was adding manually a Presenter Implementation class myself and creating an View & Presenter interfaces for my "UIBinder Implementation" file just like what we see with GWT MVP View structure eclipse creates but then the question becomes how do I reuse this composite GWT widget in my other views as my presenter won't have the ClientFactory, Event Bus fields needed for any RPC calls. With GWT Activities & Places, AppActivityMapper starts an activity by passing place & Client factory to my activity which in turns references itself to the View. Since there is no Place component for my custom composite View, I have no way to instantiate my Presenter here.

And I don't want my "UIBInder Implementation" file to include RPC calls logic. 

Any help would be highly appreciated. What are the best practices here to achieve this. 

Jens

unread,
Sep 12, 2012, 11:40:11 AM9/12/12
to google-we...@googlegroups.com
The fact that a custom widget uses MVP should be hidden so you would end up having:

MyCustomWidget extends Composite implements CustomView {

  MyCustomWidget() {
    myPresenter = new Presenter(this); //takes CustomView as argument so you can mock the view while testing the presenter
  }  

   public void myCoolMethod() {
      myPresenter.doTheTestableWorkForMe(); //delegation to presenter if wanted/needed
   }

}

If your presenter needs additional dependencies you would pass through your ClientFactory, e.g.

MyCustomWidget(ClientFactory factory) {
  myPresenter = new Presenter(this, factory);
}

The presenter would be package private so no one outside the package can use it but you can still test the presenter as the test typically resides in the same package.

I think this works best for complex widgets and it is the same strategy as the cell widgets work internally (see AbstractHasData and its presenter).

-- J.

BM

unread,
Sep 12, 2012, 12:04:04 PM9/12/12
to google-we...@googlegroups.com
Hi Jens,
Thanks for replying back with an example. You answered what I am needing for. So that definitely helps. I kind of thought about this approach but couple of things I found here which I am not sure is better way to do that.

1) My presenter would need additional dependencies like ClientFactory, EventBus. That means my MyCustomWidget need to have ClientFactory, EventBus so that I can pass them to the Presenter. Considering we want to make our MVP Views as dumb as possible and have only GWT widget code inside is this okay to include ClientFactory, EventBus in your View class now?

2) If you see the classic GWT MVP view, Place instantiates an Activity class passing ClientFactory in it's constructor and Activity class start method uses ClientFactory to get the view and assign itself inside the view as it's presenter. Whereas your way is opposite where your Composite View class is instantiating Activity through it's constructor and passing itself to the Presenter. 

3) If I am referencing this Custom Composite View MyCustomWidget in another Ui Binder View how do I pass ClientFactory, EventBus to this MyCustomWidget using UIBinder? That means I have to pass ClientFactory, EventBus to every Parent View so that it can get passed to the  MyCustomWidget if that view is using it. This kind of differs to existing Activities & Places framework where MVP View doesn't hold ClientFactory, EventBus objects but it's Activity class do.

What do you think?

Thomas Broyer

unread,
Sep 12, 2012, 12:12:41 PM9/12/12
to google-we...@googlegroups.com

On Wednesday, September 12, 2012 6:04:04 PM UTC+2, BM wrote:
Hi Jens,
Thanks for replying back with an example. You answered what I am needing for. So that definitely helps. I kind of thought about this approach but couple of things I found here which I am not sure is better way to do that.

1) My presenter would need additional dependencies like ClientFactory, EventBus. That means my MyCustomWidget need to have ClientFactory, EventBus so that I can pass them to the Presenter. Considering we want to make our MVP Views as dumb as possible and have only GWT widget code inside is this okay to include ClientFactory, EventBus in your View class now?

Why not?
(that wouldn't be my preferred approach if you ask me)
 
2) If you see the classic GWT MVP view, Place instantiates an Activity class passing ClientFactory in it's constructor and Activity class start method uses ClientFactory to get the view and assign itself inside the view as it's presenter. Whereas your way is opposite where your Composite View class is instantiating Activity through it's constructor and passing itself to the Presenter.

Yes.
FYI, CellTable, CellList, etc. use MVP internally, with the view constructing the presenter (simplifying a bit), as Jens suggested.

3) If I am referencing this Custom Composite View MyCustomWidget in another Ui Binder View how do I pass ClientFactory, EventBus to this MyCustomWidget using UIBinder? That means I have to pass ClientFactory, EventBus to every Parent View so that it can get passed to the  MyCustomWidget if that view is using it. This kind of differs to existing Activities & Places framework where MVP View doesn't hold ClientFactory, EventBus objects but it's Activity class do.

What do you think?


When you have such external dependencies, it's clear that these components are not "just widgets". In that case, I'd rather follow the Wave way: "parent view" creates the "child view", "parent presenter" creates the "child presenter" giving it its "child view" retrieved from the "parent view".

BM

unread,
Sep 12, 2012, 12:35:53 PM9/12/12
to google-we...@googlegroups.com
Thanks Thomas. Your replies are always quick and helpful. 

Regarding your comment on my third point, the reason why I have external dependencies is because let's say my custom view has some custom table (Cell Table has some limitations so not using it). That means I can reuse the custom table in my parent view as a widget and can show multiple widgets based on different data I get from my parent Activity RPC call. Also I have a onMouseOver event which shows a custom pop-up like Netflix on a certain cell in each row.  I also have onClick event on a certain column in each row which basically need to take the user to a different place. I have no way to get hold of Place Controller in my Custom Widget for onClick event. What if one of my column has two radio buttons and onChange of that radio button should fire an event and update that value to the database. Again without ClientFactory I won't be able to make RPC call and hence I need a separate Presenter for that custom widget to handle the click events and have RPC call to make an update to DB. We clearly don't want RPC code inside custom widget file as that code will not be testable without GWTTestCases which I want to avoid.

So yea you are right, it is not just widget which simply shows data but it has user interactions but it is still consider a reusable custom widget. 

So your approach of parent view, child view, parent presenter which could be activity and child presenter is mentioned in this thread? : https://groups.google.com/forum/?fromgroups=#!searchin/google-web-toolkit/composite$20views$20using$20MVP/google-web-toolkit/yHLSA881wsM/c0iQq7JSJRQJ

Please advise. 

Thomas Broyer

unread,
Sep 12, 2012, 12:45:44 PM9/12/12
to google-we...@googlegroups.com


On Wednesday, September 12, 2012 6:35:53 PM UTC+2, BM wrote:
So your approach of parent view, child view, parent presenter which could be activity and child presenter is mentioned in this thread? : https://groups.google.com/forum/?fromgroups=#!searchin/google-web-toolkit/composite$20views$20using$20MVP/google-web-toolkit/yHLSA881wsM/c0iQq7JSJRQJ

Yep. Exactly.

BM

unread,
Sep 12, 2012, 1:26:13 PM9/12/12
to google-we...@googlegroups.com
Thomas, Jens, you guys rock!! Thank you very much for quick replies and helping GWT community stronger day by day!
Reply all
Reply to author
Forward
0 new messages