svetlo / gwt-platform

Automatically exported from code.google.com/p/gwt-platform
0 stars 0 forks source link

Support non GWT-RPC backend in the dispatch module #179

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
The dispatch module is currently tightly coupled with GWT's native RPC. It 
would be nice to support alternate mechanisms.

This is discussed here:
http://groups.google.com/group/gwt-platform/browse_thread/thread/1cf3efb5780e5b8
0

Original issue reported on code.google.com by philippe.beaudoin on 27 Aug 2010 at 8:44

GoogleCodeExporter commented 9 years ago
Bumping to 0.5, preparing for release.

Original comment by philippe.beaudoin on 2 Sep 2010 at 10:37

GoogleCodeExporter commented 9 years ago
I made a working example (It's based on basicsample you can just import in 
Eclipse and "run as webapp").

It's a simple example application, with : 
* Server side : A standard (non GWT) servlet which allow to create a retrieve 
"items" 
* Client side : 
    * An implementation of DispatchAsync usable on the client side.
    * The code to use this implementation with a presenter to create / retrieve items on the UI

Should I push it on https://samples.gwt-platform.googlecode.com/hg/ ? 

I attach it on the ticket anyway. 

And I am starting to write the corresponding documentation. I'll put it in the 
wiki in "Samples/Dispatch Without GWT-RPC".

Original comment by denis.la...@gmail.com on 4 Sep 2010 at 5:36

Attachments:

GoogleCodeExporter commented 9 years ago
Sure, go ahead !

Ask for a CR too !

Cheers and thanks !

Original comment by goudreau...@gmail.com on 4 Sep 2010 at 6:38

GoogleCodeExporter commented 9 years ago
I asked for a CR : http://codereview.appspot.com/2171043/

In the meantime I made some changes in the sample : 
* use Json with GWT Overlays, as it more relevant than manual String parsing in 
this kind of scenario
* updated to use gwtp-0.4.jar

Original comment by denis.la...@gmail.com on 12 Sep 2010 at 11:34

Attachments:

GoogleCodeExporter commented 9 years ago
Updated sample to use Piriti to read data.

Next steps:
* Denis, would you please update app engine backend for create item, so it is 
REST compliant? It should work like this
request: POST /items 
request body: {"name": "asdf"} 
response body: none 

* After this, I would update the sample to use Piriti also to send data to 
back-end using a model.

* I'll look then at possibility of getting rid of all Action, Result and 
Handler classes per request, and have some generic ones for all requests, 
accepting and returning Models. 

As mentioned on the group, it would be really great to have this imported in 
code repository.

Thanks!

Original comment by marius.a...@gmail.com on 13 Sep 2010 at 9:24

Attachments:

GoogleCodeExporter commented 9 years ago
Hi guys, 

I've been working on a solution for caching, and as a side effect I think my 
solution will be useful when using a non GWT-RPC backend in the dispatch module.

My idea is to have client-side action handlers.  These are called when before 
the gwt-rpc call, and provide a chance to perform some processing before the 
call is made, perform some processing after the call returns before being 
returned to the callee, or completely skip making the gwt-rpc call all together 
(I think this will be useful to you).

I'd appreciate you input.  We are discussing some of the ideas in this wave: 
https://wave.google.com/wave/waveref/googlewave.com/w+rY0H7VOmA 

Marius & Denis, I've added you to the wave already.

I've got a proof-of-concept quality code review up at 
http://codereview.appspot.com/2104056/  (still needs comments, etc).

Here is an example of what application code might look like.
http://pastebin.com/FFiMvcQm

Brendan

Original comment by brendanp...@gmail.com on 13 Sep 2010 at 11:46

GoogleCodeExporter commented 9 years ago
a CR has been requested for the modifications of the sample (not yet in trunk 
and still in CR) : http://codereview.appspot.com/2202041/ : 
* use gwtp-0.4 instead of gwtp-0.3
* use JSON to communicate with the server
* use piriti as a parsing lib (for JSON/XML)

Original comment by denis.la...@gmail.com on 14 Sep 2010 at 9:50

GoogleCodeExporter commented 9 years ago
Code review looks good to me, no comments. After having this in trunk we can 
move forward with trying to reduce amount of code to be written for each 
request.

It would also be nice to update the back-end to be REST compliant.

Original comment by marius.a...@gmail.com on 15 Sep 2010 at 7:47

GoogleCodeExporter commented 9 years ago

Original comment by philippe.beaudoin on 22 Sep 2010 at 1:35

GoogleCodeExporter commented 9 years ago
I'm not sure this example is still relevant.

Because with Brendan work, there's a new system to pre/post process Actions.
It may be the recommanded way to use dispatch with non GWT-RPC backends in GWTP.

@brendanpdoherty : What do you think ? Should I update the sample to use the 
new system ?
The idea was to have a complete working eclipse example, so new users could 
quick start a new project with non GWT-RPC backend.

Cheers, 

Denis

Original comment by denis.la...@gmail.com on 25 Sep 2010 at 11:53

GoogleCodeExporter commented 9 years ago
Denis, I think it would be an excellent idea.

Original comment by philippe.beaudoin on 25 Sep 2010 at 3:13

GoogleCodeExporter commented 9 years ago
Great idea.   The changes are now in the main trunk.

Here is a sample of a client-action handler that does geocoding using google 
maps backend (no gwt-rpc).
http://pastebin.com/idaT5gws

The sample could also demonstrate combining the client action handler and the 
associated presenter in the same split point.  I'm just committing some code to 
make that easier.

Original comment by bren...@doherty.net.nz on 26 Sep 2010 at 10:51

GoogleCodeExporter commented 9 years ago
i run the demo dispatch-without-gwtrpc.tar.gz 8.7 MB . 
1. there are many error 10:10:48.510 [ERROR] [gwtpsample] Errors in 
'jar:file:/D:/work/springsource/sts-2.3.3.M1/plugins/com.google.gwt.eclipse.sdkb
undle.2.1.0_2.1.0.m1-201005191217/gwt-2.1.0.M1/gwt-bikeshed.jar!/com/google/gwt/
valuestore/shared/impl/RecordSchema.java' 

2. the demo url doesnt use /create/pojo/id  /delete/pojo/id2.   can provide 
such demo ?

Original comment by second.c...@gmail.com on 12 Oct 2010 at 2:33

GoogleCodeExporter commented 9 years ago
@Denis: Did you get to update the sample to use the new ClientActionHandlers?
I have been playing around to do it myself, but somehow I have a hard time to 
find a good solution (especially avoiding a lot of code on the individual 
ClientHandlers).
Maybe if you have something, you could share it.

Original comment by uemit.se...@gmail.com on 19 Oct 2010 at 1:24

GoogleCodeExporter commented 9 years ago

I would like to keep it simple to implement a new Handler : 
* Map the Action to a GWT RequestBuilder
* Extract the ActionResult from the response

I began updating the sample to use the new ClientActionHandlers. Not finished 
yet.
I'll keep you posted

Original comment by denis.la...@gmail.com on 19 Oct 2010 at 4:08

GoogleCodeExporter commented 9 years ago
@Denis: Thanks for the update. What I have been doing is to create an abstract 
class which extends AbstractActionHandler and implements the 
RequestBuilderActionHandler interface of your initial sanmple 
(getRequestBuilder, extractResult)
and for the actual ClientActionHandler I just extend this abstract class and 
implement the interface (extractResult and getRequestBuilder). It works so far 
but I am not sure if that's the best approach. 

I can post the code if you like

Original comment by uemit.se...@gmail.com on 20 Oct 2010 at 7:32

GoogleCodeExporter commented 9 years ago
@uemit.seren Your approch seems interesting, yes please post the code (you can 
attach a file to the issue).

Original comment by denis.la...@gmail.com on 21 Oct 2010 at 8:55

GoogleCodeExporter commented 9 years ago
@Denis: I have posted the 3 important classes/interfaces at pastebin: 
http://pastebin.com/FReameEm

The AbstractRequestBuilderClientActionHandler takes care of the common 
RequestBuilder code part. Just FYI. I  implemented also the HasEventBus 
interface in order to support firing a LoadingIndicator Event but if you don't 
need a LoadingIndicator you can leave EventBus/HasEventBus  and the 
loadingIndicator stuff out.

The RequestBuilderActionHandler interface is actually your interface. I could 
also create these two functions as an abstract function on the 
AbstractRequestBuilderClientActionHandler class instead but I am not sure which 
approach is better.

Finally the GetAllItemsActionHandler is an actual implementation of the 
ClientActionHandler which uses pirtri to pass back the ActionResult (I have 
left out the Action and ActionResult classes -> same as in your previous 
example)

Hope this helps. I am not sure if that's the best approach but it works so far. 
Btw I use python and JSON as backend.

Original comment by uemit.se...@gmail.com on 21 Oct 2010 at 9:48

GoogleCodeExporter commented 9 years ago
@uemit.seren
Seems great !
Maybee we could split AbstractRequestBuilderClientActionHandler in two classes, 
one without the loadingIndicator, and another one extending the previous and 
adding the loadingIndicator behavior.
I am integrating this class with the example, so we'll have (finally !) a 
complete working example with non GWT backend "the right way".

Cheers, 

Denis

Original comment by denis.la...@gmail.com on 21 Oct 2010 at 12:29

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
@Denis: Sounds really good. 
I agree on the LoadingIndicator thing. The 
AbstractRequestBuilderClientActionHandler class should only deal with the 
RequestBuilder stuff. People can then extend it do either implement 
LoadingIndicator or Cache or whatever they want. Actually I am not really sure 
if my specific LoadingIndicator implementation is the best approach (in my case 
I have multiple requests at the same time and I want to show the indicator as 
long as the last request hasn't been completed -> therefore I use these static 
class members)

I have a suggestion concerning the interface. We could get rid of the 
RequestBuilderActionHandler interface by moving the two functions 
(extractResult and getRequestBuilder) into the 
AbstractRequestBuilderClientActionHandler class. Because I don't think any 
other class will implement this interface. -> We would end up with only one 
abstract class which extends the AbstractClientActionHandler: 
http://pastebin.com/e6VcAhH2

What do you think? 

Original comment by uemit.se...@gmail.com on 21 Oct 2010 at 12:53

GoogleCodeExporter commented 9 years ago
You guys might be interested with:
http://codereview.appspot.com/2657041/

Take a look at patch set two and especially strategies.

Original comment by goudreau...@gmail.com on 21 Oct 2010 at 7:25

GoogleCodeExporter commented 9 years ago
@Christian: Thanks for the info. I looked into the patch set two and as far as 
I understood it, the functionality for extracting the Result and the getting 
the RequestBuilder information (URL and Method) were moved into a separate 
interface and Action extending class respectively. In this case do I really 
need an actual implementation for each ClientActionHandler or couldn't i just 
use the one  AbstractClientActionHandler (which deals with the RequestBuilder 
part) and just implement different Actions and Results? I am asking because in 
the code review there is an GetBlogPostsClientActionHandler? Isn't that a bit 
redundant? So in the end I would just register the AbstractClientActionHandler 
in the MyClientActionHandlerRegistry. Is that possible or am I missing 
something here?

Original comment by uemit.se...@gmail.com on 22 Oct 2010 at 11:10

GoogleCodeExporter commented 9 years ago
I think so, I'll have to see how things gonna work with gin since Action will 
not be strongly defined one by one, but it's clearly a goal in the end.

I'll do some rework, I had some good dream yesterday night about how to 
simplify things a little.

I'll keep you posted ! :D But I clearly thing that in the end, it'll be just 
what you guys need :D

Original comment by goudreau...@gmail.com on 22 Oct 2010 at 12:26

GoogleCodeExporter commented 9 years ago
@Christian: Great to hear that.  Looking forward to whatever you guys come up 
with ;-)

Original comment by uemit.se...@gmail.com on 22 Oct 2010 at 12:41

GoogleCodeExporter commented 9 years ago
Hi, 

Sorry to say that but ... I have a strange feeling while implementing this 
solution :)

We have a mechanism to enhance the behavior of the DispatchAsync: 
ClientActionHandler. 
This is a great solution to add cross-cutting dispatch concerns like caching, 
logging, security, ...

But using it (and only it) to implement RPC with non GWT backends feels weird 
to me: 
We "short-cut" regular Dispatch calls, never call it, and do the non-GWT-RPC 
call in there.

The ClientActionHandler is a form of AOP for DispatchAsync.
And what we are about to do could be compared to: 
* We want to change completely the implementation of a method
* So we add pre-processing where we do the actual job, and skip the original 
method entirely.
=> It would make more sense to just change the implementation of the method :)

In conclusion I think we should keep the Dispatch with non GWT RPC example as 
it was in his last form: An alternative implementation of DispatchAsync using 
GWT RequestBuilder.
And add ClientActionHandler if needed, that is: If we need to add behavior to 
RPC calls (caching, logging, ...).

Also, with this solution, adding a ClientActionHandler to a project (eg: adding 
cache) would be exactly the same for a GWT-RPC or non-GWT-RPC DispatchAsync 
implementation.

Of course I realize that I could have completely missed the point.
In that case please enlight me :)

@brendan
What do you think ? 

Cheers, 

Denis

Original comment by denis.la...@gmail.com on 22 Oct 2010 at 1:01

GoogleCodeExporter commented 9 years ago
@Denis:
About your concerns, here's why I think ClientActionHandler is the way.

First, this solution could end up calling the RPC server if nothings is found 
or if an error occurs, without having to change anything to your code but the 
clientActionHandler. (Ok small advantage if you're not using RPC at all)

Second, you can chain various client action handler, in what I've done so far, 
I'm calling Cache first, then requestBuilder.

I do agree that:
1. We could make a new "dispatch" implementation, that was my first though and 
is already there and probably we'll have no other choice to do the same thing 
for RequestFactory. The only thing missing is that I would really prefer that 
switching dispatch implementation change nothing... IE, when we do 
dispatcher.execute, it's the same for every implementation. Anyway, 
ClientActionHandler with RequestBuilder has it's use, but it's thin.

Original comment by goudreau...@gmail.com on 22 Oct 2010 at 1:15

GoogleCodeExporter commented 9 years ago
So be it ! ;)

I still think it would have been cleaner to redefine DispatchAsync.
But anyway it's almost exactly the same for the implementers of Handlers.
And of course for the presenters it won't change a thing.

Handler implementation : 
* Just extends AbstractRequestBuilderClientActionHandler
* implements the 2 abstract methods : 
    * extractResult
    * getRequestBuilder
* Register the handler with GIN

That's it.

@uemit.seren: As you suggested: I merged 
AbstractRequestBuilderClientActionHandler with RequestBuilderActionHandler.

Here's the code review: http://codereview.appspot.com/2693041

And I attached the working example: dispatch-without-gwtrpc-20101024-19h15.tgz

Cheers, 

Denis

Original comment by denis.la...@gmail.com on 23 Oct 2010 at 5:18

Attachments:

GoogleCodeExporter commented 9 years ago
Hi denis. In Attached example JSON format is incorrect. 
I fix it.

Original comment by antonev...@gmail.com on 6 Nov 2010 at 9:12

Attachments:

GoogleCodeExporter commented 9 years ago
Is there any news on that issue? Right now I am using the latest approach 
(example code denis posted) and it works fine but I am curious if there is any 
new recommended approach from official side. Christian said that he had some 
some ideas. I am asking because I am thinking about implementing caching and 
wanted to make sure that the recommended way of dealing with non rpc-backends 
hasn't changed in that regards

thanks in advance

Original comment by uemit.se...@gmail.com on 22 Nov 2010 at 6:34

GoogleCodeExporter commented 9 years ago
Well I kinda started to work on something else in the meanwhile and didn't had 
time to look at it.

But latest idea was to create an injectable interface to take care of the 
XML/JSON/whatever. I was also proposing to extends Action and add URL 
informations inside dispatch actions.

That was it ! Oh well, there was something else, we were talking about using it 
as dispatch instead of a client action handler.

Original comment by goudreau...@gmail.com on 22 Nov 2010 at 6:49

GoogleCodeExporter commented 9 years ago
Thanks for the update Christian. One last question, are there any plans to 
implement/include these ideas in the gwtplatform in the near future and the 
codereview you posted some time ago (which also includes caching strategy) is 
still the way to go as regards caching?

Original comment by uemit.se...@gmail.com on 22 Nov 2010 at 7:03

GoogleCodeExporter commented 9 years ago
Well, we do encourage you to use the CachingClientActionHandler right inside 
Gwt-Platform.

I was trying to chain everything within my code review, but it introduce too 
much boiler plate. As for if we're planning to introduce this soon, it only 
depends on the time we have, but it's planned. If no one work on that before 
me, I think I'll finally have some time in december to finish/polish what's 
already done and also experiment a little with request factory.

Original comment by goudreau...@gmail.com on 22 Nov 2010 at 7:11

GoogleCodeExporter commented 9 years ago
Great to hear, that these ideas are comming soon (maybe as a christmas present 
;-)) 
And thanks again for the time and effort you put into this great project. 

Original comment by uemit.se...@gmail.com on 22 Nov 2010 at 8:56

GoogleCodeExporter commented 9 years ago
hello, i bookmarked this feature. it's very interesting. may i know is there 
any plan to support 'gwt-address-path' that look like restful-path in the 
future ? example  http://gwttestapp/create/new_item     
http://gwttestapp/retrieve/item/34   or will remain using existing page !main , 
!nextPage in the future? 

Original comment by second.c...@gmail.com on 28 Nov 2010 at 5:53

GoogleCodeExporter commented 9 years ago
You can already change the path as you like. Override getServiceName in your 
actions.

Original comment by goudreau...@gmail.com on 28 Nov 2010 at 1:45

GoogleCodeExporter commented 9 years ago
1.totoe.jar can be removed since it's not used in this project
2. how to use clientSideCaching for this example? modify  extractResult method 
for the handler?

Original comment by second.c...@gmail.com on 30 Nov 2010 at 2:26

GoogleCodeExporter commented 9 years ago
may i know when using non-rpc, json to communicate, will  @GenDispatch(isSecure 
= true)  work to protect from xsrf attack?

Original comment by second.c...@gmail.com on 30 Nov 2010 at 3:17

GoogleCodeExporter commented 9 years ago
Since that check is done server side with RPC request, you'll have to make sure 
to implement something similar yourself. As for us, we will make sure to enable 
client side compatibility in case you want to implement that solution.

Original comment by goudreau...@gmail.com on 30 Nov 2010 at 3:29

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
does that mean on the client side, i can remain using 
bindConstant().annotatedWith(SecurityCookie.class).to(Constants.securityCookieNa
me);
and @GenDispatch(isSecure = true)

on server side:
and only need to modify public class ItemsManagerServlet extends HttpServlet { ?

can briefly explain how to modify server side?

Original comment by second.c...@gmail.com on 1 Dec 2010 at 1:11

GoogleCodeExporter commented 9 years ago
Server side must initialize a cookie with the name Constants.securityCookieName 
and must have a generated id hard to find.

Original comment by goudreau...@gmail.com on 1 Dec 2010 at 3:53

GoogleCodeExporter commented 9 years ago
XSRF explained in one paragraph:

The malicious party inserts an image in a forum post. The image is actually a 
link to an action on your webapp. This is a sensitive action that should only 
be performed by a logged-in user. The user seeing the image is currently logged 
into your webapp. The action doesn't require any parameter and works with a GET 
request.

Without XSRF protection, the action will be performed as soon as the user sees 
the image. (Because the browser sends the session cookie.)

GWTP's XSRF protection explained in one paragraph.

Every action in GWTP expects at least one input parameter: the security cookie. 
This cookie is sent in the body of a POST request. The cookie is stored in the 
user's browser and, on the server, in the user's session. XSRF-protected 
actions cannot be executed unless the security cookie in the request matches 
the one in the session. (This all happen behind your back when using the 
standard GWTP dispatcher. You have to implement it yourself if you're using 
your custom dispatcher.)

Why does this protect against XSRF attacks?

The malicious image can't read the security cookie on the browser, so it has no 
way of sending in as part of the request. Ok, suppose instead of a malicious 
image that it was a complete piece of javascript trying to access the security 
cookie and forge a POST request. This does not work either because the browser 
doesn't allow javascript code to read a cookie from a different domain.

Original comment by philippe.beaudoin on 1 Dec 2010 at 5:20

GoogleCodeExporter commented 9 years ago
you mentioned, for xsrf protection, securitycookies must send with "post" , but 
in this case, user doing "GET" (NON RPC) , is securitycookies  need to put as 
parameter to before doing 'get' to server as well?   like this 
http://server.com?securitycookies=testonly&getAllListing=abc ?

Original comment by second.c...@gmail.com on 2 Dec 2010 at 1:22

GoogleCodeExporter commented 9 years ago
Yes, with GET it's even more important because a simple image could be used as 
a XSRF attack.

That being said, if you trust your users to use modern browser and no (old) 
flash you could use a simpler technique: just add a custom header to contain 
some (public) string and make sure the header is defined server-side. I just 
learned about this technique today:
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/f0f74b073
4f04a1c/c069af38d05855e0?lnk=gst&q=XSRF#c069af38d05855e0

Original comment by philippe.beaudoin on 2 Dec 2010 at 1:32

GoogleCodeExporter commented 9 years ago
Maybe it helps to see a more complete example. I'm currently implementing a 
time recording application (http://code.google.com/p/tire-d8/) which uses GWTP 
on the client side and Restlet (http://www.restlet.org) for the communication. 
I'm using client action handlers which also include protection against XSRF. 
The whole thing is implemented as follows:

1. After successful login the servlet filter 
http://code.google.com/p/taoki/source/browse/trunk/src/main/java/name/pehl/taoki
/security/SecurityCookieFilter.java generates a random security token which is 
sent to the client on each request.

2. The base class of my custom action handlers 
http://code.google.com/p/tire-d8/source/browse/trunk/app/src/main/java/name/pehl
/tire/client/dispatch/AbstractRestletClientActionHandler.java reads the cookie 
and adds a custom header with the security token.

3. The resources on the server side read the cookie and header and are only 
processed in case they match. Otherwise they return with 403. The security 
check is done using Taoki (http://code.google.com/p/taoki/) a small library I 
wrote. Taoki mainly contains glue code for Restlet, Guice and Google App 
Engine. Besides there are a few classes which take care of the security checks. 
The implementations used in TiRe are 
http://code.google.com/p/taoki/source/browse/trunk/src/main/java/name/pehl/taoki
/security/CookieSecurityCheck.java and 
http://code.google.com/p/taoki/source/browse/trunk/src/main/java/name/pehl/taoki
/security/HeaderSecurityTokenReader.java  

There's not much documentation yet, but feel free to take a look into the 
source code and let me know if this is somewhat useful.

- Harald

Original comment by harald.pehl on 2 Dec 2010 at 12:56

GoogleCodeExporter commented 9 years ago
1. is the securitytoken generated only "once" after user success login and sent 
to client side. In other words, all client requests will using this same 
"token" ?

2. what is the website is a public-page, where there is no required to login to 
retrieve information.   when should server generate the token (as cookies) and 
send to client in question 1 ?

Original comment by second.c...@gmail.com on 5 Dec 2010 at 7:30

GoogleCodeExporter commented 9 years ago
1) There is one token by session.

2) I don't think you need to care for XSRF attacks if there is no
authentication/identity provided. Anybody could call your RPC from
anywhere in that case, no need to setup an attack.

  Philippe

Original comment by philippe.beaudoin on 5 Dec 2010 at 7:35

GoogleCodeExporter commented 9 years ago
Bumping to 0.6, preparing release 0.5.

Original comment by philippe.beaudoin on 25 Jan 2011 at 6:33

GoogleCodeExporter commented 9 years ago
Bumping to 0.7, preparing release 0.6.

Original comment by philippe.beaudoin on 6 Jun 2011 at 8:17