GWT and Spring integration

317 views
Skip to first unread message

marcelpanse

unread,
May 18, 2006, 6:21:19 AM5/18/06
to Google Web Toolkit
How to integrate GWT into my Spring application.

Can i remote RPC calls through proxied spring beans?
Is it possible to mix my current spring app controllers with GWT
Widgets?

It is not really clear to me if i can use my current WEB-INF/web.xml
structure loading my servlets combining with the GWT architecture?

gr,
Marcel

christoph...@gmail.com

unread,
May 18, 2006, 9:58:12 AM5/18/06
to Google Web Toolkit
You could probably do the same thing that you have to do to integrate
Spring and DWR. You'll have to have a dispatcher equivalent to the
DWRServletDispatcher.

marcelpanse

unread,
May 18, 2006, 10:58:04 AM5/18/06
to Google Web Toolkit
I found something,

you can start your gwt servlet in the springserver.. ie:

<bean id="gwtController"
class="org.springframework.web.servlet.mvc.ServletWrappingController">
<property name="servletClass">
<value>com.google.gwt.dev.shell.GWTShellServlet</value>
</property>
</bean>

instead of starting it in web.xml

Curt

unread,
May 21, 2006, 9:18:09 PM5/21/06
to Google Web Toolkit
I think GWTShellServlet is only for the development environment, and it
isn't intended for deployment. I might be wrong, but I don't think you
want to go with this option.

jack.tang

unread,
May 21, 2006, 10:03:48 PM5/21/06
to Google Web Toolkit
Hi Guys

Did you integrate spring with gwt with success?
my idea is quite simple, write one servlet wrapper of
RemoteServiceServlet and make a bridge to spring bean container. GWT
client invokes the servlet (ServiceEntryPoint in gwt term) using RPC.
So i think we can manager these services by spring.

Curt

unread,
May 21, 2006, 11:33:38 PM5/21/06
to Google Web Toolkit
Great work by all of the developers who contributed to this interesting
and innovative product! I'm looking forward to getting an opportunity
to apply it to a project.

I wouldn't go with the wrapper approach for RemoteServiceServlet, as
you'll see that there's probably a more extensible way to implement
this solution.

I have a suggestion about improving the RPC server's ability to
integrate with Spring Framework. GWT would need no dependencies on
Spring, but the change would let a Spring support class (or any other
IoC container) inject a reference to the object representing the
service implementation. Before I go forth and implement my own POC, I
wanted to get some feedback from others.

Currently, the concrete subclass overriding the RemoteServiceServlet
must contain the concrete service implementation. While not
necessarily a problem, this inheritance hierarchy causes two
limitations:

* Developers cannot reuse existing web service implementations if the
implementations inherit from another type of base class, and
* Developers cannot apply transaction control to individual service
methods in an aspect-oriented fashion (provided by Spring)

>From looking at the code, it appears that a few simple changes would
provide the option that would let the RemoteServiceServlet delegate
service implementation to a separate POJO service class.

This solution would require addition of a "service" property on
RemoteServiceServlet as a reference to an optional delegate object. On
RemoteServiceServlet invocation, if the property is null, then the
class would continue to behave as it currently does (using the
servlet's concrete class as the service implementation). If the
property is not null, then the RemoteServiceServlet would interrogate
and invoke methods on the referenced object.

With this hook, Spring (or another container/developer) can "inject"
the service into the servlet. (marcelpanse: I'm using a variation of
your suggestion. Good observation about the ServletWrappingController,
by the way.)

<bean id="myServiceViaGWT"

class="org.springframework.web.servlet.mvc.ServletWrappingController">
<property name="servletClass">

<value>com.google.gwt.user.server.RemoteServiceServlet</value>
</property>
<property name="service" ref="myService"/>
</bean>

This simple change buys us is the ability to have declarative
transaction control on a method-by-method basis, along with any other
AOP goodies Spring provides. It lets us reuse existing services,
published through GWT.

With that said, what does everyone else think?

Thanks,

Curt

Don't forget to rate! :-)

jack.tang

unread,
May 22, 2006, 1:05:45 AM5/22/06
to Google Web Toolkit
Hi Curt,

I bet it not so easy. Your solution seems ok the application is
deployed.
But another question how can we start hosted browser along with spring
application together for development?

/Jack

marcelpanse

unread,
May 22, 2006, 2:42:53 AM5/22/06
to Google Web Toolkit
Yeah i fixed it using a servletWrappingController.. The problem with
this approach is you can't declare your service bean as a 'spring'
bean. You can only set a class in the servletWrappingController and
that will instantiate a new object from that class.. You cant inject
any other spring beans into your service..
My solution is that is created a new class
ServletBeanWrappingController. With i can give a servletInstance
instead of a servletClass.

Now i can create a service bean in my xml.. Inject some managers/dao
other stuff into it and use the bean in the servletWrappingController!

I already submitted an improvement in spring's jira about this issue.

The hosted browser should still work as normal, now using the
springbeans.. (just create a servlet the normal way with spring)

jack.tang

unread,
May 22, 2006, 2:49:58 AM5/22/06
to Google Web Toolkit
Hey, marcelpanse. Could you pls post me the jira id or the url? Thanks
a lot.

marcelpanse

unread,
May 22, 2006, 3:57:43 AM5/22/06
to Google Web Toolkit

Mike Stephen

unread,
May 22, 2006, 6:59:30 AM5/22/06
to Google Web Toolkit
marcelpanse wrote:
> here it is:
> http://opensource.atlassian.com/projects/spring/browse/SPR-2034

Hi Marcel,

Can you define servlet instances in Spring? What would the
applicationContext look like?

Another approach I thought may work is to use the following code in
your servlet:

WebApplicationContext appContext =
WebApplicationContextUtils.getApplicationContext(this.getServletContext());
UserService userService = (UserService)
appContext.getBean("userService");
... some code which uses UserService

Its far from ideal, as you have to lookup the beans rather than have
them injected, but it should work.

It would be great to have a Spring class that could automatically
expose your service beans, much like the HessianServiceExporter, or the
HttpInvokerServiceExporter...

Regards,

Mike.

marcelpanse

unread,
May 22, 2006, 8:51:19 AM5/22/06
to Google Web Toolkit
Should be something like this:


<bean id="gwtController"


class="org.springframework.web.servlet.mvc.ServletWrappingController">
<property name="servletClass">

<value>com.google.gwt.dev.shell.GWTShellServlet</value>
</property>
</bean>

<bean id="UserService"
class="web.service.ServletBeanWrappingController">
<property name="beanName">
<value>userService</value>
</property>
<property name="servletClass">
<value>web.service.UserServiceImpl</value>
</property>
<property name="servletInstance">
<ref bean="userService" />
</property>
</bean>

<bean id="userService" class="web.service.UserServiceImpl">
<property name="productManager">
<ref bean="productManager" />
</property>
</bean>


map gwt in SimpleUrlHandlerMapping like:
<prop key="/**/*">gwtController</prop>

But not that the web.service.ServletBeanWrappingController does not
exists in spring. The ServletWrappingController DOES exists but it
doesnt implement the setInstance method .. What i did is copyed the
servletWrappingController and added a setInstance method and also added
this line in afterPropertiesSet method just before the init();

if (servletInstance == null)
servletInstance = (Servlet) servletClass.newInstance();

aos

unread,
Jun 2, 2006, 12:58:27 AM6/2/06
to Google Web Toolkit
Thanks guys.
1.I fully appreciate your idea of using ServletBeanWrappingController.
Implementation wise though I would like to suggest instead of replacing
Spring WrappingController with the custom one, subclass it and screen
out the private attribute servletInstance of the original class by
defining another attibute that holds the instance of the servlet and
overriding three methods delegating processing to the local instance if
present or superclass one otherwise:

handleRequestInternal() {
if (instanceServlet != null)
instanceServlet.service(request, response); // uses
injected property
else
super.handleRequestInternal(request, response); // uses
superclass property
}
afterPropertiesSet() ;
destroy()

Now you can inject the property as you would normally do. I beleive
this is a cleaner implementation.

2. To generalize the solution further actual service code could be
implemented in separate service beans (say, implementing some
interface). The GWT RPC processing servlet (derived from
RemoteServiceServlet class) can be injected with these service beans.
It serves client requests for services delegating processing to the
appropriate service bean and calling the specified method on it (using
reflection). Now implement your services and inject them into the
processing servlet. From the client side it will look like this:

invokeService(String serviceName, String[] params);

3. I've tried linking the GWT front end with Spring's MVC and this is
strightforward.

Regards, Alex

jevons...@gmail.com

unread,
Jun 13, 2006, 11:44:37 PM6/13/06
to Google Web Toolkit
create a new class:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

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

public class GwtServiceExporter implements Controller{
private RemoteServiceServlet service;

public RemoteServiceServlet getService() {
return service;
}

public void setService(RemoteServiceServlet service) {
this.service = service;
}

public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
service.doPost(request, response);
return null;
}

}

and in web.xml:
<servlet>
<servlet-name>service</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>service</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

then in spring(service-servlet.xml):
<beans>

<bean name="/login.do"
class="server.spring.GwtServiceExporter">
<property name="service" ref="LoginService" />
</bean>

<bean name="/register.do"
class="server.spring.GwtServiceExporter">
<property name="service" ref="RegisterService" />
</bean>
<bean name="LoginService" class="server.LoginServiceImpl"></bean>
<bean name="RegisterService"
class="server.register.RegisterServiceImpl"></bean>

</beans>

Eric

unread,
Jun 21, 2006, 9:27:16 AM6/21/06
to Google Web Toolkit
I want to manage my remote service implementations using Spring (need
to use Spring dependency injection to initialize references to other
Spring-managed objects), but I'm not all that enthused about using the
Spring web framework. We tend to stick to the Spring basics (beans,
aop).

So, using the ideas here, I wrote a very simple dispatcher that seems
to achieve the same effect as the Spring DispatcherServlet:

public class ServiceDispatcherServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}

protected void doPost(HttpServletRequest req, HttpServletResponse
resp)
throws ServletException, IOException {
// we use a custom way to get the ApplicationContext, instead of
assuming WebApplicationContext
ApplicationContext context =
ContextLoader.getApplicationContext(getServletContext());

// treat the Request URI as a bean name, and dispatch the request to
that RemoteServiceServlet
RemoteServiceServlet servlet =
(RemoteServiceServlet)context.getBean(req.getRequestURI());
if (servlet != null) {
servlet.doPost(req, resp);
}
}
}

In the web.xml, I added a definition:

<servlet>
<servlet-name>serviceDispatcher</servlet-name>
<servlet-class>com.everstream.server.ServiceDispatcherServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>serviceDispatcher</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>

Then in my Spring configuration, I defined my services. For example:

<bean name="/service/userlist"
class="com.blah.blah.blah.server.UserListServiceImpl">
<property name="userService"><ref bean="userService"/></property>
</bean>


Did I miss anything here?

There is one interesting thing.... using this approach, it appears
unnecessary to define my remote services using the <servlet> tag in the
module xml. In fact, this strategy depends on Spring to do the remote
service servlet instantiation. Is this consistent with others'
experience... that in hosted mode, you can use the web.xml OR the
module xml to define the servlet entry points?

Reply all
Reply to author
Forward
0 new messages