Tuesday, January 29, 2013

Re: Problem with ListEditor when list items' Ids are composites (@EmbeddedId)

Thomas - that was it! I was (again) trying to be clever and encapsulating the composite id from my front end code, by delegating the biz object's setters into the id object on the server side. I suppose using a composite id in lieu of a Long or other primitive, you have to treat it very un-business-like in order for the RF to do its job correctly.  Thanks again for your insight, this was driving me up the wall!

-Blue

On Monday, January 28, 2013 4:52:10 PM UTC-5, Thomas Broyer wrote:
Oh, sorry, should have tilted before: your composite ID is a ValueProxy, so it MUST have getters and setters for all of its "parts" (and that means there must be setters on your ID too), or you cannot recreate an equivalent ID on the server-side, and such a proxy cannot round-trip server→client→server.
Not sure if it'd be enough to solve your issue, but it's a start.
As an alternative, convert the ID to/from a string in your Locator.

On Monday, January 28, 2013 8:44:45 PM UTC+1, bloo wrote:
Hi Thomas,

I combined the RequestFactoryServlet config into one instance, and branch on ("if non-static method and declared from a subclass of my base Entity class") to wrap the call itself in @Transactional (leaving "Service Pojo" Requests to determine which of their methods are @Transactional or not), but have the same issues I described above (at least now my server side GWT plumbing is a bit cleaner).

For the sake of debugging, I'll post the steps I take and resultant wire data below. If there's anything I can test and/or provide, let me know.

1. Load WineProxy and stage for edit via InstanceRequest.find(stableId()):

>>> {"F":"ws.web.shared.bindery.WineServiceRequestFactory","I":[{"O":"?","P":[{"S":"IjMi","T":"OPi7mudJuUS2QND9fE2xUf7Oo4I="}],"R":["wineType","estates.producer","mainEstate.producer","mainEstate.origin.appellation","mainEstate.origin.region","mainEstate.origin.subRegion","mainEstate.origin.originCountry","varietalComponents.id","varietalComponents.varietal"]}]}

<<< {"S":[true],"O":[{"T":"Rglf5pMW5kFN$TOzH6q0GhrHRys=","V":"MS4w","P":{"id":"637","name":"Côtes du Rhône"},"S":"IjYzNyI=","O":"UPDATE"},{"T":"oZUy$OYUkgKfvuqnqmCIhHeChmI=","V":"MS4w","P":{"id":"194","name":"Chardonnay","wineType":1,"profile":""},"S":"IjE5NCI=","O":"UPDATE"},{"T":"jFwa66QILJFT494o4Fl_HHh4RaI=","V":"MC4w","P":{"id":"13","name":"France"},"S":"IjEzIg==","O":"UPDATE"},{"T":"W8dRM5FtHdJIAt2i6mFy98KdIF8=","V":"MS4w","P":{"id":"138","name":"Rhône"},"S":"IjEzOCI=","O":"UPDATE"},{"T":"7k4WXcrjIt8yA19bZ4wZpkdvoRA=","V":"MC4w","P":{"varietal":{"T":"oZUy$OYUkgKfvuqnqmCIhHeChmI=","S":"IjE5NCI="},"id":{"T":"98umNTSsoLc6SjKgecg_UJ8QcgA=","R":"2","Y":2}},"S":"eyJPIjpbeyJUIjoiOTh1bU5UU3NvTGM2U2pLZ2VjZ19VSjhRY2dBPSIsIlAiOnt9LCJSIjoiMiIsIlkiOjF9XSwiSSI6W3siUCI6W3siVCI6Ijk4dW1OVFNzb0xjNlNqS2dlY2dfVUo4UWNnQT0iLCJSIjoiMiIsIlkiOjF9XX1dfQ==","O":"UPDATE"},{"T":"OPi7mudJuUS2QND9fE2xUf7Oo4I=","V":"My4w","P":{"id":"3","varietalComponents":[{"T":"7k4WXcrjIt8yA19bZ4wZpkdvoRA=","S":"eyJPIjpbeyJUIjoiOTh1bU5UU3NvTGM2U2pLZ2VjZ19VSjhRY2dBPSIsIlAiOnt9LCJSIjoiMiIsIlkiOjF9XSwiSSI6W3siUCI6W3siVCI6Ijk4dW1OVFNzb0xjNlNqS2dlY2dfVUo4UWNnQT0iLCJSIjoiMiIsIlkiOjF9XX1dfQ=="}],"estates":[{"T":"Vqxe_RlQJX28$GxeJByGamu4OTk=","S":"Ijg1MjYi"}],"vintage":"2009","wineType":0,"displayName":"2009 Gilles Ferran - France, Rhône, Côtes du Rhône","varietalComponentsShortName":"Chardonnay","mainEstate":{"T":"Vqxe_RlQJX28$GxeJByGamu4OTk=","S":"Ijg1MjYi"}},"S":"IjMi","O":"UPDATE"},{"T":"Vqxe_RlQJX28$GxeJByGamu4OTk=","V":"My4w","P":{"id":"8526","name":"Gilles Ferran","producer":{"T":"6ii4rVbu7YQPvm45Tik$ZR5YAw8=","S":"IjgyNzQi"},"origin":{"T":"H0c_n4HS3FqVwOgiGOZdHjNB4O4=","R":"2","Y":1}},"S":"Ijg1MjYi","O":"UPDATE"},{"T":"6ii4rVbu7YQPvm45Tik$ZR5YAw8=","V":"Mi4w","P":{"id":"8274","displayName":"Gilles Ferran"},"S":"IjgyNzQi","O":"UPDATE"},{"T":"98umNTSsoLc6SjKgecg_UJ8QcgA=","P":{},"R":"2","Y":2},{"T":"H0c_n4HS3FqVwOgiGOZdHjNB4O4=","P":{"region":{"T":"W8dRM5FtHdJIAt2i6mFy98KdIF8=","S":"IjEzOCI="},"originCountry":{"T":"jFwa66QILJFT494o4Fl_HHh4RaI=","S":"IjEzIg=="},"appellation":{"T":"Rglf5pMW5kFN$TOzH6q0GhrHRys=","S":"IjYzNyI="},"originDisplayName":"France - Rhône"},"R":"2","Y":1}],"I":[{"T":"OPi7mudJuUS2QND9fE2xUf7Oo4I=","S":"IjMi"}]}


2. Query "Selector" input for VarietalProxies and choose one (many were returned, only showing the one I selected and "hold" until save; the querying is done to a called a data service pojo that handles my "selector" queries)

>>> {"F":"ws.web.shared.bindery.WineServiceRequestFactory","I":[{"O":"df2QO3_6k4y6pWfJVgM4lxIy948=","P":["Pinot Gr",20]}]}

<<< {"S":[true],"O":[{"T":"oZUy$OYUkgKfvuqnqmCIhHeChmI=","V":"MS4w","P":{"id":"791","name":"Pinot Gris","wineType":1,"profile":""},"S":"Ijc5MSI=","O":"UPDATE"}],"I":[[{"T":"oZUy$OYUkgKfvuqnqmCIhHeChmI=","S":"Ijc5MSI="}]]}


3. On "save" user action
 3a. create new VarietalComponentProxy instance 
 3b. take the held VarietalProxy instance and set it into the newly created VCP
 3c. add that VCP to the "varietalComponents" ListEditor
 3d. call fire() on the RequestContext from InstanceRequest.approve().using(WineProxy):

>>> {"F":"ws.web.shared.bindery.WineInstanceRequestFactory","I":[{"O":"6KYMbi3ql_XFgB7Qhd9B3Jr2$Q4=","P":[{"S":"IjMi","T":"OPi7mudJuUS2QND9fE2xUf7Oo4I="}],"R":["estates","mainEstate.origin","approval.submittedBy","approval.approvedBy"]}],"O":[{"O":"UPDATE","S":"IjMi","T":"OPi7mudJuUS2QND9fE2xUf7Oo4I=","V":"My4w","P":{"varietalComponents":[{"S":"eyJPIjpbeyJUIjoiOTh1bU5UU3NvTGM2U2pLZ2VjZ19VSjhRY2dBPSIsIlAiOnt9LCJSIjoiMiIsIlkiOjF9XSwiSSI6W3siUCI6W3siVCI6Ijk4dW1OVFNzb0xjNlNqS2dlY2dfVUo4UWNnQT0iLCJSIjoiMiIsIlkiOjF9XX1dfQ==","T":"7k4WXcrjIt8yA19bZ4wZpkdvoRA="},{"R":"1","C":17,"T":"7k4WXcrjIt8yA19bZ4wZpkdvoRA="}]}},{"O":"UPDATE","S":"Ijg1MjYi","T":"Vqxe_RlQJX28$GxeJByGamu4OTk=","V":"My4w"},{"O":"PERSIST","R":"1","C":136,"T":"H0c_n4HS3FqVwOgiGOZdHjNB4O4=","P":{"originDisplayName":"France - Rhône","originCountry":{"S":"IjEzIg==","T":"jFwa66QILJFT494o4Fl_HHh4RaI="},"appellation":{"S":"IjYzNyI=","T":"Rglf5pMW5kFN$TOzH6q0GhrHRys="},"region":{"S":"IjEzOCI=","T":"W8dRM5FtHdJIAt2i6mFy98KdIF8="},"subregion":null}},{"O":"UPDATE","S":"IjEzIg==","T":"jFwa66QILJFT494o4Fl_HHh4RaI=","V":"MC4w"},{"O":"UPDATE","S":"IjYzNyI=","T":"Rglf5pMW5kFN$TOzH6q0GhrHRys=","V":"MS4w"},{"O":"UPDATE","S":"IjEzOCI=","T":"W8dRM5FtHdJIAt2i6mFy98KdIF8=","V":"MS4w"},{"O":"UPDATE","S":"IjgyNzQi","T":"6ii4rVbu7YQPvm45Tik$ZR5YAw8=","V":"Mi4w"},{"O":"UPDATE","S":"eyJPIjpbeyJUIjoiOTh1bU5UU3NvTGM2U2pLZ2VjZ19VSjhRY2dBPSIsIlAiOnt9LCJSIjoiMiIsIlkiOjF9XSwiSSI6W3siUCI6W3siVCI6Ijk4dW1OVFNzb0xjNlNqS2dlY2dfVUo4UWNnQT0iLCJSIjoiMiIsIlkiOjF9XX1dfQ==","T":"7k4WXcrjIt8yA19bZ4wZpkdvoRA=","V":"MC4w"},{"O":"PERSIST","R":"1","C":135,"T":"98umNTSsoLc6SjKgecg_UJ8QcgA="},{"O":"UPDATE","S":"IjE5NCI=","T":"oZUy$OYUkgKfvuqnqmCIhHeChmI=","V":"MS4w"},{"O":"PERSIST","R":"1","C":17,"T":"7k4WXcrjIt8yA19bZ4wZpkdvoRA=","P":{"id":{"R":"1","C":18,"T":"98umNTSsoLc6SjKgecg_UJ8QcgA="},"varietal":{"S":"Ijc5MSI=","T":"oZUy$OYUkgKfvuqnqmCIhHeChmI="},"wine":{"S":"IjMi","T":"OPi7mudJuUS2QND9fE2xUf7Oo4I="}}},{"O":"PERSIST","R":"1","C":18,"T":"98umNTSsoLc6SjKgecg_UJ8QcgA="},{"O":"UPDATE","S":"Ijc5MSI=","T":"oZUy$OYUkgKfvuqnqmCIhHeChmI=","V":"MS4w"}]}

<<< {"S":[true],"O":[{"T":"Rglf5pMW5kFN$TOzH6q0GhrHRys=","V":"MS4w","P":{"id":"637","name":"Côtes du Rhône"},"S":"IjYzNyI=","O":"UPDATE"},{"T":"H0c_n4HS3FqVwOgiGOZdHjNB4O4=","R":"1","C":136},{"T":"jFwa66QILJFT494o4Fl_HHh4RaI=","V":"MC4w","P":{"id":"13","name":"France"},"S":"IjEzIg==","O":"UPDATE"},{"T":"7k4WXcrjIt8yA19bZ4wZpkdvoRA=","S":"eyJPIjpbeyJUIjoiOTh1bU5UU3NvTGM2U2pLZ2VjZ19VSjhRY2dBPSIsIlAiOnt9LCJSIjoiMiIsIlkiOjF9XSwiSSI6W3siUCI6W3siVCI6Ijk4dW1OVFNzb0xjNlNqS2dlY2dfVUo4UWNnQT0iLCJSIjoiMiIsIlkiOjF9XX1dfQ=="},{"T":"ve$F9PnxOROKmY8WGxmd$WaMo8s=","V":"MC4w","P":{"id":"1","lastName":"SYSTEM","email":"sys...@myapp.com","submitter":true,"approver":true,"active":true,"firstName":"SYSTEM"},"S":"IjEi","O":"UPDATE"},{"T":"oZUy$OYUkgKfvuqnqmCIhHeChmI=","V":"MS4w","S":"Ijc5MSI=","O":"UPDATE"},{"T":"OPi7mudJuUS2QND9fE2xUf7Oo4I=","V":"My4w","P":{"id":"3","estates":[{"T":"Vqxe_RlQJX28$GxeJByGamu4OTk=","S":"Ijg1MjYi"}],"vintage":"2009","approval":{"T":"Evq5qwLVzHIwYkk_bot_q0in1CY=","R":"2","Y":1},"wineType":0,"displayName":"2009 Gilles Ferran - France, Rhône, Côtes du Rhône","varietalComponentsShortName":"Pinot Gris","mainEstate":{"T":"Vqxe_RlQJX28$GxeJByGamu4OTk=","S":"Ijg1MjYi"}},"S":"IjMi","O":"UPDATE"},{"T":"98umNTSsoLc6SjKgecg_UJ8QcgA=","R":"1","C":135},{"T":"H0c_n4HS3FqVwOgiGOZdHjNB4O4=","P":{"region":{"T":"W8dRM5FtHdJIAt2i6mFy98KdIF8=","S":"IjEzOCI="},"originCountry":{"T":"jFwa66QILJFT494o4Fl_HHh4RaI=","S":"IjEzIg=="},"appellation":{"T":"Rglf5pMW5kFN$TOzH6q0GhrHRys=","S":"IjYzNyI="},"originDisplayName":"France - Rhône"},"R":"2","Y":2},{"T":"Evq5qwLVzHIwYkk_bot_q0in1CY=","P":{"submittedOn":"1359322479397","approved":true,"approvedBy":{"T":"ve$F9PnxOROKmY8WGxmd$WaMo8s=","S":"IjEi"},"submittedBy":{"T":"ve$F9PnxOROKmY8WGxmd$WaMo8s=","S":"IjEi"},"approvedOn":"1359322479398"},"R":"2","Y":1},{"T":"7k4WXcrjIt8yA19bZ4wZpkdvoRA=","V":"MC4w","S":"eyJPIjpbeyJUIjoiOTh1bU5UU3NvTGM2U2pLZ2VjZ19VSjhRY2dBPSIsIlAiOnt9LCJSIjoiMiIsIlkiOjF9XSwiSSI6W3siUCI6W3siVCI6Ijk4dW1OVFNzb0xjNlNqS2dlY2dfVUo4UWNnQT0iLCJSIjoiMiIsIlkiOjF9XX1dfQ==","C":17,"O":"PERSIST"},{"T":"oZUy$OYUkgKfvuqnqmCIhHeChmI=","V":"MS4w","S":"IjE5NCI=","O":"UPDATE"},{"T":"98umNTSsoLc6SjKgecg_UJ8QcgA=","R":"1","C":18},{"T":"W8dRM5FtHdJIAt2i6mFy98KdIF8=","V":"MS4w","P":{"id":"138","name":"Rhône"},"S":"IjEzOCI=","O":"UPDATE"},{"T":"6ii4rVbu7YQPvm45Tik$ZR5YAw8=","V":"Mi4w","S":"IjgyNzQi","O":"UPDATE"},{"T":"Vqxe_RlQJX28$GxeJByGamu4OTk=","V":"My4w","P":{"id":"8526","name":"Gilles Ferran","origin":{"T":"H0c_n4HS3FqVwOgiGOZdHjNB4O4=","R":"2","Y":2}},"S":"Ijg1MjYi","O":"UPDATE"}],"I":[{"T":"OPi7mudJuUS2QND9fE2xUf7Oo4I=","S":"IjMi"}]}


4. Re-load WineProxy into editor: (the original VCP [Chardonnay] is gone, only the added one [Pinot Gris] remains.. had I added 2 VCPs in step 3, 2 would return here but they'd be duplicates of the last VCP added)

>>> {"F":"ws.web.shared.bindery.WineServiceRequestFactory","I":[{"O":"?","P":[{"S":"IjMi","T":"OPi7mudJuUS2QND9fE2xUf7Oo4I="}],"R":["wineType","estates.producer","mainEstate.producer","mainEstate.origin.appellation","mainEstate.origin.region","mainEstate.origin.subRegion","mainEstate.origin.originCountry","varietalComponents.id","varietalComponents.varietal"]}]}

<<< {"S":[true],"O":[{"T":"Rglf5pMW5kFN$TOzH6q0GhrHRys=","V":"MS4w","P":{"id":"637","name":"Côtes du Rhône"},"S":"IjYzNyI=","O":"UPDATE"},{"T":"jFwa66QILJFT494o4Fl_HHh4RaI=","V":"MC4w","P":{"id":"13","name":"France"},"S":"IjEzIg==","O":"UPDATE"},{"T":"W8dRM5FtHdJIAt2i6mFy98KdIF8=","V":"MS4w","P":{"id":"138","name":"Rhône"},"S":"IjEzOCI=","O":"UPDATE"},{"T":"7k4WXcrjIt8yA19bZ4wZpkdvoRA=","V":"MC4w","P":{"varietal":{"T":"oZUy$OYUkgKfvuqnqmCIhHeChmI=","S":"Ijc5MSI="},"id":{"T":"98umNTSsoLc6SjKgecg_UJ8QcgA=","R":"2","Y":2}},"S":"eyJPIjpbeyJUIjoiOTh1bU5UU3NvTGM2U2pLZ2VjZ19VSjhRY2dBPSIsIlAiOnt9LCJSIjoiMiIsIlkiOjF9XSwiSSI6W3siUCI6W3siVCI6Ijk4dW1OVFNzb0xjNlNqS2dlY2dfVUo4UWNnQT0iLCJSIjoiMiIsIlkiOjF9XX1dfQ==","O":"UPDATE"},{"T":"OPi7mudJuUS2QND9fE2xUf7Oo4I=","V":"My4w","P":{"id":"3","varietalComponents":[{"T":"7k4WXcrjIt8yA19bZ4wZpkdvoRA=","S":"eyJPIjpbeyJUIjoiOTh1bU5UU3NvTGM2U2pLZ2VjZ19VSjhRY2dBPSIsIlAiOnt9LCJSIjoiMiIsIlkiOjF9XSwiSSI6W3siUCI6W3siVCI6Ijk4dW1OVFNzb0xjNlNqS2dlY2dfVUo4UWNnQT0iLCJSIjoiMiIsIlkiOjF9XX1dfQ=="}],"estates":[{"T":"Vqxe_RlQJX28$GxeJByGamu4OTk=","S":"Ijg1MjYi"}],"vintage":"2009","wineType":0,"displayName":"2009 Gilles Ferran - France, Rhône, Côtes du Rhône","varietalComponentsShortName":"Pinot Gris","mainEstate":{"T":"Vqxe_RlQJX28$GxeJByGamu4OTk=","S":"Ijg1MjYi"}},"S":"IjMi","O":"UPDATE"},{"T":"Vqxe_RlQJX28$GxeJByGamu4OTk=","V":"My4w","P":{"id":"8526","name":"Gilles Ferran","producer":{"T":"6ii4rVbu7YQPvm45Tik$ZR5YAw8=","S":"IjgyNzQi"},"origin":{"T":"H0c_n4HS3FqVwOgiGOZdHjNB4O4=","R":"2","Y":1}},"S":"Ijg1MjYi","O":"UPDATE"},{"T":"6ii4rVbu7YQPvm45Tik$ZR5YAw8=","V":"Mi4w","P":{"id":"8274","displayName":"Gilles Ferran"},"S":"IjgyNzQi","O":"UPDATE"},{"T":"oZUy$OYUkgKfvuqnqmCIhHeChmI=","V":"MS4w","P":{"id":"791","name":"Pinot Gris","wineType":1,"profile":""},"S":"Ijc5MSI=","O":"UPDATE"},{"T":"98umNTSsoLc6SjKgecg_UJ8QcgA=","P":{},"R":"2","Y":2},{"T":"H0c_n4HS3FqVwOgiGOZdHjNB4O4=","P":{"region":{"T":"W8dRM5FtHdJIAt2i6mFy98KdIF8=","S":"IjEzOCI="},"originCountry":{"T":"jFwa66QILJFT494o4Fl_HHh4RaI=","S":"IjEzIg=="},"appellation":{"T":"Rglf5pMW5kFN$TOzH6q0GhrHRys=","S":"IjYzNyI="},"originDisplayName":"France - Rhône"},"R":"2","Y":1}],"I":[{"T":"OPi7mudJuUS2QND9fE2xUf7Oo4I=","S":"IjMi"}]}





On Monday, January 28, 2013 10:17:21 AM UTC-5, bloo wrote:
I like the idea of the ServiceLayerDecorator examining for non-static methods on @Entity objects - that's basically what I was trying to do with 2 separate RF's without the server side introspection. The last resort will be to redo all my InstanceRequest calls as Requests - the client-side refactoring is no big deal, but a boiler-plate CRUD-only (DAO-esque) service would be needed which kind of annoys me (architecturally).

Thanks again for your response. The shared static context between both RF's I was unaware of. That's what I get for trying to be too clever. Will report back in a few!

-Blue

On Monday, January 28, 2013 3:51:23 AM UTC-5, Thomas Broyer wrote:


On Sunday, January 27, 2013 8:05:00 PM UTC+1, bloo wrote:
I believe this may be similar to: http://code.google.com/p/google-web-toolkit/issues/detail?id=7827 but I can't be certain as I'm using slightly different components.

I have a WineProxy EntityProxy with a list of VarietalComponentProxy EntityProxies. The id of the VCP is a VarietalComponentIdProxy (which proxies a JPA @EmbeddedId instance), but that id's ValueProxy has no setters or getters (I set and get to the VCP itself client-side, and on the server-side set up the VCId accordingly).

When creating a new VCP foro the currently edited WineProxy, I call a service to query for a list VarietalProxy objects, select one and hold it, then before persisting the WineProxy, I 'set' the held VarietalProxy into a newly created VCP which I then add to the WineProxy's VCP list editor before calling a InstanceRequest.persist().using(WineProxy).

Several problems arise when I go to edit a WineProxy.
  1. First, if I have multiple VCs, the RF find() returns the same VC for the # of items it's supposed to be returning. This is odd.
  2. Second, if I save as-is, the VCP list is fine. But if I add or remove a VCP to/from the list, any existing VCPs get sent to the server as nulls, and if I filter them out to avoid NPEs, they're simply removed from that Wine relation.
I don't have a problem calling query services to give me EntityProxy objects to add to another object's ListEditor for any non-composite id based lists. This one is the only one that's giving me a bunch of issues, so in light of the issue I linked to above, I think I may be doing something fundamentally wrong.

I'm using Guice with Guice-Persist, GP's PersistFilter on every http request to enable Open-Session-In-View for the app, and JPA + Hibernate for data access.

I don't know if this is relevant, but since I'm querying for VarietalProxy's via a "service" Request and I'm editing and persisting my proxies via InstanceRequest "services" - each of which are backed by different servlets:

All of my InstanceRequest "services" are defined in one RequestFactory, backed by a subclass of RequestFactoryServlet (at "/instanceRequest") that uses a ServiceLayerDecorator that I've overridden invoke() with Guice-Persist's @Transactional so that all of my InstanceRequests are within a txn.

All of my Request "services" are defined in another RequestFactory backed by a separate RequestFactoryServlet (at "/gwtRequest") that uses my own ServiceLocator to find the Guice bound services, which may or may not have their service methods demarcated with @Transactional.

That might be the problem.

I can't see any reason you'd want to use 2 distinct RequestFactory interfaces and 2 distinct RequestFactoryServlet instances (particularly as RF uses shared static state, and doesn't preclude calling your InstanceRequest on /gwtRequest, or your other Requests on /instanceRequest.

Can't you setup your ServiceLayerDecorator to only use an explicit transaction on non-static methods invoked on, say, a JPA entity object? (one that you know have not been provided by Guice and therefore isn't subject to AOP interception). Or alternatively, though impacting all your client code as well, how about ditching InstanceRequest and moving everything to Request, with separate "service" objects on the server-side? (that can be provided by Guice and thus intercepted by Guice-Persist)

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

No comments:

Post a Comment