IMHO, The interesting case is not AOP of outgoing objects, but AOP of incoming objects (return values from RPC). This might even help some of the GWT/GAE/JDO issues, where you could AOP enhance an incoming model object to track dirty modification of fields. This is not unlike the JRE serialization mechanisms like readResolve() this allow replacement.
-Ray On Wed, Apr 22, 2009 at 7:19 PM, Arthur Kalmenson <[email protected]> wrote: > >> 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 <[email protected]> wrote: >> >> On Tue, Apr 21, 2009 at 7:11 PM, Arthur Kalmenson <[email protected]> >> 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 <[email protected]> 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 >>>> <[email protected]> wrote: >>>>> Sounds a good solution. >>>>> How would this solve the use case "data returned by RPC call" ? >>>>> >>>>> 2009/4/21 Ray Cromwell <[email protected]> >>>>>> >>>>>> 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 >>>>>> <[email protected]> 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 <[email protected]> >>>>>> >> >>>>>> >> On Tue, Apr 21, 2009 at 12:38 PM, nicolas de loof >>>>>> >> <[email protected]> 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 <[email protected]> >>>>>> >>>> >>>>>> >>>> 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 <[email protected]> >>>>>> >>>> wrote: >>>>>> >>>>> >>>>>> >>>>> >>>>>> >>>>> >>>>>> >>>>> On 20 avr, 08:43, nicolas de loof <[email protected]> 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 -~----------~----~----~----~------~----~------~--~---
