fmgasparino / google-gin

Automatically exported from code.google.com/p/google-gin
Apache License 2.0
0 stars 0 forks source link

Provide a way to allow sub-injector instances #61

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
This is mostly an anticipatory issue for using GIN with the upcoming 'runAsync' 
feature of GWT 
2.0. I haven't actually tried doing this in code yet, but I'm working on 
another GWT library that 
uses GIN and can see it coming...

Essentially, the issue is that it's currently difficult (impossible?) to use 
GIN within the context of 
code loaded by a runAsync call. Well, it's actually possible, by calling 
GWT.create( 
MyAsyncInjector.class ), but the new injector can't access any of the objects 
already created in 
the main application's Injector.

What would be good would be a way to instantiate a sub-GInjector that will fall 
back to a parent 
GInjector if no bindings are available. I haven't quite figured out how this 
might work yet though, 
since it's tricky passing in instance objects to GWT.create()...

If I come up with any ideas I'll post them here.

Original issue reported on code.google.com by Bitmei...@gmail.com on 27 Oct 2009 at 3:54

GoogleCodeExporter commented 9 years ago
Hm, I'd expect runAsync to work without two injectors. GWT can split the single 
injector class in to multiple fragments, I think. Would be great for someone to 
dig 
deeply in to this -- we've had some preliminary investigations before but 
nothing 
definitive.

I'd like to believe we can make Gin + runAsync work well without exposing any 
complexity to the developer.

Original comment by bsto...@google.com on 27 Oct 2009 at 9:13

GoogleCodeExporter commented 9 years ago
If that's the case, great. Probably worth confirming I guess. I won't be able 
to move my current codebase to GWT 
2.0 in the short term, but I'll see if I can come up with a test case.

Original comment by Bitmei...@gmail.com on 27 Oct 2009 at 11:20

GoogleCodeExporter commented 9 years ago
runAsync + Gin's Provider works great for me, I just have to create proxy class 
for 
each "main" (with it's own dependencies) class. this proxy class just places 
provider.get() inside RunAsyncCallback onSuccess.

If there's a way to avoid this, I'm all ears

Original comment by dusan.ma...@gmail.com on 29 Oct 2009 at 1:54

GoogleCodeExporter commented 9 years ago
Hi Dusan,

I'm not exactly tracking with your explanation? Could you post a code snippet?

Essentially, the issue with runAsync is making sure that your classes don't 
leak directly into other parts of the 
code, right? It seems that you can have class references, just not calls to 
class constructors outside the 
'runAsync' context, or those classes can't get split out, is that correct? I'm 
a little hazy on exactly how that might 
actually work, but I'm guessing there's some JavaScript magic going on in the 
background somewhere...

Original comment by Bitmei...@gmail.com on 29 Oct 2009 at 3:17

GoogleCodeExporter commented 9 years ago
Hi David, that's exactly what I'm trying to solve with "proxy presenters". I 
got my 
application split into presenters (gwt-presenter), where I have one main, and 
then 
child presenters which have dependencies on other presenters.

If I feel like I need some of them loaded with runAsync, I replace their 
instantiation (I use Gin) with Proxy, which instead of registering the "real" 
presenter, wraps this instantiation and registration (with main) within 
RunAsyncCallback. And it works! The code gets splitted exactly like I intented, 
I 
just need to watch my dependencies.

I was really surprised how nicely this works: Gin (Guice) + gwt-presenter + 
code 
splitting is a piece of cake. There are of course some issues, but those are 
rather 
specific to gwt-presenter (PlaceManager)

Original comment by dusan.ma...@gmail.com on 29 Oct 2009 at 3:40

GoogleCodeExporter commented 9 years ago
Hi Dusan,

What about the child dependencies? Where do you register them? Still in the 
main gin
module?

Original comment by marc...@gmail.com on 29 Oct 2009 at 3:46

GoogleCodeExporter commented 9 years ago
Hi Dusan,

I'm still not quite understanding your description. Any chance you could post 
your 'runAsync' method at least, so 
I can see how you're doing your injection?

Original comment by Bitmei...@gmail.com on 29 Oct 2009 at 4:10

GoogleCodeExporter commented 9 years ago
okay, here you go, but I guess it doesn't make sense since I can't post "big 
picture". Here is the proxy class http://pastie.org/675173

Real MediaPresenter, has it's own dependencies (MediaFormPresenter, custom 
widgets, 
...) Now, I have sort of main presenter which just register (addModule() 
method) all 
child presenters, but doesn't care about result of that registration. So if I 
use my 
Proxy instead, MediaPresenter (and all of it's dependencies) will end up in a 
separate split point.

Take a look at that class I posted. If I want some presenter to be in initial 
download, in register() method, I just skip calling runAsync(), and do 
addModule() 
right there.

Original comment by dusan.ma...@gmail.com on 29 Oct 2009 at 4:31

GoogleCodeExporter commented 9 years ago
Ah, ok. That helps a lot.

So the key with using runAsync and GIN is to inject Provider<X> instead of X 
directly, then call Provider.get() 
inside the runAsync's 'onSuccess()' method. Which, now that I look back is what 
you said in the first place :)

I'm wondering if there's a way to adapt the 'Gateway' pattern (essentially, a 
private constructor and an extra 
callback to receive the created class from 'onSuccess') to work nicely with 
Provider/GIN.

Alternately, would it be useful/possible to have a scope for runAsync classes. 
I'm thinking probably not...

Original comment by Bitmei...@gmail.com on 29 Oct 2009 at 4:57

GoogleCodeExporter commented 9 years ago
yeah, that's what I'm trying to figure out, how to skip those fugly proxy 
classes. So 
far no idea. You can of course pass provider to createAsync (as in gateway 
pattern), 
that could work

Original comment by dusan.ma...@gmail.com on 29 Oct 2009 at 5:05

GoogleCodeExporter commented 9 years ago
What we kind of need is an asynchronous version of Provider that can be 
injected into classes wherever. 
Essentially a generic Gateway pattern. Let's call it Gateway for now. Eg:

public class Gateway<Type> {
  public interface Callback {
    void onSuccess( Type value );
    void onFailure( Throwable exception );
  }

  private final Provider<Type> value;

  @Inject
  public Gateway( Provider<Type> value ) {
    this.value = value;
  }

  public void get( final Callback callback ) {

            GWT.runAsync(new RunAsyncCallback() {

                @Override
                public void onFailure(Throwable reason) {
                    callback.onFailure( reason );
                }

                @Override
                public void onSuccess() {
                    callback.onSuccess( value.get() );
                }});
  }
}

Then, ideally, you'd just inject "Gateway<MyType> myType" into your other 
classes and call 'get( new 
Callback<MyType>() {...})' and you're off to the races. However, I'm not sure 
how to get GIN to generically 
create typed classes.

Original comment by Bitmei...@gmail.com on 29 Oct 2009 at 5:21

GoogleCodeExporter commented 9 years ago
I tried to generalize my proxy class, and I got the types right, but suddenly 
GWT sent 
all my runAsync code to leftovers :(

more on that: http://groups.google.com/group/google-web-
toolkit/browse_thread/thread/783cac72e23950d1/67580bea02318832

Original comment by dusan.ma...@gmail.com on 29 Oct 2009 at 5:25

GoogleCodeExporter commented 9 years ago
Hmm. I'm not familiar enough with how it actually breaks the code apart to 
comment, unfortunately...I really 
should get a little test project going using GWT 2.0.

One last thought - what if my example code above was an abstract class, and you 
created concrete subclasses 
for specific types. Eg:

public class FooGenerator extends Generator<Foo> {
  @Inject
  public FooGenerator( Provider<Foo> foo ) {
    super( foo );
  }
}

Not sure if that would help the compiler figure out where to split or not...

Original comment by Bitmei...@gmail.com on 29 Oct 2009 at 5:48

GoogleCodeExporter commented 9 years ago
that's sort of what I do with proxies. but let's stop this discussion as it is 
not 
related to the bug in any way, somebody can get upset :)

Original comment by dusan.ma...@gmail.com on 29 Oct 2009 at 5:56

GoogleCodeExporter commented 9 years ago
Well, it is basically - this discussion was my original intent when raising the 
issue. Probably the issue should be 
retitled 'Support GWT.runAsync()'. And then invalidated, since it seems like it 
is already possible, with careful 
planning...

Original comment by Bitmei...@gmail.com on 29 Oct 2009 at 6:05

GoogleCodeExporter commented 9 years ago
 hacked up GIN few weeks ago and added an AsyncProvider<T> interface:

interface AsyncProvider<T> {
   get(AsyncCallback<T>); // resuing same rpc AsyncCallback interface
}

GIN would then create the the object T in a runAsync block and then pass it via 
the 
AsyncCallback interface. Something like this:

GWT.runAsync(new RunAsyncCallback() {

  public void onSuccess() {
    // same gin generation code to create T
    asyncCallbac.onSuccess(T);
  }

  public void onFailure(Throwable ex) {
    asyncCallback.onFailure(ex);
  }
}
I am adding the patch here, not very well tested or polished, but I made the 
code 
splitting work with the existing samples app (patch for that attached as well). 
If you 
guys like the idea, I can polish it up and work with gin developers to get this 
in.

Original comment by fazal.a...@gmail.com on 29 Oct 2009 at 7:44

Attachments:

GoogleCodeExporter commented 9 years ago
I like the approach. Makes things much tidier for working with runAsync via 
injections. This issue should 
definitely get renamed though, or another created more appropriate to the 
actual change being requested.

Original comment by Bitmei...@gmail.com on 29 Oct 2009 at 8:06

GoogleCodeExporter commented 9 years ago
One side note - this would bind the GIN trunk to the current GWT trunk, which 
would be a a bit of a pain for 
those of us who haven't made the jump yet...

Any plans for a GIN point release?

Original comment by Bitmei...@gmail.com on 29 Oct 2009 at 8:08

GoogleCodeExporter commented 9 years ago
+1 . I like the idea, I believe it should be part of Gin.

But again, it would be quite common to reuse subclass of AsyncCallback, and we 
would
face issue described here:
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/783cac72e
23950d1/67580bea02318832

Original comment by dusan.ma...@gmail.com on 29 Oct 2009 at 8:18

GoogleCodeExporter commented 9 years ago
The big reason that I didn't move forward with this was one of the gin guys 
said that 
they are preparing for a 1.0 release soonish. Once that happens, they will look 
into 
having a dependency on GWT 2.0

Original comment by fazal.a...@gmail.com on 29 Oct 2009 at 11:29

GoogleCodeExporter commented 9 years ago
There's no way to stop AsyncCallback reuse (the Gateway pattern has the same 
issue, I would imaging. It will just 
have to be documented that it Should Not Be Done, yes?

Original comment by Bitmei...@gmail.com on 30 Oct 2009 at 2:40

GoogleCodeExporter commented 9 years ago
Actually, having looked at the code, because it doesn't actually refer to any 
GWT 2-specific classes in code (only 
in Strings where generating code), this will actually compile against GWT 
1.6/1.7. So theoretically this could be 
added in GIN 1.0, but would only actually be usable in GWT 2 environments, 
since the generated code will fail to 
compile in 1.7.

Original comment by Bitmei...@gmail.com on 30 Oct 2009 at 4:14

GoogleCodeExporter commented 9 years ago
what't the problem with having gwt-trunk branch of gin? nevermind, I was 
actually 
thinking whether some GinModule.installAsync() or AsyncGinModule wouldn't be 
more 
appropriate then having AsyncProvider acting directly on dependencies?

Original comment by dusan.ma...@gmail.com on 30 Oct 2009 at 11:39

GoogleCodeExporter commented 9 years ago

Original comment by aragos on 1 Dec 2009 at 1:48

GoogleCodeExporter commented 9 years ago
@fazal.asim: I applied your patch to my version of GIN and it worked perfectly. 
Thanks 
a lot for dramatically simplifying the process of using GIN with code 
splitting. Count 
my vote for inclusion of this feature in GIN.

Original comment by philippe.beaudoin on 3 Mar 2010 at 7:47

GoogleCodeExporter commented 9 years ago
@philippe , rock !

Original comment by second.c...@gmail.com on 4 Mar 2010 at 6:07

GoogleCodeExporter commented 9 years ago
The AsyncProvider patch was priceless. It helped us to remove tons of code, 
made the 
design so much cleaner and lighter. No proxies, no multiple GIN 
modules/ginjectors 
needed.
We would really love to see it in the official GIN release.

Original comment by urg...@gmail.com on 9 Mar 2010 at 11:33

GoogleCodeExporter commented 9 years ago
cool.. I will try to find some time this week to work on this. 

Original comment by fazal.a...@gmail.com on 10 Mar 2010 at 2:14

GoogleCodeExporter commented 9 years ago
I also would like to vote to get this into the official GIN releases. Can 
anyone from
the team comment on a __rough__ schedule when this could be possible and also 
if they
would consider including the patch?

Original comment by spra...@gmail.com on 10 Mar 2010 at 10:49

GoogleCodeExporter commented 9 years ago
AsyncProvider would too be useful to provide remote instances across RPC

Original comment by andres.a...@gmail.com on 10 Mar 2010 at 12:53

GoogleCodeExporter commented 9 years ago
I'd be happy to include this, I'll work with Asim to get it into the code base.

Original comment by aragos on 10 Mar 2010 at 7:38

GoogleCodeExporter commented 9 years ago
ok, finally got it out for review:

http://codereview.appspot.com/646042

Original comment by fazal.a...@gmail.com on 19 Mar 2010 at 4:02

GoogleCodeExporter commented 9 years ago
Any update on this? The code review has been stalled on some test failure for a 
while. 
I'd like to get it in my release of gwt-platform.

Original comment by philippe.beaudoin on 29 Mar 2010 at 6:14

GoogleCodeExporter commented 9 years ago
The test failure was fixed, waiting on peter to try to patch it and try again. 

Original comment by fazal.a...@gmail.com on 29 Mar 2010 at 6:54

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Any progress on the review / patch process?
No updates mentioned on the codereview page.
As a lot of people are really interested in this particluar fix it would be 
nice if
we could move on to get this into trunk.

Original comment by kotes...@gmail.com on 30 Mar 2010 at 1:14

GoogleCodeExporter commented 9 years ago
Committed in r137. Many thanks to fazal.asim for submitting this patch!

Original comment by aragos on 30 Mar 2010 at 9:33

GoogleCodeExporter commented 9 years ago
Thanks so much to both of you! I simply replaced my old patched gin with r137 
and it 
works like a charm. For anybody interested to get their hands on this awesome 
feature I 
packaged it in a jar at http://code.google.com/p/gwt-platform/

Original comment by philippe.beaudoin on 30 Mar 2010 at 11:27

GoogleCodeExporter commented 9 years ago
Thanks a bunch. Great work & collaboration alltogether

Original comment by kotes...@gmail.com on 6 Apr 2010 at 6:51

GoogleCodeExporter commented 9 years ago
This was kick-ass work... can we get a quick note about async injectors added 
to the wiki / tutorial page? With a 
trunk-only disclaimer, of course. A quick explanation would be great. 

Original comment by sudhi...@gmail.com on 7 Apr 2010 at 9:15

GoogleCodeExporter commented 9 years ago
I plan to add some docs about this but haven't had the chance. stay tuned :)

Original comment by fazal.a...@gmail.com on 7 Apr 2010 at 1:00

GoogleCodeExporter commented 9 years ago
I ran into a problem today where the development version of AsyncProvider works 
well, 
but the javascript version throws an Exception. I've documented it on the forum:
 http://groups.google.com/group/google-gin/browse_thread/thread/995db1ebccbc3104?hl=en
We may want to enter this as a separated bug, but I wasn't 100% sure it was in 
AsyncProvider.

Original comment by philippe.beaudoin on 10 Apr 2010 at 1:02

GoogleCodeExporter commented 9 years ago
Maybe I am wrong,I still can't figure out a way to share instance(for 
example,EventBus) between multiple modules based on discussion of this 
thread.Can anybody give an example,thanks in advance.

Original comment by Alexande...@gmail.com on 19 Jan 2012 at 2:40

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
I don't get it eather... how do I share the instance of the eventbus with a 
child injector?

Thank you for any help!

Original comment by fippi...@gmail.com on 17 Feb 2012 at 5:48

GoogleCodeExporter commented 9 years ago
Some guy provided a working 
solution:http://www.amateurinmotion.com/articles/2009/11/02/async-with-gin.html,
it still works under(gwt 2.4+gin 1.5)

Original comment by Alexande...@gmail.com on 11 Apr 2012 at 4:05

GoogleCodeExporter commented 9 years ago
Why is it that T is now a ? extends T?

Original comment by christia...@arcbees.com on 10 Sep 2014 at 9:00