Maybe the simpler answer is to have a read resolve / write object equivalent.
I personally think coupling these value objects all the way from your database tier to the browser smells. The detached object problem seems like a symptom of the smell. On 23/04/2009, at 12:22 PM, Ray Cromwell <[email protected]> wrote: > > 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 -~----------~----~----~----~------~----~------~--~---
