Sunday, January 20, 2013

Intercept GWT RPC Request and Response


Some times you want to do some generic things like setting some header or adding some log or may be even showing a progress bar while rpc call is in progress and hide it once you receive the response. I came across one of such requirement for showing progress bar while service call is in progress. Following is complete end to end solution I found after searching for some solutions. I got some help at following threads https://groups.google.com/forum/?fromgroups=#!msg/google-web-toolkit/VeiJUPBUsi4/Hq2VDMF9W1kJ and http://stackoverflow.com/questions/5309624/how-to-intercept-the-onsuccess-method-in-gwt

I created one complete end  to end working example from that help.

1:  public class LoaderRpcRequestBuilder extends RpcRequestBuilder {  
2:       private Loader     loader;  
3:       private class RequestCallbackWrapper implements RequestCallback {  
4:            private RequestCallback     callback;  
5:            RequestCallbackWrapper(RequestCallback aCallback) {  
6:                 this.callback = aCallback;  
7:            }  
8:            @Override  
9:            public void onResponseReceived(Request request, Response response) {  
10:                 loader.hide();  
11:                 callback.onResponseReceived(request, response);  
12:            }  
13:            @Override  
14:            public void onError(Request request, Throwable exception) {  
15:                 loader.hide();  
16:                 callback.onError(request, exception);  
17:            }  
18:       }  
19:       public LoaderRpcRequestBuilder(Loader loader) {  
20:            this.loader = loader;  
21:       }  
22:       public LoaderRpcRequestBuilder() {  
23:            this(new Loader());  
24:       }  
25:       @Override  
26:       protected RequestBuilder doCreate(String serviceEntryPoint) {  
27:            RequestBuilder rb = super.doCreate(serviceEntryPoint);  
28:            loader.show();  
29:            return rb;  
30:       }  
31:       @Override  
32:       protected void doFinish(RequestBuilder rb) {  
33:            super.doFinish(rb);  
34:            rb.setCallback(new RequestCallbackWrapper(rb.getCallback()));  
35:       }  
36:  }  

Here in above code we are creating our own custom RpcRequestBuilder by extending RpcRequestBuilder and by overriding its doCreate and doFinish() method. We are intercepting the calls that will be made. In doCreate() we are showing loader and then inside doFinish we are setting one general purpose RequestCallback wrapper which we have created to intercept response received. Where we are hiding our loader inside onResponseReceived() and onError.

Note: be sure to call super.doFinish(rb); other wise you will get SecurityException. There are some tokens which is set by doFinish method to avoid XSRF attack. (Though they say one should not just rely on this mechanism to avoid XSRF attack.)

Now that we have created custom RpcRequestBuilder we need to understand how to use it.

1:  ServiceAsync serivce = GWT.create(Service.class);  
2:  ServiceDefTarget target = (ServiceDefTarget) serivce;  
3:  target.setRpcRequestBuilder(new LoaderRpcRequestBuilder());  

When we make rpc call we get async instance before making any service call we need to set our own custom RpcRequestBuilder.





Wednesday, January 2, 2013

set Servlet RequestScope Guice dependencies


Set some commonly used dependencies which are dependent on some parameter of HTTP Request.

The most common use case is to add logged in user context in request scope from session id inside filter. To do that you need to bind such a dependency inside your ServletModule like following.

 bind(User.class).annotatedWith(Names.named("user")).to(User.class).in(ServletScopes.REQUEST);  

You are just binding a given User.class with @Named("user") annotation inside RequestScope. Now you have to take care of setting required value when request is made. Which can be achieved by using Servlet filter as follows.

1:  public class AuthCheckFilter implements Filter {  
2:       @Override  
3:       public void destroy() {  
4:       }  
5:       @Override  
6:       public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {  
7:            HttpServletRequest httpRequest = (HttpServletRequest) request;  
8:            .....< Code to retrieve session from request either through query param,   
9:            cookie or HTTP header and validate the session.   
10:            session is not valid throw error as per application specific requirement>.....  
11:            User us = ...<code to retrieve user from session>  
12:            httpRequest.setAttribute(Key.get(User.class, Names.named("user")).toString(), us);  
13:            chain.doFilter(httpRequest, response);  
14:       }  
15:       @Override  
16:       public void init(FilterConfig arg0) throws ServletException {  
17:       }  
18:  }  

Note: We are setting User object for @Named("user") dependency at line no 12. When you set the user value inside httpRequest object as attribute.

Now that we have set the value. We can access it or inject it

1:  @Singleton  
2:  public class SomeDao {  
3:    @Inject  
4:    @Named("user")  
5:    Provider<User> user;  
6:    public void someMethod() {  
7:      User user = user.get();  
8:    }  
9:  }  

As it is request scoped dependency you need to access / inject it through Provider.

http://code.google.com/p/google-guice/wiki/ServletModule refer Using RequestScope section.