Friday, December 31, 2010

Re: Best way to integrate GWT with existing Spring services?

Hi

I've very successfully used a scheme for making a HandlerAdaptor for a GWT RemoteServiceServlet.

I based my code on:

http://blog.digitalascent.com/2007/11/gwt-rpc-with-spring-2x_12.html

(Chris Lee)

but I found that Chris's original code had a problem with 2.+ RemoteServiceServlets in 3 ways:

1. it only supported 'legacy' serialization.
2. it didn't provide a ServletContext so error messages generated NPEs
3. I didn't like his copy/paste approach

 so I modified his GwtRpcEndPointHandlerAdapter as below. You could inject a WebApplicationContext instead of an App.Context and then the cast. Also, possibly the servlet name should be defined differently.


package <your.package.name>

import java.util.Enumeration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * Spring HandlerAdapter to dispatch GWT-RPC requests. Relies on handlers
 * registered by GwtAnnotationHandlerMapper<br>
 * <p>Re-written by me to build a cache of configured {@code RemoteServiceServlet}s, one
 * for each {@code Handler} class. The {@code RemoteServiceServlet} is now a composition rather
 * than an aggregation.</p>
 * <p>Each instance of the Remote
 *
 *
 *
 * @author Chris Lee
 * @author Alan Chaney
 *
 */
public class GwtRpcEndPointHandlerAdapter implements HandlerAdapter {

  
   
    private Map<Class<?>, RemoteServiceServlet> servletMap;
    private ServletContext servletContext;
   
    @Autowired(required=true)
    protected ApplicationContext appContext;
   
    public GwtRpcEndPointHandlerAdapter() {
        this.servletMap = new ConcurrentHashMap<Class<?>, RemoteServiceServlet>();
    }

    public long getLastModified(HttpServletRequest request, Object handler) {
        return -1;
    }
    // use with 'init-method' or appropriate life-cycle annotation
    public void init() {
        getServletContext();
       
    }

    /**
     * A local class which implements the servlet configuration.
     * @author Alan Chaney
     *
     */
    public class ServletConfigInst implements ServletConfig {

        @Override
        public String getInitParameter(String arg0) {
            // No parameters
            return null;
        }

        @Override
        public Enumeration getInitParameterNames() {
            // No parameters
            return null;
        }

        @Override
        public ServletContext getServletContext() {
            return GwtRpcEndPointHandlerAdapter.this.getServletContext();
        }

        @Override
        public String getServletName() {
            return this.getClass().getSimpleName();
        }
       
    }
   
   
    /**
     * Finds the WebApplicationContext from the Autowired application context and returns the
     * {@code ServletContext}
     *
     * @return Servlet context from WebApplicationContext.
     */
    public ServletContext getServletContext() {
        if (servletContext == null) {
            WebApplicationContext wac = (WebApplicationContext) appContext;
            servletContext = wac.getServletContext();
            if (servletContext == null) {
                logger.warn("'servletContext' was null");
            }
        }
        return servletContext;
    }

    public ModelAndView handle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
       
        RemoteServiceServlet servlet = servletMap.get(handler.getClass());
        if (servlet == null){
            servlet = prepareServlet(handler);
        }
        servlet.doPost(request, response);
        return null;
    }


    protected RemoteServiceServlet prepareServlet(Object handler) throws ServletException {
        RemoteServiceServlet rss = new RemoteServiceServlet(handler);
        ServletConfig sc = new ServletConfigInst();
        rss.init(sc);
        this.servletMap.put(handler.getClass(), rss);
        return rss;
    }


    @Override
    public boolean supports(Object handler) {
        return handler instanceof RemoteService
                && handler.getClass().isAnnotationPresent(GwtRpcEndPoint.class);
    }

}






On 12/31/2010 6:11 AM, 华佗转世 wrote:
Is anyone know, how integrate GWT with Spring MVC (controller)? 

2010/12/31 Paul G. <palo.gressa@gmail.com>
Hi Daniel,

you are right, this question has been asked so many times. We're using
GWT-RPC because when we stared our project then GWT 1.6 was out and
actual. I don't know much about RequestFactory. But I think there is
still one same approach. So there is one big question for you. How
good is your knowledge about servlets and spring. If you don't know
much about these things, try to learn something first. Because my only
advice is: GWT-RPC is just another servlet.

If your application architecture is based on traditional j2e tiers
(presentation, business, integration) then switching between flex and
gwt is about to implement a new gwt tier and you can use still same
business tier.

GWT-RPC is just servlet, which takes input string, parses it, creates
objects based on policy file with respect to servlet and then calls
proper method.

Look at how GWT-Dispatch works: there is only one rpc method -
dispatch; where input is generic Action; return object is generic
Result.So there is one handler method and you are just calling
dispatch method with input as actions[something like a box with
properties]. Based on type of action, proper hadnler will be called.
If you are good with spring, make some automatic handler registrations
based on annotations or interface scanning of classpaths.

Daniel and all of you who are reading this post, please, if your
experiences with gwt, spring are not very good, try to dig into these
frameworks and try to learn how they works first.

Pavol

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




--
━  ・・・・  ・━  ━・  ━・━  ・・・
--------
Be the change you want to see in the world!
--------
Mars Hsu -- 华佗转世
Skype: marsxu1984

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


--  Alan Chaney CTO and Founder, Mechnicality, Inc. www.mechnicality.com

No comments:

Post a Comment