> Now, MyBean does not implement interface X, but a generator/AOP > interceptor could make a subclass of MyBean that has interface X > implement. IIRC, GWT RPC just invokes the default constructor, so > there's no way to intercept this and substitute a replacement.
Yeah, that is an interesting question. However, wouldn't the AOP be happening before you send the object over the wire? You wouldn't really care about any interception at that point.... -- Arthur Kalmenson On Wed, Apr 22, 2009 at 12:28 AM, Ray Cromwell <cromwell...@gmail.com> wrote: > > On Tue, Apr 21, 2009 at 7:11 PM, Arthur Kalmenson <arthur.k...@gmail.com> > wrote: >> >> 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? > > > I think what he's saying is that he might have an RPC method like this: > > public interface MyService extends RemoteService { > MyBean getBean(); > } > > Now, MyBean does not implement interface X, but a generator/AOP > interceptor could make a subclass of MyBean that has interface X > implement. IIRC, GWT RPC just invokes the default constructor, so > there's no way to intercept this and substitute a replacement. > > I think the other thing he might want to do is intercept client-side > UI classes and make them call addPropertyChangeListener() on a model > object based on certain invocations. > > -Ray > >> 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 -~----------~----~----~----~------~----~------~--~---