Code Splitting Simple Example Still getting Thrown into Left Overs

158 views
Skip to first unread message

Ashton Thomas

unread,
Jan 5, 2013, 11:27:51 AM1/5/13
to google-we...@googlegroups.com
I would greatly appreciate some input here. I am trying to use the below references to implement Code Splitting w/ Activities/Place/GIN

HOWEVER, I can't get anything to work. Not even a simple solution which I 'think' should be working regardless of my current implementation for A/P+GIN...

Thomas' ActivityAsyncProxy https://gist.github.com/3038878 (This is the method I am trying to use)

Other References:

My Hope is that I am doing something blatantly wrong. I have a simple Split Point that creates a string and custom widget (very simple) and shows a PopupPanel. However it still gets thrown into the Left overs.
My end goal is the complete solution to MVP/GIN (which originally didn't work so I thought I'd try this simple solution - no luck so I'm coming to you guys:)


I've attached a piece of the Compile Report and including the below links for better reference:


Button b = new Button("Click Me", new ClickHandler() {

      @Override

      public void onClick(ClickEvent event) {

        GWT.runAsync(Application.class, new RunAsyncCallback() {

          @Override

          public void onSuccess() {

            String sp3 = "3sp33sp33sp33sp33sp33sp33sp33sp33sp33sp33sp33sp33spp3";

            VerticalPanel vp = new VerticalPanel();

            vp.add(new InlineLabel(sp3));

            MySPTestWidget t = new MySPTestWidget(); // Simple Composite with unique string to test SP

            vp.add(t);

            PopupPanel p = new PopupPanel();

            p.setWidget(vp);

            p.center();

          }

          @Override

          public void onFailure(Throwable reason) {

            Window.alert("SP Application Failed");

          }

        });

      }

    });



Any thoughts on why the simple (and possibly the ultimate goal of MVP/GIN-CodeSplitting) is not working?


Thanks very much in advance!
-Ashton

GwtSPCompileReport.jpg

Ed

unread,
Jan 6, 2013, 5:42:38 PM1/6/13
to google-we...@googlegroups.com
I haven't looked in detail at your code, but you might experiencing the same problems I had, see this issue (and the linked forum post):


Op zaterdag 5 januari 2013 17:27:51 UTC+1 schreef Ashton Thomas het volgende:

Ashton Thomas

unread,
Jan 7, 2013, 11:14:31 AM1/7/13
to google-we...@googlegroups.com
Ed, thanks for the reply.


I did some more digging off of the link you sent and, although I don't think this is the same issue, I found the following issue:

(Note: I switched versions to 2.4 and still had the same problem)

It seems I was using both -draftCompile and -compileReport

I removed -draftCompile and it split the simple example correctly.

As for my ultimate goal of Code Splitting using MVP/GIN, I am unable to get the solution found here:
to give the correct split points as it links a dependency on the abstract method createInstance().

I have since created a new test branch with solution found here: 

my branch is at:

This is producing the correct split points; however, AFAIK we haven't found a silver bullet for GIN/MVP/Code Splitting:

I will look into both solutions to see if I can find my error (if it is something I am doing wrong) or a possible work-around:
- Thomas' ActivityAsyncProxy - not breaking dependency chain (problem my config/implementation)
- Saeed's async mapper - Edge cases 

If anyone has some input, I would greatly appreciate it as I am just recently digging into Code Splitting.

Thanks!
-Ashton

Ashton Thomas

unread,
Jan 7, 2013, 11:14:46 AM1/7/13
to google-we...@googlegroups.com
Ed, thanks for the reply.


I did some more digging off of the link you sent and, although I don't think this is the same issue, I found the following issue:

(Note: I switched versions to 2.4 and still had the same problem)

It seems I was using both -draftCompile and -compileReport

I removed -draftCompile and it split the simple example correctly.

As for my ultimate goal of Code Splitting using MVP/GIN, I am unable to get the solution found here:
to give the correct split points as it links a dependency on the abstract method createInstance().

I have since created a new test branch with solution found here: 

my branch is at:

This is producing the correct split points; however, AFAIK we haven't found a silver bullet for GIN/MVP/Code Splitting:

I will look into both solutions to see if I can find my error (if it is something I am doing wrong) or a possible work-around:
- Thomas' ActivityAsyncProxy - not breaking dependency chain (problem my config/implementation)
- Saeed's async mapper - Edge cases 

If anyone has some input, I would greatly appreciate it as I am just recently digging into Code Splitting.

Thanks!
-Ashton


On Sunday, January 6, 2013 5:42:38 PM UTC-5, Ed wrote:

Jens

unread,
Jan 7, 2013, 12:27:26 PM1/7/13
to google-we...@googlegroups.com
Currently using http://code.google.com/p/google-web-toolkit/issues/detail?id=5129#c18 and so far I haven't seen an issue with it. I also proxy complete ActivityMappers so I can freely decide if I want to code split a single activity or a group of activities because it does not buy you anything if you make a split point for a very small activity just because its an activity. But today, GWT 2.5 negates that a bit as it allows you to automatically merge split points (although you dont have any control)

-- J.

Ashton Thomas

unread,
Jan 8, 2013, 9:24:26 AM1/8/13
to google-we...@googlegroups.com
Jens, thanks for the input.

If you don't mind me asking, 

- Do you link Activities directly to specific places: Activity<P extends Place> ?
- Somewhat related, do you set an actual "place" (constructor/setter) or just a particular param (DTO/other object/variable)?
- Do you have a lot of "ActivityWithPlaceProxy" boiler plate?
- Do you show any loading on the ActivityWithPlaceProxy.start() prior to the actual start of the desired activity?
- I Assume by proxy complete mappers you mean: build a proxy mapper delivered via AsyncProvider which will pull all activities in that mapper at once??
- It would appear there is a situation when using activities provided via RunAsync that the default ActivityMapper behavior is not desired:
--- In non-RunAsync, if a new Activity starts AND sets the display widget/panel prior to the activity which preceded it (user navigates before current activity can set display), clear/kill current activity and proceed with next
---- However, this is not the same when RunAsync is involved as Activity "A" can be called and downloaded. Prior to "A" being downloaded, Activity "B" is started and downloads or loads faster than "A"
---- So "A" will set the display panel AFTER Activity "B" -> The default ActivityManager will give control to "A" and kill of "B" even though we probably want to give "B" the control and display since "A" took longer loading and setting the display...
---- I am not sure if my logic fits reality, but I have extended Saeed's asyncMapper/Manager example to use the Place to determine what activity gets control
---- (That last place fired gets control. So if an activity loads but is linked - pass the Place as params through the async calls - to a different place, kill it)

* I have included some links to this process below incase anyone wants to do verify or reference:

(Branch: act-async-mapper)

Using "Place" to determine start order (or ignoring of previous/stale activities due):

Saeed's Original:

Jens

unread,
Jan 8, 2013, 2:58:21 PM1/8/13
to google-we...@googlegroups.com

If you don't mind me asking, 

- Do you link Activities directly to specific places: Activity<P extends Place> ?
- Somewhat related, do you set an actual "place" (constructor/setter) or just a particular param (DTO/other object/variable)?

Yes I do. Its like

interface CustomActivity extends Activity<P extends Place> {
  void setPlace(P place);
}

Along with an abstract CustomActivityBase class that implements this interface and adds some protected "isActive" logic: the activity is considered inactive if cancel/stop is called so that any RPC call and its onSuccess() code will be disabled in the activities start() method (user navigates away before RPC returns):

onSuccess(..) {
  if(isActive()) {
   ...//proceed
  }
}

 
- Do you have a lot of "ActivityWithPlaceProxy" boiler plate?

Its more or less the usual if-construct to instantiate the correct activity for a given place in the ActivityMapper. There is a bit additional code because of the complete mappers I code split (see below).

 
- Do you show any loading on the ActivityWithPlaceProxy.start() prior to the actual start of the desired activity?

Not yet. Depending on how you want to notify your users you could:
1.) Implement a custom AcceptsOneWidget/SimplePanel/SimpleLayoutPanel that shows a loading text/icon in the display area when no child widget is set (on construction and on setWidget(null)).
2.) Fire a custom event on the event bus and let a global notification mechanism listen for it.

 
- I Assume by proxy complete mappers you mean: build a proxy mapper delivered via AsyncProvider which will pull all activities in that mapper at once??

Its a normal ActivityMapper having Gin Provider<ConcreteActivity> as fields and the usual dispatch code in getActivity(Place). You then have a slightly different implementation of your AsyncActivityWithPlaceProxy that does not use an AsyncProvider<CustomActivity> but an AsyncProvider<ActivityMapper> and loads the mapper in the proxy's start() method. When the mapper is loaded you get the correct Activity from the mapper using the place that has been set to the proxy through the ActivityMapper that is assigned to the ActivityManager and finally start the activity.

Obviously the ActivityMapper assigned to the ActivityManager has to catch all possible places for that async mapper hidden in the activity proxy:

getActivity(Place place) {
   if(place instanceof ConcretePlace1 || place instanceof ConcretePlace2 || ...) {
     AsyncActivityWithPlaceAndMapperProxy activity = //...
     activity.setPlace(place) // the internal mapper will dispatch the place to the correct activity.
   }
}

You could mitigate that by introducing a common super class (or marker interface) for places that are handled by the same async ActivityMapper.

 
- It would appear there is a situation when using activities provided via RunAsync that the default ActivityMapper behavior is not desired:
--- In non-RunAsync, if a new Activity starts AND sets the display widget/panel prior to the activity which preceded it (user navigates before current activity can set display), clear/kill current activity and proceed with next
---- However, this is not the same when RunAsync is involved as Activity "A" can be called and downloaded. Prior to "A" being downloaded, Activity "B" is started and downloads or loads faster than "A"
---- So "A" will set the display panel AFTER Activity "B" -> The default ActivityManager will give control to "A" and kill of "B" even though we probably want to give "B" the control and display since "A" took longer loading and setting the display...
---- I am not sure if my logic fits reality, but I have extended Saeed's asyncMapper/Manager example to use the Place to determine what activity gets control
---- (That last place fired gets control. So if an activity loads but is linked - pass the Place as params through the async calls - to a different place, kill it)

The activity that is active is your AsyncActivityProxy. The start() method (maybe) does an async RPC call like most ordinary Activities probably also do to load some data. So your AsyncActivityProxy should also have the same "isActive" logic like an ordinary activity. So in onSuccess() of GWT.runAsync() you do: 

if(isActive()) { //false if cancel/stop has been called on the proxy while activity is downloaded
   activity.setPlace(place);
   activity.start(panel, eventbus);
}

Only the activity that is currently active in the ActivityManager will win because the previous one will not proceed if the download completes to late (isActive() is false). Am I missing something?


Speaking in menu items I use the async ActivityMapper to generate a single split point that contains all the sub menu items of a single main menu item. As soon as an Activity for a given sub menu item gets too large I remove it from the async ActivityMapper and code split it separately.


Feel free to ask more :-)


-- J.
Reply all
Reply to author
Forward
0 new messages