Gin actually falls back on calling GWT.create() if it can't find a
binding for an injected dependency. This means that, using Bruce's
example, you could have something like this:

public class SomeWidget() {

  @Inject
  public SomeWidget(PersonBeanWithMethodCallLogger personBean) {
    person.getName();
  }
}

All you need to do is bind SomeWidget, but no implicit binding is
required for PersonBeanWithMethodCallLogger. It might actually work if
you inject PersonBean, I'll check it out later though.

With regards to unit testability. If you use Gin throughout, and don't
instantiate any UIObject anywhere in your code (but rather DI them),
you can fully mock anything if you use GWTMockUtilities calling the
disarm() and restore() methods (see the class' Javadoc). You can then
write integration tests using GWTTestCase by having a Ginjector inside
your test case and calling GWT.create() on it.

> ... I'm not sure if it handles RPC methods with
> classes have have @Inject annotations

Hmm, but don't you normally send some kind of Model or domain object
over the wire and not something that would need to be injected with
dependencies by Gin?

And Bruce, that's an interesting example. I was thinking how one would
implement AOP in GWT, perhaps it's not as hard as I originally
thought. Is there a way to extend this example to dynamically create
proxies for any class that'll be advised by some aspect?

Also, Nicolas, AFAIK, the GWT team (bobv) is working on a data binding
(and validation?) framework. I'm hoping something will hit the
incubator soon so we can all jump on board and help out. It'd
definitely have saved us thousands of lines of glue code ;).

P.S. Sorry about not writing up that how-to for GWTMockUtilities,
Bruce. I'll try to do it some time this week.

Best regards,
--
Arthur Kalmenson



On Tue, Apr 21, 2009 at 2:58 PM, Ray Cromwell <cromwell...@gmail.com> wrote:
>
> Interesting question. Gin auto-creates RPC interfaces as well, for
> example, if you have:
>
> public interface MyFoo extends Ginjector {
>   MyServiceAsync getService();
> }
>
> then Gin implicitly looks for MyService.class and invokes
> GWT.create(MyService.class) when calling getService(). Since Gin is
> handling the creation, I'm not sure if it handles RPC methods with
> classes have have @Inject annotations, but you could probably setup a
> separate binding. The de-serialization logic in RPC is not likely to
> allow Gin interception, since it apparently uses default constructors
> to create classes, and what you want it to do is delegate the
> construction to some injectable mechanism (e.g. to substitute your own
> subclasses)
>
> It doesn't sound impossible to make this work, and is probably easier
> to get right than trying to make new Foo() interceptable by the
> compiler. I would join the Gin groups and ask the guys there about it.
>
> -Ray
>
>
> On Tue, Apr 21, 2009 at 11:49 AM, nicolas de loof
> <nicolas.del...@gmail.com> wrote:
>> Sounds a good solution.
>> How would this solve the use case "data returned by RPC call" ?
>>
>> 2009/4/21 Ray Cromwell <cromwell...@gmail.com>
>>>
>>> I really think Guice-style dependency injection is the way to go to
>>> solve this problem, rather than trying to emulate Java
>>> Proxies/Classloader in the compiler. If you use Guice/Gin, then in Gin
>>> you can inject GWT.create-d versions, and in JUnit-mode, you can use
>>> regular Guice injection. The code use is 99% between GWT and non-GWT
>>> versions test versions, with the exception of the
>>> Guice-config/Injector creation.
>>>
>>> Because of the way Gin works transitively, you only need a single
>>> GWT.create() and this is isolated to your startup code while in your
>>> JUnit version, you kick off a Guice-injected class instead.
>>>
>>> -Ray
>>>
>>> On Tue, Apr 21, 2009 at 11:28 AM, nicolas de loof
>>> <nicolas.del...@gmail.com> wrote:
>>> > A simple example : databinding
>>> > Lets consider I want to bind some Label text to some model Bean value.
>>> > Gwt
>>> > Label widget "text" can be accessed as a javaBean property, so this
>>> > sound a
>>> > typical java.beans.binding use-case
>>> > This requires my model bean to support PropertyChangeListeners. As I'm
>>> > lazy
>>> > I'd like a generator to create an "enhanced" model class with such
>>> > support
>>> > for the "value" property.
>>> > I can get this to work today if my model Bean is created using
>>> > GWT.create(),
>>> > but this makes my code GWT-dependant and not testable in "standalone"
>>> > junit.
>>> > If the generator "enhanced" class is used even when I use " new Model()
>>> > " or
>>> > get a Model bean from RPC, my code can be easily unit tested.
>>> > Cheers,
>>> > Nicolas
>>> >
>>> > 2009/4/21 Bruce Johnson <br...@google.com>
>>> >>
>>> >> On Tue, Apr 21, 2009 at 12:38 PM, nicolas de loof
>>> >> <nicolas.del...@gmail.com> wrote:
>>> >>>
>>> >>> The only critism I'd have is the requirement to use GWT.create() to
>>> >>> get
>>> >>> code from a generator. This is a requirement when the generated code
>>> >>> doesn't
>>> >>> extend the source type (for example for Async interfaces) but not when
>>> >>> the
>>> >>> genrator is used to add some capabilities (ie acts as a decorator),
>>> >>> for
>>> >>> example to add PropertyChangeListener to a model bean.
>>> >>
>>> >> Perhaps if you could distill down a more concrete example, it could get
>>> >> the wheels turning. Enhancements to GWT.create() certainly aren't off
>>> >> the
>>> >> table. Ray Cromwell has made some pretty useful-sounding suggestions in
>>> >> the
>>> >> past. We just have to find large-group consensus on what makes the most
>>> >> sense, striking a balance between power, clarity, and of course,
>>> >> optimizability.
>>> >>
>>> >> Here's a quick back-of-envelope pattern that could possibly work:
>>> >>
>>> >> class PersonBean {
>>> >>   void setName(String name):
>>> >>   String getName();
>>> >> }
>>> >>
>>> >> interface MethodCallLogger {
>>> >> }
>>> >>
>>> >> class MyEntryPoint {
>>> >>   class PersonBeanWithMethodCallLogger extends PersonBean implements
>>> >> MethodCallLogger {
>>> >>     // empty, but a subclass gets generated
>>> >>   }
>>> >>
>>> >>   public void onModuleLoad() {
>>> >>     // Have a generate-with rule for MethodCallLoggerGenerator,
>>> >> triggered
>>> >> by assignability to "MethodCallLogger"
>>> >>     PersonBean pb = GWT.create(PersonBeanWithMethodCallLogger.class);
>>> >>     pb.setName("Nicolas");
>>> >>   }
>>> >> }
>>> >>
>>> >> // Generated...
>>> >> class PersonBeanWithMethodCallLoggerImpl extends
>>> >> PersonBeanWithMethodCallLogger {
>>> >>   void setName(String name) {
>>> >>     someLogger.log("setName('" + name + "') called");
>>> >>     super.setName(name);
>>> >>   }
>>> >>
>>> >>   ...
>>> >> }
>>> >>
>>> >> As formulated above, this pattern doesn't compose well. But it might be
>>> >> that we can forge a pattern like this into something everyone likes
>>> >> eventually.
>>> >>
>>> >> -- Bruce
>>> >>
>>> >>>
>>> >>> This makes unit testing more difficult as code that uses GWT.create
>>> >>> cannot run in "classic" jUnit. It would be great to have the compiler
>>> >>> use
>>> >>> generator-extended classes even when created using the standard "new"
>>> >>> keyword.
>>> >>> Thanks a lot for the explanation.
>>> >>> Nicolas
>>> >>>
>>> >>> 2009/4/21 Bruce Johnson <br...@google.com>
>>> >>>>
>>> >>>> A sort of philosophical meta-point that may or may not be of
>>> >>>> interest...
>>> >>>>
>>> >>>> When we started GWT, we were worried about managing the complexity of
>>> >>>> compile-time code generation, so we tried to find the simplest, most
>>> >>>> easy-to-debug approach we could think of. GWT's model of never
>>> >>>> changing
>>> >>>> existing code[1], but only adding new Java source during the compile,
>>> >>>> is
>>> >>>> really a design choice, not a technical limitation. The benefit of
>>> >>>> the
>>> >>>> current design is that you can add -gen to hosted mode and map the
>>> >>>> corresponding folder into your source path, and then easily step
>>> >>>> through all
>>> >>>> your code, both handwritten and generated, in the debugger. This
>>> >>>> avoids
>>> >>>> tricky or confusing situations wherein the source code you see
>>> >>>> appears to be
>>> >>>> doing something different than the bytecode that's running. It seems
>>> >>>> good to
>>> >>>> avoid that kind of dichotomy, on the principle that
>>> >>>> straightforward-though-verbose is generally better than
>>> >>>> fancy-but-confusing.
>>> >>>>
>>> >>>> [1] Overlay types were the first time we ever even did bytecode
>>> >>>> rewriting, and that support is implemented at a very deep level.
>>> >>>> Also, JSOs
>>> >>>> are intended to be among only a very few "magic" things in GWT
>>> >>>> (basically,
>>> >>>> JSNI, GWT.create(), GWT.runAsync(), and JSOs). We went to a lot of
>>> >>>> effort to
>>> >>>> ensure that JSOs worked according to a fixed set of rules that are
>>> >>>> not hard
>>> >>>> to comply with, even if people don't fully understand why the
>>> >>>> implementation
>>> >>>> requires it.
>>> >>>>
>>> >>>> On Mon, Apr 20, 2009 at 11:11 AM, Thomas Broyer <t.bro...@gmail.com>
>>> >>>> wrote:
>>> >>>>>
>>> >>>>>
>>> >>>>>
>>> >>>>> On 20 avr, 08:43, nicolas de loof <nicolas.del...@gmail.com> wrote:
>>> >>>>> > > > I wonder if there is any way to also "pre-process" Java
>>> >>>>> > > > sources,
>>> >>>>> > > > for
>>> >>>>> > > example
>>> >>>>> > > > this would enable support for Aspect Oriented Programming or
>>> >>>>> > > > maybe some
>>> >>>>> > > > DataBinding framework.
>>> >>>>> >
>>> >>>>> > > Depends what you mean by "pre-process"... Generally, generators
>>> >>>>> > > analyze the class they're called for (for example, looking for
>>> >>>>> > > specific annotations on methods or on the class itself) and
>>> >>>>> > > according
>>> >>>>> > > to this generate a Java class extending the one they've been
>>> >>>>> > > called
>>> >>>>> > > for.
>>> >>>>> > > (is this understandable? is this at least no-so-bad english?)
>>> >>>>> >
>>> >>>>> > In many case the generator will create from MyClassX some
>>> >>>>> > MyClassXImpl or
>>> >>>>> > equivalent that extends the original one, bu not REPLACE it as
>>> >>>>> > Java
>>> >>>>> > source.
>>> >>>>> > This is what I mean by "pre-process".
>>> >>>>> >
>>> >>>>> > For example, to implement a AOP framework I'd like to instrument
>>> >>>>> > all
>>> >>>>> > calls
>>> >>>>> > to some method. For this reason I'd like a generator /
>>> >>>>> > pre-processor
>>> >>>>> > to
>>> >>>>> > check the source files and detect the matching pointcuts to add
>>> >>>>> > some
>>> >>>>> > adived
>>> >>>>> > code. Many other example can apply, including annotation
>>> >>>>> > processing
>>> >>>>> > for
>>> >>>>> > declarative coding (ex : @Property annotation to automagically
>>> >>>>> > introduce the
>>> >>>>> > required PropertyChangeListeners)
>>> >>>>>
>>> >>>>> You would generate a subclass that delegates to super.method()
>>> >>>>> after/
>>> >>>>> before the aspect(s) code.
>>> >>>>>
>>> >>>>> > I never tried it myself, but I'n not sure a generator can REPLACE
>>> >>>>> > the
>>> >>>>> > original Java Source.
>>> >>>>>
>>> >>>>> AFAICT, it can't, but there's probably no need for this.
>>> >>>>>
>>> >>>>> > I may be wrong but I also thing the generated code is
>>> >>>>> > only available when using   GWT.create(),
>>> >>>>>
>>> >>>>> The generator is only called at the point where GWT.create() is
>>> >>>>> called
>>> >>>>> (I may be wrong but you could generate a different output for each
>>> >>>>> GWT.create() call-point for the same class literal), so yes, you're
>>> >>>>> right.
>>> >>>>>
>>> >>>>>
>>> >>>>>
>>> >>>>
>>> >>>>
>>> >>>>
>>> >>>
>>> >>>
>>> >>>
>>> >>
>>> >>
>>> >>
>>> >
>>> >
>>> > >
>>> >
>>>
>>>
>>
>>
>> >
>>
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to