Gwt 2.1 Activities + Code splitting + Gin

1,200 views
Skip to first unread message

Nicolas Antoniazzi

unread,
Nov 5, 2010, 8:24:25 PM11/5/10
to google-we...@googlegroups.com
Hello,

I am trying to use CodeSplitting with Activites on 2.1.
I read this very interresting thread http://code.google.com/p/google-web-toolkit/issues/detail?id=5129 and T.Broyer says that the best approach is to use an AsyncProxy for Activities.

It makes sense but I have problem with it since my "Activities" are binded with Gin. AsyncProxy uses GWT.create() to instantiate the concrete types and all my @Inject in my Activities are thus not initialized.

Does anyone tried to mix new Activity concepts with "Code Splitting" ? And do you know if it could be compatible with "Gin activities" ?

Thanks

Nicolas.

Thomas Broyer

unread,
Nov 6, 2010, 9:27:08 AM11/6/10
to Google Web Toolkit


On 6 nov, 01:24, Nicolas Antoniazzi <nicolas.antonia...@gmail.com>
wrote:
> Hello,
>
> I am trying to use CodeSplitting with Activites on 2.1.
> I read this very interresting threadhttp://code.google.com/p/google-web-toolkit/issues/detail?id=5129and
> T.Broyer says that the best approach is to use an AsyncProxy for Activities.

I certainly didn't say it's the best approach (just that Jarod's code
wasn't adding anything to AsyncProxy).

> It makes sense but I have problem with it since my "Activities" are binded
> with Gin. AsyncProxy uses GWT.create() to instantiate the concrete types and
> all my @Inject in my Activities are thus not initialized.

That's probably the reason why GIN added AsyncProvider<?>s
(unfortunately not released yet)

> Does anyone tried to mix new Activity concepts with "Code Splitting" ? And
> do you know if it could be compatible with "Gin activities" ?

I started coding the ActivityAsyncProxy I talked about in the issue
tracker (i.e. don't even call start() on the activity if it's
cancelled before being "downloaded"), but haven't yet tried it. I
think (read: I *suppose*) that for it to work with GIN, your concrete
implementations would have to use GIN's AsyncProvider, or get the
Activity from the Ginjector from within a GWT.runAsync.

Ashton Thomas

unread,
Nov 6, 2010, 5:16:54 PM11/6/10
to Google Web Toolkit
Does anyone have some words for implementing the AsyncProvider<T>
(Still in trunk as Thomas points out)??

I have not see any code showing how to implement this so I am a little
lost on where to start.

How do we need to use AsyncProvider and what else needs to be change /
restructure anything?

Is the AsyncProvider even usable right now if we compile from source?

Nicolas Antoniazzi

unread,
Nov 6, 2010, 7:40:15 PM11/6/10
to google-we...@googlegroups.com
Thanks Thomas, I implemented something similar to what you said (I think) and it works fine ! All my activities are code splitted "automatically" now.

I used the AsyncProvider<T>.
I used a gin version compiled by gwtp team that include the AsyncProxy (althouth that I do not use gwtp for severals resons, thanks to gwtp dev for this :) ) .


The usage of AsyncProvider<T> is very simple. It's exactly like a normal Provider<T> instead that you have to give an AsyncCallback to the get() method.
example :

@Inject
Provider<MyClass> myProvider;

@Inject
AsyncProvider<MyClass> myAsyncProvider;

private MyClass instance1;
private MyClass instance2;

public void myMethod() {
  // To get an instance without code splitting
  instance1 = myProvider.get();

  // To get an instance with code splitting
  myAsyncProvider.get(new AsyncCallback<MyClass>() {
@Override
public void onSuccess(MyClass result) {
    instance2 = result;
  }
}
@Override
public void onFailure(Throwable caught) {
}
  }

In the previous example, instance1 is instanciated without code splitting, instance2 with code splitting.
This is just a small example to show you the syntax. This example is very stupid since if you declare a class with a class Provider<MyClass> in the same file than an AsyncProvider<MyClass>, MyClass code will not be code splitted.

Now, just for people who would like to know how to implement an ActivityAsyncProxy, my implementation looks like this : (And it might really not be the best one. Thomas, maybe that you have a better code to share ;) )

public class ActivityAsyncProxy<T> implements Activity {

@Inject
private AsyncProvider<T> provider;
private boolean canceled = false;
private Activity impl;

@Override
public String mayStop() {
if (impl != null) return impl.mayStop();
return null;
}

@Override
public void onCancel() {
if (impl != null) {
impl.onCancel();
} else {
canceled = true;
}
}

@Override
public void onStop() {
if (impl != null) {
impl.onStop();
} else {
canceled = true;
}
}

@Override
public void start(final AcceptsOneWidget panel, final EventBus eventBus) {
provider.get(new AsyncCallback<T>() {

@Override
public void onSuccess(T result) {
// Do not starts loaded activity if it has been canceled
if (!canceled) {
impl = (Activity) result;
impl.start(panel, eventBus);
}
}

@Override
public void onFailure(Throwable caught) {
// TODO : send error message
}
});
}
}

Now, in my ActivityMapper :

public class RootActivityMapper implements ActivityMapper {

@Inject
Provider<ActivityAsyncProxy<LoginActivity>> loginActivityProvider;

@Inject
Provider<ActivityAsyncProxy<ProfileActivity>> profileActivityProvider;

@Inject
Provider<ActivityAsyncProxy<PrivacyActivity>> privacyActivityProvider;

@Override
public Activity getActivity(Place place) {
if (place instanceof LoginPlace) return loginActivityProvider.get();
if (place instanceof ProfilePlace) return profileActivityProvider.get();
if (place instanceof PrivacyPlace) return privacyActivityProvider.get();

return null;
}
}

And that's all.

Well, Just for information, I created my custom provider for ActivityAsyncProxy :

public class ActivityAsyncProxyProvider<T extends Activity> implements Provider<ActivityAsyncProxy<T>> {

@Inject
Provider<ActivityProxy<T>> provider;

@Override
public ActivityAsyncProxy<T> get() {
return provider.get();
}
}

Now, in my ActivityMapper, injection are less verbose :

@Inject
ActivityAsyncProxyProvider<LoginActivity> loginActivityProvider;

@Inject
ActivityAsyncProxyProvider<ProfileActivity> profileActivityProvider;

@Inject
ActivityAsyncProxyProvider<PrivacyActivity> privacyActivityProvider;


Thanks Thomas, you helped me a lot this week with all your tips ! :)

Nicolas

2010/11/6 Ashton Thomas <attech...@gmail.com>
--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.


PhilBeaudoin

unread,
Nov 7, 2010, 12:49:33 AM11/7/10
to Google Web Toolkit
Hi Nicolas,

If you start using AsyncProvider, you might be interested in GWTP's
ProviderBundle at some point. The problem of AsyncProvider is that it
may introduce too many split points, and you will often want to do
some manual optimization and group a few things together behind the
same split point. ProviderBundle makes that really easy to do.

ProviderBundle is totally usable without the rest of GWTP. (Although
I'd love to hear your reason for not using it. ;))

Cheers,

Philippe

On Nov 6, 4:40 pm, Nicolas Antoniazzi <nicolas.antonia...@gmail.com>
wrote:
> Thanks Thomas, I implemented something similar to what you said (I think)
> and it works fine ! All my activities are code splitted "automatically" now.
>
> I used the AsyncProvider<T>.
> I used a gin version compiled by gwtp team that include the AsyncProxy
> (althouth that I do not use gwtp for severals resons, thanks to gwtp dev for
> this :) ) .
>
> @Ashton, you can get it from here :http://code.google.com/p/gwt-platform/http://code.google.com/p/gwt-platform/downloads/detail?name=gin-r137.jar
> 2010/11/6 Ashton Thomas <attechserv...@gmail.com>
> > google-web-tool...@googlegroups.com<google-web-toolkit%2Bunsubs cr...@googlegroups.com>
> > .

Nicolas Antoniazzi

unread,
Nov 7, 2010, 6:49:15 AM11/7/10
to google-we...@googlegroups.com
Hi Phillipe.
i am going to try "ProviderBundle".

I tried to migrate my application to gwtp just before the 2.1 release but I reverted my changes for 3 reasons :

1 - I prefer to not depend too much on an external framework. I love all new things that come in every new release of gwt and I am afraid that frameworks become unsupported or do not follow new features. I had the exemple of a friend who has prefered to use GXT instead of Pure GWT, and today, he cannot use UiBinder or the new Handler mechanism. He is still using the old listener way.
Today, GWT has released the new Activity ~ MVP part, with their own Place system. At the moment, MVP of GWT seems less powerfull than the GWTP's one, but the syntax is different. And tomorrow, maybe that directions will be more different. So I prefer not taking the risk to have a situation like with GXT.

2 - Declaration of Presenter / View looks too much complicated to me (but it is a pure subjective vision :) ).
All the generation of ProxyPlace are too magical for me or not enough... By instance, The automatic generation of a Place is something interesting, but in the same time, it is too complicated to generate. I do not like the fact to have to declare an interface which extends ProxyPlace, and references it in a type litteral. I would have prefered to just have something like :

@Place("login");
@RunAsync
public class LoginActivity implement GwtpActivity<LoginActivity.Presenter>

public inteface Presenter {
 public void onLogin();
 ...
}

or something similar.
Today I prefer to stay on a manual code for this part instead of a "half generation" that is (in my opinion) too complicated to declare.
Finally (for the code style part), I did not like the fact that we have to use a local Widget variable in View and returns it with a asWidget() method for UiBinder Views.
Today with GWT 2.1, all widgets implements IsWidget and provides a asWidget(). But since we have to store a local instance of Widget inside of view for UiBinder, it cannot be done automatically, we have to override it.
However, I understand that IsWidget was not ready when you first implemented it. But today, it does not solve the problem of the local Widget variable.

3 - My application has two top div. One called "root" for the main part of my application, and one called "overlay" for all elements that comes like a filter over my root elements (to display overlay help, ...). They have both some css declaration on them.
I did not find any way to reuse this system with GWTP. GWTP come with a RootPresenter and I wanted to use a second RootPresenter plugged on overlay div but it is not possible.
ActivityManager are more flexible for this, they have a setDisplay() method to setup the top element to use.

Well, Phillipe, all those things are just my personal feelings for my specifical needs. I think that GWTP is a great framework for a lot of people.
Unfortunatly, in my case, I had to fight against it (maybe that it was a design problem, but I am not sure), and there was all the more subjective aspects (abouts framework overlay and code style) that made me go away.

In any case, Phillipe and Christian, thanks for your great work .
I am going to try ProviderBundle, maybe that I will be more comfortable with it :)

Nicolas.

2010/11/7 PhilBeaudoin <philippe...@gmail.com>
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.

Christian Goudreau

unread,
Nov 7, 2010, 7:42:15 AM11/7/10
to google-we...@googlegroups.com
I just want to answer some of your concern :D

1- We want to introduce and follow every release of Gwt. We already introduced Gwt's evenbus instead of using ours and there's more changes on the way. That's a long term engagement, even our contributor guideline follows gwt.
2- You don't like the proxy's magic ? You can create them :D Proxy are used for lasy instantiation of presenters and to facilitate code splitting while keeping everything decoupled.
3- There's some way to do that with gwtp (PresenterWidget, proxy events). But there's no reason  to only use Gwtp, even though we encourage it. I think that activity manager can become handy for cases that we don't fully support yet.

Cheers, 
--
Christian Goudreau

Christian Goudreau

unread,
Nov 7, 2010, 7:46:18 AM11/7/10
to google-we...@googlegroups.com
More info on my number 3 comment. 
I just saw a comment from Philippe saying that mixing activity and place is discouraged for the  moment. Comming from what I say in one, I think this comment will be more appropriate for future release :D

Cheers,
--
Christian Goudreau

PhilBeaudoin

unread,
Nov 7, 2010, 10:21:31 PM11/7/10
to Google Web Toolkit
Thanks Nicolas for your answer. Most of the feedback we get from GWTP
users is very positive, but it's the opinion of people who decided not
to use it that will help us improve it!

Christian summarized it well when he said we want to keep following
GWT. We will support the IsWidget interface soon and remove the need
for view to support custom interfaces, so you will be able to use any
GWT widget (or your own Composite) as a view.

Regarding GWTP's uses of GWT generators, I haven't looked at the
mechanism GWT 2.1 uses to decouple event plumbing from presenter
instances. In my experience, this is required to allow lazy
instantiation and code splitting of presenters. I remember reading T.
Broyer saying he didn't care too much about this since his presenters
were small but, in my experience, presenters can sometime include
quite a bit of logic. In my opinion, being able to lazily instantiate
them and wake them up on specific events is necessary for scalability.
In GWTP this is done through proxys, in MVP4G it is done by defining
events within the global event bus, and I still have to look into the
precise way GWT 2.1 solves this problem.

Also, I think it's a bit unfair to call GWTP's code generation "magic"
when GWT relies on it for so many different things... But if you
really want to write proxys yourself, GWTP's allows it.

Out of curiosity, which version of GWTP did you try?

Cheers,

Philippe


On Nov 7, 5:46 am, Christian Goudreau <goudreau.christ...@gmail.com>
wrote:
> >>  2010/11/7 PhilBeaudoin <philippe.beaud...@gmail.com>
>
> >> Hi Nicolas,
>
> >>> If you start using AsyncProvider, you might be interested in GWTP's
> >>> ProviderBundle at some point. The problem of AsyncProvider is that it
> >>> may introduce too many split points, and you will often want to do
> >>> some manual optimization and group a few things together behind the
> >>> same split point. ProviderBundle makes that really easy to do.
>
> >>> ProviderBundle is totally usable without the rest of GWTP. (Although
> >>> I'd love to hear your reason for not using it. ;))
>
> >>> Cheers,
>
> >>>   Philippe
>
> >>> On Nov 6, 4:40 pm, Nicolas Antoniazzi <nicolas.antonia...@gmail.com>
> >>> wrote:
> >>> > Thanks Thomas, I implemented something similar to what you said (I
> >>> think)
> >>> > and it works fine ! All my activities are code splitted "automatically"
> >>> now.
>
> >>> > I used the AsyncProvider<T>.
> >>> > I used a gin version compiled by gwtp team that include the AsyncProxy
> >>> > (althouth that I do not use gwtp for severals resons, thanks to gwtp
> >>> dev for
> >>> > this :) ) .
>
> >>> > @Ashton, you can get it from here :
> >>>http://code.google.com/p/gwt-platform/http://code.google.com/p/gwt-pl...
> ...
>
> read more »

Thomas Broyer

unread,
Nov 8, 2010, 4:21:46 AM11/8/10
to Google Web Toolkit


On 8 nov, 04:21, PhilBeaudoin <philippe.beaud...@gmail.com> wrote:
>
> Regarding GWTP's uses of GWT generators, I haven't looked at the
> mechanism GWT 2.1 uses to decouple event plumbing from presenter
> instances. In my experience, this is required to allow lazy
> instantiation and code splitting of presenters. I remember reading T.
> Broyer saying he didn't care too much about this since his presenters
> were small but, in my experience, presenters can sometime include
> quite a bit of logic. In my opinion, being able to lazily instantiate
> them and wake them up on specific events is necessary for scalability.

I think the overall idea of activities is that they are short-lived
instances, so they're effectively "lazily created" (actually, a new
instance is created each time one is needed) and they don't need to be
"awoken" because if they're not currently in use they're already
"dead" and garbage collected.
The ActivityManager (actually its associated ActivityMapper) will
decide whether a particular activity is needed (and then instantiate
it, possibly going through a GWT.runAsync for code splitting); the
activity will listen to events its interested in *during its lifetime*
(e.g. whether some object has changed or has been added or deleted, so
it can update its view); but when it's done (stopped or cancelled),
it's simply thrown away (the event bus passed to the start() method is
a ResettableEventBus so all handlers have been automatically
unregistered for you, which as a side effect allows the activity to be
garbage collected).
This is the (AIUI) intended use, but nothing forces you to write such
short-lived instances: you can very well use singletons, but then
you'll have the additional task of maintaining state between
"runs" (start/stop or start/cancel), in which case your activity can
listen to events from the event bus after being stopped/cancelled
(just use the "real" event bus instead of the ResettableEventBus
passed to the start() method); but it won't "ask to be revealed":
navigation is handled at another layer, triggered on the
PlaceController and handled by ActivityManagers.

Nicolas Antoniazzi

unread,
Nov 8, 2010, 4:35:09 AM11/8/10
to google-we...@googlegroups.com
Hi Phillipe,

Also, I think it's a bit unfair to call GWTP's code generation "magic"
when GWT relies on it for so many different things... But if you
really want to write proxys yourself, GWTP's allows it.

Yes, I agree that I was a bit unfair with GWTP. In my opinion, it would be a geater tool (for me) if the code in front of generators were more concise (just annotation, no empty interfaces to add), and maybe more "optional". bindPresenter() needs view, proxyplace, presenter. But if I prefer to not use ProxyPlace as you suggest, I can't.
 
Out of curiosity, which version of GWTP did you try?

0.4. But I might not have been in the depth of the framework (Just coded 4 main pages of my app) until I get blocked by the Top Div/RootPresenter problem that I explained before.

Cheers,
 
Nicolas.

PhilBeaudoin

unread,
Nov 8, 2010, 3:42:12 PM11/8/10
to Google Web Toolkit
Thanks Thomas.

So the way I understand it, the ActivityManager/ActivityMapper are GWT
2.1 equivalent's of GWTP's proxy for the purpose of navigation. It's
just that in GWTP you don't need to create or modify a separate class,
all is done within your presenter.

In my apps, I often have some presenters that need to be awoken when a
given message transit on the bus. Say, for example, a ChatBoxPresenter
would like to wake up when a NewChatMessageEvent transits on the bus.
In GWTP it's simply a matter of annotating a method with @ProxyEvent
in the presenter -- ChatBoxPresenter is still lazily instantiated and
code split. How would you handle such a case in GWT 2.1 short of
instantiating the ChatBoxPresenter at app start?

In the GWTP samples we use singleton presenters, which makes it easy
to retain state during the app lifetime, a frequent use case. Also, it
cuts down on the cost of instantiating and garbage collecting the
presenters all the time. Finally, singleton presenters ensure that you
don't mistakenly attach two instances of the presenter to the same
singleton view. However, nothing prevents you from using non-singleton
presenters. GWTP presenters have the equivalent of a resettable event
bus, and every handlers are unregistered upon an unbind(). In fact,
GWTP offers reusable components separating logic from (non-singleton)
views -- which we call PresenterWidget. These are quickly becoming one
of the most popular feature of the framework and I don't find their
equivalent in GWT.

@Nicolas, Re: the need for a proxy interface
I believe it is a limitation of GWT generators that they have to be
attached to classes/interfaces. If anybody has a better idea I'm a
buyer. But isn't it better than manually writing/editing
ActivityManagers?

Cheers,

Philippe

On Nov 8, 1:35 am, Nicolas Antoniazzi <nicolas.antonia...@gmail.com>
wrote:

Nicolas Antoniazzi

unread,
Nov 8, 2010, 5:01:36 PM11/8/10
to google-we...@googlegroups.com
@Nicolas, Re: the need for a proxy interface
I believe it is a limitation of GWT generators that they have to be
attached to classes/interfaces. If anybody has a better idea I'm a
buyer. But isn't it better than manually writing/editing
ActivityManagers?

Is it not possible to set an annotation above the presenter ?
if presenters implements an interface (Presenter) it should be possible to handle it with a generator and write extra code, no ? (Well I suppose, I never tried to write a real generator).
However, this generator might be more difficult to write since it has to mix generated code with user code.

It might look a but curious, for the hand written part. But to me, it looks ugly to have empty inner interfaces in my code. Hand coded place are a bit longer to write (10 seconds), but at least, it is a classic style :)
However, I am using uiBinder and the empty UiBinder<> interface is ugly too... And I can't do anything against it :) (But I am still looking for a way of remove it. Maybe that gin will help me).

I think that my vision about code style is very personal and that lots of people prefer to use the annotated inner interface, so do not worry about my comments Phillipe :)

Cheers,

Nicolas 

Cheers,

  Philippe

On Nov 8, 1:35 am, Nicolas Antoniazzi <nicolas.antonia...@gmail.com>
wrote:
> Hi Phillipe,
>
> Also, I think it's a bit unfair to call GWTP's code generation "magic"
>
>  when GWT relies on it for so many different things... But if you
>
> > really want to write proxys yourself, GWTP's allows it.
>
> Yes, I agree that I was a bit unfair with GWTP. In my opinion, it would be a
> geater tool (for me) if the code in front of generators were more concise
> (just annotation, no empty interfaces to add), and maybe more "optional".
> bindPresenter() needs view, proxyplace, presenter. But if I prefer to not
> use ProxyPlace as you suggest, I can't.
>
> > Out of curiosity, which version of GWTP did you try?
>
> 0.4. But I might not have been in the depth of the framework (Just coded 4
> main pages of my app) until I get blocked by the Top Div/RootPresenter
> problem that I explained before.
>
> Cheers,
>
> Nicolas.

Thomas Broyer

unread,
Nov 9, 2010, 4:32:37 AM11/9/10
to Google Web Toolkit


On 8 nov, 21:42, PhilBeaudoin <philippe.beaud...@gmail.com> wrote:
> Thanks Thomas.
>
> So the way I understand it, the ActivityManager/ActivityMapper are GWT
> 2.1 equivalent's of GWTP's proxy for the purpose of navigation. It's
> just that in GWTP you don't need to create or modify a separate class,
> all is done within your presenter.
>
> In my apps, I often have some presenters that need to be awoken when a
> given message transit on the bus. Say, for example, a ChatBoxPresenter
> would like to wake up when a NewChatMessageEvent transits on the bus.
> In GWTP it's simply a matter of annotating a method with @ProxyEvent
> in the presenter -- ChatBoxPresenter is still lazily instantiated and
> code split. How would you handle such a case in GWT 2.1 short of
> instantiating the ChatBoxPresenter at app start?

As I understand it, your ChatBoxPresenter isn't related to a "place",
i.e. it's "awoken" based on a "business event", not a navigation
event; and in other words, it's not an Activity: case made.
Activities (ActivityManager) is limited in scope to reacting to place
changes and navigation (not that you couldn't use the Activity
"contract" in other scenarios, such as your "chat box", but the
ActivityManager wouldn't be the right tool for the job, you'd have to
find/write another "activity manager" for your different use case).

In other words: GWT 2.1 Activities won't replace GWTP as a whole (and
I believe, as I already said in the past, that it's not its goal
either).

Reply all
Reply to author
Forward
0 new messages