Giving GWT a Spring in its Step
August 24, 2008
Some might claim that I’m rehashing a topic that has already been solved however I’m compelled to write this article as I personally struggled to connect all the disparate dots in order to make Google Web Toolkit (GWT) integrate with the Spring Framework. This is intended to be the article that I wished I’d stumbled upon in the first 10 minutes of looking for a solution to the problem. Before we start I’d also like to acknowledge that I’ve borrowed heavily from the concepts that people like George Georgovassilis pioneered. There’s nothing really new or groundbreaking here, I’ve simply combined all the knowledge that I’ve gained from all over the place into one convenient guide.
Update: Since publishing this article I’ve been contacted by Richard Bondi with regard to some great work that he’s also done on the matter of which I wish to also acknowledge his fantastic work. If you want to know more on this subject then I heartily recommend you check out his article on how to Integrate Spring with GWT and once you’ve done that, stubbing in hosted mode. Thanks again Richard.
Why would anyone want to integrate Spring and GWT?
If you’re familar with GWT (and I’m assuming you are) you may have marvelled, as I did, with how seamless and uncomplicated client-server interaction is. You are also probably aware that GWT RPC services are not web services. In fact they’re just plain old servlets that are endowed with an ability to serialize and deserialize information across the wire using a rather compact encoding developed by Google.
The RemoteServiceServlet class is great insofar as it handles all the grunt work of the RPC side of things whilst letting you get down to the business of writing your business logic for your services. The fact that you have to extend RemoteServiceServlet raises a few gnarly questions however:
1. What happens if I’ve already got my business logic implemented as an existing Java class with it’s own inheritance heirarchy?
2. What if you want to reuse that same class to implement a SOAP web service or any other RESTful interface for that matter?
3. What if I want to use the service class internally and don’t need all the RPC stuff?
4. What if something better than GWT comes out and I just want to replace the presentation layer technology?
Ouch! Suddenly extending RemoteServiceServlet starts to look a bit painful and far less useful than it did before. Now we could either try to imitate the ostrich and pretend that this isn’t an issue, or we could address the problem head on. We’re going to take the latter option.
Enter Spring
One answer to the above questions is to use a technique called Dependency Injection (DI). The Spring Framework happens to come with quite a good IoC container implementation and has become an industry standard. Without getting into the details about what DI is and how it works, Spring was designed with the intent of making your code as loosely coupled to its dependencies as possible and promoting POJO based development for enterprise applications.
So what does this look like in practice? Well currently out RPC model looks like this:
Ideally we want to look more like this:
Not too different really. With the exception of two new classes and two new interfaces you could be forgiven for thinking that I’d hardly done a thing, not to mention that three of them are Spring MVC classes! Well that’s actually the truth of it, I’ve done bugger all. It’s also worth noting that all the work is on the server-side with nothing new for the client.
Going back to our sample code, essentially all we need to do now is wire up our DispatcherServlet (a front-controller) and point it to our new GwtRpcController class for all RPC requests. We’ll also need to break the inheritance chain on the YourServiceImpl (a.k.a. QuoteServiceImpl) class to prove a point.
Getting down to business
In order to illustrate the point, I’m going to walk you through an adaptation of a random quote program from another GWT tutorial originally found on netbeans.org. I’ve adapted the original example to Eclipse as it’s my IDE of choice and I’m using Tomcat 6 as my test server.
For this tutorial you’ll require the following
- Java 5 or greater
- Spring Framework 2.5.x with Spring MVC
- Google Web Toolkit 1.5.x (RC1 or RC2 is fine)
- Eclipse 3.2 (J2EE distribution) or greater
- Tomcat, WebSphere, WebLogic, JBoss or whatever. As long as it has a servlet container that implements the 2.4 servlet spec or greater and that runs on the Java 5 runtime at the very least.
If you’re impatient like me you might also want access to the project source code which can be found here. Please note that you’ll have to download the dependencies separately as I don’t want to inadvertently infringe on any copyright restrictions.
Okay so maybe I lied a little beforehand, there’s a bit more that we have to do in the way of re-jigging our project structure to make it all hang together and work. Anyway, time to cut some code!
Creating the project
Open the terminal/command line and go to the folder where you’ve unzipped the GWT SDK. And run the following command to create your eclipse project:
./projectCreator -ant gwt-wisdom -eclipse gwt-wisdom -out /home/dave/eclipse/workspace/gwt-wisdom
Note: replace the -out parameter argument with your own project destination. Also I’m using Linux, Windows users should just get rid of the preceeding “./” and change all forward slashes to back slashes and the commands will work just fine.
Now run this command to create your GWT project structure:
./applicationCreator -eclipse gwt-wisdom -out ~/eclipse/workspace/gwt-wisdom org.example.gwtwisdom.client.GwtWisdom
Again replace the -out parameter with the same location you used for the command above
Next import the new application into Eclipse using the File > Import menu option. Choose the Existing Projects option from under the General category and then browse to where ever you output the project files to.At this stage you should be able to hit run and test that the application skeleton is working.
Additional project setup
So that your application will compile once we start adding Spring into the mix add the the Spring framework and Spring Web MVC jars (spring.jar, spring-webmvc.jar) to your applications build path.
Now we need somewhere to put all our configuration files and deployment time dependencies. Create the following directory structure at the base of your project WebContent/WEB-INF/lib. This is almost identical to the Eclipse WTP project structure and will become useful later when we automate the project build with an Ant script.
In the WebContent/WEB-INF folder create a web.xml file an copy and paste the text below into it:
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>GWT Wisdom</display-name> <!-- Initialise the Spring MVC DispatcherServlet --> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Map the DispatcherServlet to only intercept RPC requests --> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>*.rpc</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>GwtWisdom.html</welcome-file> </welcome-file-list> </web-app>
Now I’m aware that the integrated Tomcat instance that comes with GWT has a web.xml file but we can’t actually modify the Tomcat web.xml file as it is dynamically regenerated by the compiler every time we start hosted mode. Hence why we’re creating our own.
If you were paying attention in the last step you would have seen that we defined a servlet in the web.xml file. This is the Spring Web MVC DispatcherServlet which will intercept our RPC requests and route them to the correct service. Each DispatcherServlet instance requires a bean definition file of the same with a “-servlet.xml” suffix. So in the same folder create a file called spring-servlet.xml and copy and paste the following into it:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <!-- The application context definition for the DispatcherServlet --> <!-- Maps the request through to a concrete controller instance --> <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <value> /**/quote.rpc=quoteController </value> </property> </bean> <!-- GwtRpcController wraps our service in order to decode the incoming --> <!-- request then delegates processing of the call to the POJO service --> <!-- and then encodes the return value forwarding the response. --> <bean id="quoteController" class="org.example.gwtwisdom.server.GwtRpcController"> <property name="remoteService"> <bean class="org.example.gwtwisdom.server.QuoteServiceImpl" /> </property> </bean> </beans>
This will be used to configure the DispatcherServlet to route calls to our services. It does so via the SimpleUrlHandlerMapper which uses regular expression syntax to match the request url to a controller bean ID.
Now you’ll need to add the following jars to the WebContent\WEB-INF\lib folder: commons-logging.jar, gwt-servlet.jar, gwt-user.jar, spring.jar, spring-webmvc.jar. This is necessary for when it comes time to deploy the app.
Creating the RPC quote service
Next we’re going to create our RPC service. Start by creating a subpackage of the *.client package and call it “service”.
Create a new interface called QuoteService and make it look like the code below:
package org.example.gwtwisdom.client.service; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; @RemoteServiceRelativePath("quote.rpc") public interface QuoteService extends RemoteService { public String getQuote(); }
Those already familiar with GWT will know that the next step is to create an async service interface to pair with the QuoteService interface we just created. Create a new interface again in the *.client.service package called QuoteServiceAsync and modify it so it looks like the following:
package org.example.gwtwisdom.client.service; import com.google.gwt.user.client.rpc.AsyncCallback; public interface QuoteServiceAsync { public void getQuote(AsyncCallback<String> callback); }
Enough of interfaces. Now it’s time to code up the actual service itself. Create a new package under the org.example.gwtwisdom package called server. Once that’s done create a new class and call it QuoteServiceImpl.
package org.example.gwtwisdom.server; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.example.gwtwisdom.client.service.QuoteService; public class QuoteServiceImpl implements QuoteService { private Random randomizer = new Random(); private static List<String> quotes = new ArrayList<String>(); static { quotes.add("No great thing is created suddenly - Epictetus"); quotes.add("Well done is better than well said - Ben Franklin"); quotes.add("No wind favors he who has no destined port - Montaigne"); quotes.add("Sometimes even to live is an act of courage - Seneca"); quotes.add("Know thyself - Socrates"); } public String getQuote() { return quotes.get(randomizer.nextInt(quotes.size())); } }
Now some of you might be saying to yourselves “hey wait a minute, don’t we have to extend RemoteServiceServlet?”. Well read on. I’m about to show you a magic trick straight out of the Gang of Four (GoF) playbook.
To cap it all off before we continue, we should probably update our module configuration file to include our new service mapping. Copy and paste the following into your GwtWisdom.gwt.xml file:
<!-- RPC service servlet declarations --> <servlet path="/quote.rpc" class="org.example.gwtwisdom.server.QuoteServiceImpl"/>
All rise for the GwtRpcController
Here’s the fun part, now we’re going to create the GwtRpcController. In the org.example.gwtwisdom.server package create a class called, you guessed it GwtRpcController. Then copy and paste the following code into it:
package org.example.gwtwisdom.server; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.context.ServletContextAware; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.SerializationException; import com.google.gwt.user.server.rpc.RPC; import com.google.gwt.user.server.rpc.RPCRequest; import com.google.gwt.user.server.rpc.RemoteServiceServlet; public class GwtRpcController extends RemoteServiceServlet implements Controller, ServletContextAware { private ServletContext servletContext; private RemoteService remoteService; private Class remoteServiceClass; public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { super.doPost(request, response); return null; } @Override public String processCall(String payload) throws SerializationException { try { RPCRequest rpcRequest = RPC.decodeRequest(payload, this.remoteServiceClass); // delegate work to the spring injected service return RPC.invokeAndEncodeResponse(this.remoteService, rpcRequest .getMethod(), rpcRequest.getParameters()); } catch (IncompatibleRemoteServiceException ex) { getServletContext() .log( "An IncompatibleRemoteServiceException was thrown while processing this call.", ex); return RPC.encodeResponseForFailure(null, ex); } } @Override public ServletContext getServletContext() { return servletContext; } public void setServletContext(ServletContext servletContext) { this.servletContext = servletContext; } public void setRemoteService(RemoteService remoteService) { this.remoteService = remoteService; this.remoteServiceClass = this.remoteService.getClass(); } }
This class works on the principle that it is both a RemoteServiceServlet AND a Spring MVC Controller (don’t you just love polymorphism?) meaning that it can not only be used as a target by the DispatcherServlet for handling incoming RPC requests, but also to decode the incoming RPC requests. Remember I previously mentioned the Gang of Four? Well you’re looking right at the strategy pattern baby. Pretty cool huh?
Upon receiving a request we delegate handling of this to the Controller’s superclass (the RemoteServiceServlet) to handle the unmarshalling of the request. We then intercept the processing of the message by overriding RemoteServiceServlet.processCall method and delegate the processing to the RemoteService POJO.
Where did we get this magical POJO from you ask? Well we injected it into the class via the setRemoteService setter back in the spring-servlet.xml bean definition file earlier.
Okay one last thing before we continue on to preparing the app for deployment. We need to tie all of this together by doing some work to display our quotes in the GWT entry point class and fixing up some of the HTML.
In the GwtWisdom.html file copy and paste the following in below the body tag:
<p>
This is an AJAX application that retrieves a random quote from
the Random Quote service every three seconds. The data is retrieved
and the quote updated without refreshing the page!
</p>
Once you’ve done that, replace the method body of the GwtWisdom classes onModuleLoad method with the following:
public void onModuleLoad() { final Label quoteText = new Label(); Timer timer = new Timer() { public void run() { // create an async callback to handle the result: AsyncCallback<String> callback = new AsyncCallback<String>() { public void onFailure(Throwable t) { // display error text if we can't get the quote: quoteText.setText("Failed to get a quote"); } public void onSuccess(String result) { // display the retrieved quote in the label: quoteText.setText(result); } }; QuoteServiceAsync service = (QuoteServiceAsync) GWT .create(QuoteService.class); service.getQuote(callback); } }; timer.scheduleRepeating(3000); RootPanel.get().add(quoteText); }
Note: since this is client-side code be careful that you use the google timer implementation as opposed to the stock Java one otherwise it won’t work like you expect.
That should take care of the display side of things. If you want you can also jazz it up a bit by putting some styles in the GwtWisdom.css file.
Ditching the GWT tomcat server
Remember that earlier on we created our own custom web.xml to initialise the Spring context via a DispatcherServler? Well because of this we can no longer rely upon the integrated tomcat server that comes with GWT to run our app. Fortunately the hosted mode browser comes with a -noserver switch which allows us to configure it to use the server of our choice during development.
There’s a bit of a knack to getting this running all running nice and seamlessly within Eclipse. First we’re going to have to compile the application then package it up and deploy it to the server just this once just so the server has knowledge of your app. Don’t worry, once it’s running in hosted mode the app will use your workspace code, but trust me we need to do this just once.
I’m actually going to use Ant to build and package the app. Conveniently, this is going to work out great in future when I need to bundle the app up into a war file and deploy it elsewhere.
First create a file called build.xml in the root of your project and copy and paste the script below into the build file.
<?xml version="1.0" encoding="utf-8"?> <project name="gwt-wisdom" default="compile" basedir="."> <description> Build file. This is used to package up your project as a war, if you want to distribute/deploy it. This isn't needed for normal operation. </description> <property file="build.number"/> <!-- GWT properties - change these to suit your distribution (i.e. windows, mac or linux) --> <property name="platform" value="linux"/> <property name="gwt.home" value="/home/dave/eclipse/lib/gwt/linux/1.5.1"/> <!-- Build properties - shouldn't need changing --> <property name="name" value="GwtWisdom"/> <property name="module" value="org.example.gwtwisdom.GwtWisdom"/> <property name="src.dir" value="src"/> <property name="web.dir" value="WebContent"/> <property name="lib.dir" value="${web.dir}/WEB-INF/lib"/> <property name="bin.dir" value="${web.dir}/WEB-INF/classes"/> <property name="test.dir" value="test"/> <property name="out.dir" value="build"/> <property name="dist.dir" value="dist"/> <!-- set classpath --> <path id="project.class.path"> <pathelement path="${java.class.path}/"/> <pathelement path="${lib.dir}/gwt-user.jar"/> <!-- Additional dependencies go here --> <pathelement path="${lib.dir}/spring.jar"/> <pathelement path="${lib.dir}/spring-webmvc.jar"/> <pathelement path="${lib.dir}/commons-logging.jar"/> </path> <target name="clean"> <delete file="${dist.dir}/${name}.war"/> <!-- Delete the bin directory tree --> <delete> <fileset dir="${bin.dir}" includes="**/*.class"/> </delete> </target> <target name="compile" description="Compile both client & server code"> <!-- cross-compile client-side java classes --> <mkdir dir="${out.dir}"/> <java classname="com.google.gwt.dev.GWTCompiler" dir="${basedir}" fork="true"> <jvmarg value="-Xmx256M"/> <classpath> <pathelement path="${java.class.path}"/> <pathelement location="${src.dir}"/> <pathelement location="${bin.dir}"/> <pathelement path="${gwt.home}/gwt-user.jar"/> <pathelement path="${gwt.home}/gwt-dev-${platform}.jar"/> </classpath> <arg line="-out ${basedir}/${out.dir}"/> <arg value="%*"/> <arg value="${module}"/> </java> <copy todir="${web.dir}"> <fileset dir="${out.dir}/${module}"/> </copy> <!-- compile server-side java classes --> <mkdir dir="${web.dir}/WEB-INF/classes"/> <javac srcdir="${src.dir}:${test.dir}" destdir="${bin.dir}" includes="**" debug="on" debuglevel="lines,vars,source" source="1.5"> <classpath refid="project.class.path"/> </javac> </target> <target name="package" depends="compile" description="Package up the project as a war"> <mkdir dir="${dist.dir}"/> <war destfile="${dist.dir}/${name}.war" webxml="${web.dir}/WEB-INF/web.xml"> <fileset dir="${out.dir}/${module}"> <include name="**/*.*"/> </fileset> <fileset dir="${web.dir}"> <include name="**/*.*"/> <exclude name="WEB-INF/web.xml"/> </fileset> </war> </target> <target name="all" depends="package"/> </project>
Run the build script using the package target (Alt+Shift+X then Q). Alternatively if you’re using Ant from the command line then running “ant package” from the project directory should do the trick. This should compile and package the app automatically for you into a war file.
If the build fails for any reason you might have to edit some of the property elements listed at the top of the file depending on your platform (windows, mac or linux) and where you unzipped your GWT libs. Just change these as appropriate and everything should work fine.
From here you can just go ahead and fire up Tomcat and deploy the war file onto the app server either via the admin console or the autodeploy directory. At this point you should be able to test your application by opening your web browser and navigating to http://localhost:8080/GwtWisdom/GwtWisdom.html. If this works then we’re all good to proceed to the next stage.
Getting hosted mode to run with -noserver
Okay we’re getting close now. This step isn’t essential really, what I’ve shown you so far should be more than enough to demonstrate the application in action. If however you want to continue debugging and testing your app in hosted mode for development like I do then read on.
We’re going to need to edit the launch configuration in order to run the app in hosted mode using our own Tomcat instance as opposed to the integrated Tomcat server. You can do this one of two ways, either edit the GwtWisdom.launch file directly or you edit them via the Eclipse run configuration manager. We’re going to do it via the run configuration manager.
You can open the manager by right-clicking on the project Run As > Run Configurations. Once there, you should see in the left-hand tree view under Java Applications the GwtWisdom launch configuration. Select it and then click the Arguments tab over on the right hand side. Check that the program arguments resemble those below. Your configuration may differ slightly as far as the port is concerned but should read something like:
-out www GwtWisdom/GwtWisdom.html
-noserver
-port 8080
This configuration tells the hosted mode browser to use an external server on the given port and where it should find your applications home page on the server.
You might also have to add the contents of your WebContent/WEB-INF/lib folder to the classpath tab in order to get it working but try it first by clicking apply and then run.
Sweet sweet success!
All that’s left to do is run the project. If you’ve configured it correctly it should fire up the app in all its hosted glory. Your services are now free from the tyranny of RemoteServiceServlet!
Now if only we could figure out a way to remove the dependency on the QuoteService interface from the service. Then it really would be a bona-fide POJO…another day, another challenge.
August 25, 2008 at 10:51 pm
[…] Kuhn has put together a comprehensive guide to piecing together GWT and Spring, a nice recipe for the Java heads among […]
August 25, 2008 at 11:02 pm
[…] Kuhn has put together a comprehensive guide to piecing together GWT and Spring, a nice recipe for the Java heads among […]
August 26, 2008 at 2:36 am
Very nice article! It’s about time there were a comprehensive how-to on this subject.
August 26, 2008 at 3:47 am
[…] Kuhn has put together a comprehensive guide to piecing together GWT and Spring, a nice recipe for the Java heads among […]
August 26, 2008 at 6:04 am
[…] Kuhn has put together a comprehensive guide to piecing together GWT and Spring, a nice recipe for the Java heads among […]
August 26, 2008 at 8:43 am
Wow! This has really helped me. Thanks so much for putting this up for us to use! Well DONE!
August 26, 2008 at 12:04 pm
Similar solutions were previously published on the google incubator site:
Integrate Spring with GWT.
And once you’ve done that, stubbing in hosted mode.
/r:b:
August 26, 2008 at 12:24 pm
Thanks for the feedback Richard.
Yes I was aware of all of this and I never attempted to take credit for the work done by others. As I originally stated; I was compelled to write this how-to as I hadn’t yet found anything that tied all the parts together in one convenient guide. Furthermore many of the examples are done in rather abstract form. It’s my hope that by putting it in the context of a full fledged project, that you can download with source code and all, would foster greater understanding.
Incidently your original post will not work without modification on GWT 1.5. You need to implement the ServletContextAware interface from the Spring libraries and override the getServletContext() method in order for it to work.
August 26, 2008 at 2:17 pm
[…] that convenient either if you’re an Eclipse user. If you’ve read my previous post on Integrating Spring with GWT you would have seen that we still had to manually package and deploy the application to the app […]
August 27, 2008 at 1:24 am
This approach can become ugly when you have many different GWT-RPC interfaces in a multi-module scenario, because all of the implementing classes will have to be injected inside the “GwtRpcController” which then needs logic to find out which service to dispatch, too.
Or am i mistaken?
August 27, 2008 at 6:03 am
[…] Giving GWT a Spring in its Step « Technophiliac (tags: spring java integration gwt) […]
August 27, 2008 at 6:04 am
[…] Giving GWT a Spring in its Step « Technophiliac (tags: spring java integration gwt) […]
August 27, 2008 at 7:13 am
Hi Sakuraba,
Thanks for the question. I’m not sure I completely understand but here goes.
The GwtRpcController doesn’t require any modification whatsoever. All the mapping/routing RPC calls to the various services you might have is performed by the DispatcherServlet and the SimpleUrlMapperHandler class. These rules are completely confined to the bean context file which you define for the DispatcherServlet. No modification of the code is necessary.
The GwtRpcController has a 1 to 1 relationship with the RemoteService. If you wish to implement another service. Then you must define another instance of the GwtRpcController via the bean context.
If you’re worried about the bean context getting a bit heavy, you can always define other application contexts for your application’s layers to break it up a bit.
Does that answer the question?
Dave
August 29, 2008 at 9:04 am
Hello Dave
Nice article – just like you, I’d also wish this were my first 10 minutes with Spring and GWT 😉
The approach you take is the most intuitive many people (including aforementioned GWT incubator) take, but it may at times be impractical. The whole point is to public business objects (POJOs) to the RPC protocol. The fact that services must now bind to a 3rd party API by implementing the RemoteService interface breaks sepparation of concerns, even if it is just an interface and is a side effect (a sinful path annotations walk on also btw).
There are actually two ways around this:
1. Create a copy interface that declares all interesting methods of your POJO service and then create a class that extends the service and implements the interface. This new class can then be exported to RPC
2. In the SL we implemented a dynamic binding: you provide a POJO class, you create an interface and the SL will bind them in runtime together for you
August 31, 2008 at 9:29 pm
Excellent post, yes, I wish it were there too when I was looking for a way to integrate Spring with GWT (had to figure it out the hard way….)
Not to mention, I work for Google, so it’s always nice to see that people like our stuff and ‘get it’ 🙂
A minor nit-pick: at first, I was unable to compile the server-side classes, and had to modify the ant file as follows:
1. add a variable to point to Tomcat’s shared libs:
2. add servlet-api.jar to the build path:
…
there’s no need to add servlet-api.jar in the WEB-INF/lib dir, as Tomcat will provide those classes for you at runtime
3. you only need to compile the server classses, not everything:
[in a real-world app, it’s likely you would have ‘shared’ Java classes – most likely somewhere like org.example.gwtwisdom.shared.* – so you would add those here too]
The one real issue here, however, is that you can’t debug the server-side classes from within Eclipse – only the client-side classes are available for inspection when running hosted mode.
The one solution (I am guessing here, as I haven’t tried it myself yet) would be to run two instances of Eclipse, one running the app inside an Eclipse-configured Tomcat instance (although, it may get a bit awkward how to deploy the classes / scripts).
Would be good to know if you’ve found a solution to this.
September 1, 2008 at 1:16 am
[…] Giving GWT a Spring in its Step Although there are other guides out there, David Kuhn has written a nice article on integrating GWT and Spring. […]
September 2, 2008 at 9:57 am
I think I followed all the instructions but I get two alerts from Eclipse, in GwtRpcController.java: “the serializable class GwtRpcController does not declare a static final serialVersionUID field of type long” (in line 18); “Class is a raw type. References to generic type Class should be parameterized” (in line 25). And I get this failure response in GwtWisdom execution: “Failed to get a quote”. Can someone explain to me what can I do to fix this?
September 2, 2008 at 10:47 am
They’re two very strange errors to be having. I have to ask; Why is eclipse complaining that the GwtRpcController needs a serialVersionUID field? This class isn’t intended to be serializable. Furthermore, this class isn’t generic so it should require any such declaration of type.
Have you changed the class at all from the example?
September 2, 2008 at 9:51 pm
No. I just get the files from the package war. But even if I copy & paste the code from this article, I get the same alerts. I thought that could be a Eclipse bug, but the application doesn´t work directly in Tomcat too, returning the failure message I said.
September 4, 2008 at 3:01 am
Some help please send to rcc.gmr@gmail.com
September 4, 2008 at 8:53 am
Well, I get this running! Eclipse still shows alerts in GwtRpcController.java, but they aren´t relevant for the execution of the application.
The problem was in build.xml, where I forgot to change some paths. It´s everything ok, now.
Thanks David for this article. It´s excellent.
September 4, 2008 at 9:26 am
My apologies rccgmr, I just checked the code again and you’re right I am getting those warnings. As you said though, it shouldn’t affect the operation of the code, but may stop you from compiling depending on how aggressive you have your compiler set (i.e. treat warnings as errors).
September 6, 2008 at 1:39 am
Very nice post, it made setting things up pretty easy. I ran into some issues with the serialization policy when using files implementing Serializable instead of isSerializable. It wouldn’t find/load the autogenerated .gwt.rpc serialization whitelist. I had to make the following change to get it to work:
@Override
public String processCall(String payload) throws SerializationException {
try {
RPCRequest rpcRequest = RPC.decodeRequest(payload,
this.remoteServiceClass, this);
// delegate work to the spring injected service
return RPC.invokeAndEncodeResponse(this.remoteService, rpcRequest
.getMethod(), rpcRequest.getParameters(), rpcRequest.getSerializationPolicy());
} catch (IncompatibleRemoteServiceException ex) {
getServletContext()
.log(
“An IncompatibleRemoteServiceException was thrown while processing this call.”,
ex);
return RPC.encodeResponseForFailure(null, ex);
}
}
September 6, 2008 at 5:53 am
I was also getting the “Failed to get a quote” error – but then I realised that I hadn’t read the acticle closely enough. I was using Tomcat 5.5.26. As soon as I moved to Tomcat 6.0.18 – it worked!. x.
September 7, 2008 at 7:18 am
Thanks Andrew, yeah I’ve since run into that problem after upgrading from RC2 to the final GWT 1.5 release. Thanks for posting the solution. I’ll update the article when I get a chance.
September 7, 2008 at 2:07 pm
Nice Article!
I would like to add that GwtWisdom.gwt.xml doesn’t need and more importantly, should not have the
sevlet
defined. That is supposed to be used when you’re using the internal Tomcat with GWT and moreover,QuoteServiceImpl
doesn’t extendRemoteServiceServlet
.@rccgmr
Those two warning that you’re getting, when you’re defining your variables, try using this:
private static final long serialVersionUID = 1L;
private ServletContext servletContext;
private RemoteService remoteService;
private Class remoteServiceClass;
The first line should clear up your serialization problem because
RemoteServiceServlet
extendsHttpServlet
, andHttpServlet
implementsSerializable
. The last line should clear up your “Class is a raw type. References to generic type Class should be parameterized” problem.For future problems like that, if you hit cnt+1 or cmd+1 on a mac, Eclipse will give you options on how to fix things like that.
September 7, 2008 at 2:09 pm
Crap….some of the stuff I wrote had some bad formatting.
private Class remoteServiceClass;
should read
private Class<? extends RemoteService> remoteServiceClass;
September 16, 2008 at 9:01 pm
thanks for the interesting and useful topic
i try to do the project step by step , everything work fine until i tried to run my application in the host mode using my eclipse run manager ..don’t i need to tell the GWT host where my tomcat is located ??
September 18, 2008 at 6:33 pm
in the host mode the web.xml is generated by the GWTshell so what to do so i can run my application in the host mode?? how can i tell the GWTshell to use my web.xml ??
September 24, 2008 at 4:55 pm
Thank you for taking the time to write this article. It was a big help as I learn GWT-Spring integration. Let me see if I can reciprocate for folks who may have had the same problem I had.
With your example source, the onFailure() kept getting invoked in the callback for me. Further inspection found that it “could not find the spring servlet”. I’m not sure if I used a cannon to kill a mosquito, but here is what I ended up doing to get the GWTWisdom example to work for me in a nutshell:
– Downloaded the GWT Server Library (http://gwt-widget.sourceforge.net/). I used version 0.1.5a.
– Integrated their JAR files (specifically gwt-sl-0.1.5a.jar and commons-logging-1.1jars) into my WEB-INF/lib and used their handler instead of your custom written GwtRpcController.
– Modified my web.xml and spring-servlet.xml files to map to these new classes. It slimmed down the complexities a bit I think. The gwt-sl JAR file complained of a lack of application context XML file, so I went ahead and created an applicationContext.xml and moved the QuoteServiceImpl bean mapping over to it.
And that’s it, seems to run fine. I didn’t try this in hosted mode, I just used a fully built WAR and dropped it into an external Tomcat 6.0.18 server. For completeness, I’m using Eclipse (Ganymede) and GWT 1.5.2 (on Windows).
If you are also suffering from this problem, my solution may help. If you are like me, you would probably find a working source far more helpful than my chatter above, so here it is: http://dl.getdropbox.com/u/114750/gwt-wisdom.zip
Hope this helps.. thanks again for the time it took to write this tutorial.
September 24, 2008 at 5:01 pm
Dropbox’s public HTML link seems to be broken at the time of this writing, so if you have problems with the above link you can grab it here:
http://www.fredhat.com/stuff/gwt-wisdom.zip
September 28, 2008 at 1:43 am
Hi I’ve been getting this error on my mac (using eclipse)
Buildfile: /Users/andrewthomas/Documents/projects/gwt-wisdom/build.xml
compile:
[java] Exception in thread "main" java.lang.NoClassDefFoundError: com/google/gwt/dev/GWTCompiler
[java] Java Result: 1
BUILD SUCCESSFUL
Total time: 686 milliseconds
I’ve tried every which way to get it going but dont seem to be able to do it. I’ve basically just downloaded the raw source code.
My new build file looks like this
Buildfile: /Users/andrewthomas/Documents/projects/gwt-wisdom/build.xml
compile:
[java] Exception in thread "main" java.lang.NoClassDefFoundError: com/google/gwt/dev/GWTCompiler
[java] Java Result: 1
BUILD SUCCESSFUL
Total time: 686 milliseconds
Any Ideas, it’s driving me nuts 🙂
September 28, 2008 at 1:44 am
Sorry this is my build.xml
Build file. This is used to package up your project as a war, if you
want to distribute/deploy it. This isn't needed for normal operation.
September 28, 2008 at 8:56 am
Hey Andy,
I’d suggest you check that the gwt.home property at the top of the build file is pointing to your copy of GWT. Also check that the platform property is set to windows, linux or mac depending on what you’re developing on.
The error your getting relates to java not being able to find the GWT compiler on the classpath. Providing you’ve made no other significant changes to the build file, following the above instructions should solve your problem.
Regards,
Dave
September 28, 2008 at 6:49 pm
Hi Dave
Thanks, my bad. I’d done everything you said above earlier I’d just forgotten to copy the lib jar files into the WEB-INF structure …. that’ll teach me to follow instructions properly 🙂
It works an absolute treat!!! great article, fantastic for newbies like me
Any
October 7, 2008 at 7:00 pm
Hi all,
Very nice article. I am using Maven2 instead of Ant to build the project, and I get the next runtime error in GWT Shell console: “Not compatible with HttpSevlet: org.example.gwtwisdom.server.QuoteServiceImpl (does your service extend RemoteServiceServlet?) Unable to dispath request”. In the browser: “Failed to get a quote”. I think I`ve not configure the pom.xml correctly:
com.totsp.gwt
maven-googlewebtoolkit2-plugin
2.0-beta24
${basedir}/src/main/webapp/WEB-INF/web.xml
INFO
org.example.gwtwisdom.GwtWisdom
org.example.gwtwisdom.GwtWisdom/GwtWisdom.html
DETAILED
false
-Xmx512m
${gwtVersion}
mergewebxml
gwt
compile
Thank you very much
November 8, 2008 at 3:57 pm
great tutorial, i am able to do it one hour……..thanks
November 28, 2008 at 3:56 am
great job!
I just have one concern. Let’s say I added a property ‘author’ on QuoteServiceImpl. If I inject a value for the property ‘author’ from the spring-servlet.xml, how can I get the value of the ‘author’ from QuoteServiceImpl?
public class QuoteServiceImpl extends RemoteServiceServlet implements QuoteService {
private String author;
….
public Quote getQuote()
{
System.out.println(author); // what will be the value of author here?
return new Quote(quotes.get(randomizer.nextInt(quotes.size())));
}
public void setAuthor(String author){
this.author = author;
}
}
added/modified in to spring-servlet.xml
thanks.
November 28, 2008 at 3:58 am
added/modified in spring-servlet.xml:
December 8, 2008 at 3:05 am
Now that it’s December of 2008, and presumably things change fairly often, is this still the preferred way to integrate Spring + GWT 1.5?
I would love to know before I begin this endeavor. Thank you
December 11, 2008 at 8:22 pm
What about having Spring in the client as well? Do you think this would work?
http://springframework.me/
December 24, 2008 at 2:00 pm
Great informative article . Very useful to add.
Just to add more about spring annotations too ( since 2.5 release ) – we can specify as follows.
In spring-servlet.xml –
GwtRpcController,java :
===============
This could injected via annotation as follows.
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
@Service(“loginController”)
public class GwtRpcController extends RemoteServiceServlet .. {
@Autowired
private RemoteService remoteService;
.
.
.
}
QuoteServiceImpl.java:
================
@Service(“remoteService”)
public class QuoteServiceImpl implements QuoteService {
}
This gets rid of the bean configuration and playing around with annotations only from hereon.
March 11, 2009 at 4:05 pm
Hello, I followed this tutorial and very glad to use Spring and GWT RPC.
But, I need the HttpSession inside my RPC server implementation.
It doesn’t really work.
Help !!!
March 11, 2009 at 6:08 pm
Hi sahlouls,
Getting access to the HttpSession object isn’t difficult but it requires you to modify the GwtRpcController slightly. Firstly you’ll need to create an interface called SessionAware. This interface has one method defined:
void setSession(HttpSession session);
Secondly you’ll need to implement this interface within your server side RemoteService implementation so that you can inject the session object.
Lastly you’ll need to modify the GwtRpcController service to check if the injected RemoteService instance is also an instance of SessionAware like so:
// inject session variable into remote services handler if session aware
if (remoteService instanceof SessionAware) {
((SessionAware) remoteService).setSession(request.getSession());
}
This needs to go between the decode step and before the invokeAndEncodeResponse in the processCall method.
Dave.
March 13, 2009 at 7:47 am
Hi,
I’m new to GWT and I was trying to get a simple app that will use GWT+Spring+Maven. I was able to find a suitable example on the internet for GWT+Spring+Maven, that also work. THe issue is that when I’m trying to define new beans and inject them in the exsiting GWT ones, the DI doesn’t work as expected. I am getting no errors though, just null values.
The example was taken from this site. I had to tweak it a little bit to work properly. To that app I was trying to add a BO layer and a DAO layer.
Any suggestions how could I register&inject those beans (myObjectDAO and myObjectBO) into “quoteService”? “quoteService” bean is registered and injected properly in “quoteController”. I do have the setters properly in place for the properties in the bean class, otherwise spring would complained.
Thank you.
===========================================================
service-context.xml
===========================================================
classpath:service-placeholder.properties
<!–
–>
===========================================================
spring-servlet.xml
===========================================================
/**/quote.rpc=quoteController
===========================================================
web.xml
===========================================================
Sample
index.html
contextConfigLocation
classpath:service-context.xml,
classpath:spring-servlet.xml
org.springframework.web.context.ContextLoaderListener
<!–
org.springframework.web.context.request.RequestContextListener
–>
spring
org.springframework.web.servlet.DispatcherServlet
1
spring
*.rpc
March 13, 2009 at 7:51 am
I’ll post again the code:
===========================================================
service-context.xml
===========================================================
<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE beans PUBLIC “-//SPRING//DTD BEAN//EN” “http://www.springframework.org/dtd/spring-beans.dtd”>
<beans>
<bean id=”quoteService” class=”com.totsp.sample.client.QuoteServiceImpl”>
<property name=”myObjBO”>
<ref bean=”myObjectBO” />
</property>
</bean>
<bean id=”salesproServicePlaceholder” class=”org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”>
<property name=”ignoreUnresolvablePlaceholders” value=”true”/>
<property name=”location”>
<value>classpath:service-placeholder.properties</value>
</property>
</bean>
<bean id=”myObjectDAO” class=”com.totsp.sample.dao.MyObjectDAOImpl”>
<!–
<property name=”sqlMapClient”>
<ref bean=”sqlMapClient” />
</property>
–>
</bean>
<bean id=”myObjectBO” class=”com.totsp.sample.bo.MyObjectBOImpl”>
<property name=”myObjectDAO”>
<ref bean=”myObjectDAO” />
</property>
</bean>
</beans>
===========================================================
spring-servlet.xml
===========================================================
<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd“>
<!– The application context definition for the DispatcherServlet –>
<!– Maps the request through to a concrete controller instance –>
<bean id=”urlMapping” class=”org.springframework.web.servlet.handler.SimpleUrlHandlerMapping”>
<property name=”mappings”>
<value>
/**/quote.rpc=quoteController
</value>
</property>
</bean>
<!– GwtRpcController wraps our service in order to decode the incoming –>
<!– request then delegates processing of the call to the POJO service –>
<!– and then encodes the return value forwarding the response. –>
<bean id=”quoteController” class=”com.totsp.sample.client.GwtRpcController”>
<property name=”remoteService”>
<ref bean=”quoteService” />
</property>
</bean>
</beans>
===========================================================
web.xml
===========================================================
<?xml version=”1.0″ encoding=”UTF-8″?>
<web-app version=”2.4″ xmlns=”http://java.sun.com/xml/ns/j2ee”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd“>
<display-name>Sample</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:service-context.xml,
classpath:spring-servlet.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!–
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
–>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.rpc</url-pattern>
</servlet-mapping>
</web-app>
March 13, 2009 at 8:35 am
Hi Christian,
It’s a bit hard to tell what’s wrong without seeing what your QuoteServiceImpl class looks like. The service context looks okay, my only question is have you got a setter method on the quote service that looks something like setMyObjBO(MyObjectBO bo)?
Dave.
March 13, 2009 at 11:59 pm
Hi Dave,
here’s my QuoteServiceImpl class:
package com.totsp.sample.client;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.totsp.sample.bo.IMyObjectBO;
public class QuoteServiceImpl extends RemoteServiceServlet implements QuoteService {
private Random randomizer = new Random();
private static List quotes = new ArrayList();
private IMyObjectBO myObjBO = null;
static {
quotes.add(“No great thing is created suddenly – Epictetus”);
quotes.add(“Well done is better than well said – Ben Franklin”);
quotes.add(“No wind favors he who has no destined port – Montaigne”);
quotes.add(“Sometimes even to live is an act of courage – Seneca”);
quotes.add(“Know thyself – Socrates”);
}
public void setMyObjBO(IMyObjectBO myObjBO) {
this.myObjBO = myObjBO;
}
public String getQuote()
{
return quotes.get(randomizer.nextInt(quotes.size()));
}
}
I set a breakpoint on the setter of myObjBO and the getQuote method. On initializing the context I’m getting the breakpoint from the setter for myObjBO been invoked and I see that property been injected with correct value. But, when the getQuote method is been invoked, the myObjBO is null. So somewhere in the middle (I cannot find exactly where ) the spring bean myObjBO is been wipe out (??) and not injected anymore. Is there any process in place that keep active the beans that extends the RemoteServiceServlet while the app is running? Any ideas?
Thank you,
Cristian
March 24, 2009 at 10:20 am
Hello,
is possible to deploy project directly with the help of Eclipse IDE ? Now when i develop some changes on server code, i have to run ant script and then deploy it and then restart tomcat – and thats time-consuming operation. Do you have some tips ? Thank you !
March 24, 2009 at 10:19 pm
Hi Martin,
The short answer is yes. It is possible to create a GWT project that integrates directly with the Eclipse WTP (Web Tools) features. If you do this then you’ll be able to add your web project to your Tomcat instance in the server view like any other normal web project. I’ve got a couple that work this way at the moment. It’s not exactly straight forward though and requires some knowledge of how to wire up the launch configuration properly.
I’ll see if I can get some time to write up a tutorial on this, however In the mean time experiment with creating a normal “Dynamic Web Project” and then shoehorning it’s package structure to look like a GWT project. It should include your module file and anything else you’d find in a normal GWT project. You’ll then need to modify the build script I provide in this tutorial slightly to compile the GWT app and copy the contents of the build into the “WebContent” dir. Once that’s done you’ll need to add your project to the server. Once you’ve done that you can create a custom launch configuration that will launch the hosted mode browser using the -noserver flag. Then start up your server, run your custom launch config and you should have a full fledged working GWT debugger which is properly integrated into eclipse. Even better, you can make code changes on the fly and refresh the hosted mode browser and your changes will immediately take effect.
Good luck mate.
March 24, 2009 at 10:26 pm
Thank you ! i will try it soon.
March 25, 2009 at 10:12 am
I created WTP project and copied GWT into it and project runs ! but in browser i see this :
Failed to get a quote: The call failed on the server; see server log for details
and in console :
SEVERE: Exception while dispatching incoming RPC call
java.lang.RuntimeException: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at org.gwtwidgets.server.spring.GWTRPCServiceExporter.handleExporterProcessingException(GWTRPCServiceExporter.java:344)
at org.gwtwidgets.server.spring.GWTRPCServiceExporter.processCall(GWTRPCServiceExporter.java:313)
And thats quite strange…
Could you give me a hint what could be wrong ? (…or send me your project which already works 🙂 ) Have a nice day. Thanks.
April 3, 2009 at 3:03 am
Hello,
Thanks for this article!
With this system, if I have an hibernate exception for example, can I have say to the user (client-side) that is an hibernate exception and not just “The call failed on the server; see server log for details”?
April 4, 2009 at 1:42 pm
Hi Justin,
Typically GWT can only move classes that implement IsSerializable across the wire. If you wish to expose an exception you’ll have to wrap it in a custom Exception class that implements IsSerializable for it to be passed across.
Just as an aside, I wouldn’t normally recommend exposing your users to the type of exceptions that are occurring. It’s bad from a UI design perspective and bad from a security standpoint (knowledge is power to a hacker). If it’s for debugging purposes to make your life easier I’d generally suggest server-side logging as the preferred alternative. That said, I don’t know the context of what you’re trying to do and I’m only making a general recommendation.
Dave
April 7, 2009 at 3:24 am
Attn: Fred and David,
Thank you, David for the article. I’m kinda bummed, cuz I still can’t get it to work. Thank you too, Fred for your contribution.
Platform: OS-X 10.5; IDE: Intellij JetBrains. GWT: 1.5.3, Java 1.5; deploying on tomcat 6.0.18 using ant.
Here’s what I’ve done so far:
1. I implemented it just as you said in the main article, after trying to get it to work for a few hours, I continued reading.
2. Found the comments about using 1.5 and the changes recommended. Did that. Still no luck.
3. Saw Fred’s September 24, 2008 at 4:55 pm and started over. I downloaded his code and attempted to deploy (as-is) No luck.
What I think is going on, is that nocache.js is not getting picked up. The html loads fine, but nothing happens. No compile or deployment errors. I’m hoping you guys can help me out.
As I said, I am using Fred’s example project as-is, so if you need to peak at the config/src files, just follow the like so kindly provided by Fred.
I’m sure it is probably some newbi thing, so I’ll keep looking and post the results if I have any success.
Thanks in advance for your help, and again for your willingness to share your knowledge.
Sincerely,
Sam
Thanks
April 7, 2009 at 3:58 am
Ahh….sweet success….
My deployment descriptors were fubar’d.
Crisis averted! Thanks again, guys!
Sam
April 7, 2009 at 3:04 pm
Hi Sam,
What exactly did you do to fix this problem. I am seeing the exact thing. I have been chasing this issue for weeks. I get the following message when I attempt to issue an RPC call from my client. The works in gwt hosted mode:
Here is the message I get:
Apr 6, 2009 10:53:16 PM org.apache.catalina.core.ApplicationContext log
SEVERE: Exception while dispatching incoming RPC call
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)
April 8, 2009 at 5:17 am
Bummer, that’s completely different than the problem I was having.
Based on the error, I suspect you may have some naming issues. Did you use the source from Fred?
I suggest using that source, and get it working as-is.
Sam
April 22, 2009 at 6:43 pm
[…] are already there and work amazingly well, if not quite out-of-the-box. For example, check out Giving GWT a Spring in its Step and […]
April 25, 2009 at 8:49 am
This was a really helpful article, thanks!
April 28, 2009 at 3:49 pm
When i run my app i get this error
[WARN] Nested in javax.servlet.ServletException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘quoteController’ defined in ServletContext resource [/WEB-INF/Test-servlet.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property ‘remoteService’ threw exception; nested exception is java.lang.NullPointerException:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘quoteController’ defined in ServletContext resource [/WEB-INF/Test-servlet.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property ‘remoteService’ threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1129)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:861)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:421)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:251)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:156)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:248)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:733)
at org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler(AbstractUrlHandlerMapping.java:256)
at org.springframework.web.servlet.handler.SimpleUrlHandlerMapping.registerHandlers(SimpleUrlHandlerMapping.java:125)
at org.springframework.web.servlet.handler.SimpleUrlHandlerMapping.initApplicationContext(SimpleUrlHandlerMapping.java:103)
at org.springframework.context.support.ApplicationObjectSupport.setApplicationContext(ApplicationObjectSupport.java:73)
at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:72)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:301)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1167)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:425)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:251)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:156)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:248)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:287)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:352)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:331)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:265)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:235)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:126)
at javax.servlet.GenericServlet.init(GenericServlet.java:212)
at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:433)
Here is some of my configurations
web.xml
Test
org.springframework.web.servlet.DispatcherServlet
1
Test
*.rpc
Test-servlet.xml (Spring beans configurations)
/**/quote.rpc=quoteController
GWTSpring.gwt.xml
April 28, 2009 at 3:52 pm
My configurations
web.xml
Test
org.springframework.web.servlet.DispatcherServlet
1
Test
*.rpc
/**/quote.rpc=quoteController
April 29, 2009 at 4:37 am
How could you convince somebody who want to use Spring to combine it with GWT? What can GWT do what Spring with its built-in AJAX capability can’t?
The intention behind this question: I want to use GWT with Spring at work. How could I convince my colleagues?
April 30, 2009 at 1:21 pm
First off, thanks for the great article. It was immensely helpful in setting up Spring + Hibernate + GWT.
Getting a GWT SerializationException “was not assignable to ‘com.google.gwt.user.client.rpc.IsSerializable’ and did not have a custom field serializer”, complaining about not implement IsSerializable when the GWT documentation clearly states the java.io.Serializable should work?
GWT isn’t the issue… it’s the controller implementation unfortunately.
Try modifying the GWTRpcController processCall method to the following:
@Override
public String processCall(String payload) throws SerializationException {
try {
RPCRequest rpcRequest = RPC.decodeRequest(payload, remoteServiceClass, this);
onAfterRequestDeserialized(rpcRequest);
return RPC.invokeAndEncodeResponse(this.remoteService, rpcRequest.getMethod(),
rpcRequest.getParameters(), rpcRequest.getSerializationPolicy());
} catch (IncompatibleRemoteServiceException ex) {
log(“An IncompatibleRemoteServiceException was thrown while processing this call.”, ex);
return RPC.encodeResponseForFailure(null, ex);
}
}
The issue is that the code does not pass on the security serialization policy (configured by a file generated by GWT with the extension .gwt.rpc). This processCall method fixes that small issue.
It’s just a copy/paste of the super class (with the same enhancements as outlined by the article), but it fixed the issue for me.
Cheers
May 3, 2009 at 4:04 pm
Your example has one logical wart; the QuoteServiceImpl class needs to extend the QuoteService interface and therefore the RemoteService interface in GWT. Therefore, your Spring service classes depend on GWT, even though nothing in them refers to GWT at all. In my work project, the service I am exposing is in another jar file in a project with no knowledge of the UI, and so I want to remove the dependency.
A coworker wrapped the Spring service in a GWT-aware service, but then one needs to handle transactionality twice. I sought a different solution by trying to use Spring AOP and introductions. However, that failed, because Spring AOP can only add interfaces to classes when there is a specific implementation class for it. However, AspectJ load-time weaving works well. I set up the system for LTW, added a simple aspect class:
package org.example.gwtwisdom.server;
@Aspect
public class QuoteIntroduction{
@DeclareParents(QuoteServiceImpl.class)
private QuoteService service;
}
and added an aop.xml file invoking this aspect. I could then remove the ‘implements QuoteService’ from the QuoteServiceImpl code, removing the GWT association.
May 7, 2009 at 3:37 am
Super article, thank you. However I keep getting failed to get a quote error. I am using tomcat 6.0x and build compiles without an error. I changed the gwt path, but nothing changed even when I downloaded the project war. Any suggestions? where should i be looking to solve this problem??
Cheers,
Veronica
May 15, 2009 at 12:08 am
Excellent article. Thanks.
August 11, 2009 at 6:40 pm
Hi,
using the autowiring bean factory to have the rpc impl autowired is IMHO an easier approach:
http://pgt.de/2009/07/17/non-invasive-gwt-and-spring-integration-reloaded/
September 4, 2009 at 2:27 pm
Great work .
Very clear and to the point
Cheers
Rajneesh
September 8, 2009 at 11:11 am
im facing the same problem reported previously by ” Sam Loy Says April 7, 2009 at 3:24 am “.
that is, i invoke the “http://localhost:8080/GwtWisdom/GwtWisdom.html” servlet but nothing happens after that. no errors or exceptions in the logs.
September 26, 2009 at 7:31 am
I have the same problem like Cristian has. The problem is double instantiation of RemoteService. First instantiation I have from Spring IoC but the second instantiation – from GWT (my suggestion). Spring, of course, does correct initialization, but GWT doesn’t create any parameter injection.
So, GwtRpcController doesn’t invoked when I do RPC request to a server.
Any suggestions?
September 26, 2009 at 7:47 am
Ok, all works fine now!
The problem – my incorrect URL mapping in web.xml.
Thanks again, David
November 1, 2009 at 6:45 am
quiza sabes, pero tu pagina se ve raro en Safari en un Mac.,
November 28, 2009 at 12:20 am
Hello,
When I try to run ant I have this error :
javax.servlet does not exist
When I try to run hosted mode I have this one :
[ERROR] Not compatible with HttpServlet: biz.manex.chbah.crc.web.server.CRCServiceImpl (does your service extend RemoteServiceServlet?)
[ERROR] Unable to dispatch request
January 12, 2010 at 6:26 pm
Great article, althought i takes a while to understand if you get it from scratch.
Best regards
January 15, 2010 at 11:16 pm
[…] всякие инструменты. Сейчас иду шаг за шагом по мануалу с поправкой на то, что версия давно уже не 1.5 а 2.0, и […]
January 23, 2010 at 5:21 am
Very nice artcile. it helped me a lot
April 28, 2010 at 8:51 am
Now that we have GWT 2 and Spring 3, has anyone tried this lately?
May 7, 2010 at 11:15 pm
This integration works and helped me a lot but after integration this.getThreadLocalRequest() method invocation in my serviceImpl class returns null. Please help
May 17, 2010 at 7:40 pm
Hi ..
Great article..I see a lot of people here have got prob with the execution of the code given… specially the “Failed to get a quote” issue, has any one come out with a solution for this.. I am using tomcat 6.0.10 so the version should not be the issue.. If any one had cracked this please reply..
May 22, 2010 at 3:22 am
>> “Failed to get a quote”
I managed to get it working with Spring 3.x & GWT 2.x. & Tomcat 6.0.26. The example still works great and made me save a lot of time and hassle, now I’m up to getting a MAVEN build for the project.
To overcome the :
“Not compatible with HttpSevlet: org.example.gwtwisdom.server.QuoteServiceImpl (does your service extend RemoteServiceServlet?) Unable to dispath request” (you’ll see this in the Tomcat log). In the browser: “Failed to get a quote” . I did what Tomcat asked:
public class QuoteServiceImpl extends RemoteServiceServlet implements QuoteService
{
….
}
i.e. extend the RemoteServiceServlet and voilà! Everything is running smoothly.
May 24, 2010 at 12:09 pm
[…] LinkedIn […]
June 28, 2010 at 7:43 am
Really a nice explanation. This had helped me a lot in understanding the approach in integrating spring & gwt. Probably similar approaches are followed in GWT-SL libraries, and now they (GWT-SL) have some advanced one too.
August 23, 2010 at 2:03 pm
Thanks a bunch.. This helped me out a lot..
August 26, 2010 at 6:50 am
Incredibly helpful. I didn’t — at all — expect it to compile and run smoothly when but (minus one typo), it ran flawlessly.
I looked around for a “Donate” button on your page but couldn’t find anything. Any way to buy you a PayPal beer?
December 24, 2010 at 7:26 pm
[…] giving-gwt-a-spring-in-its-step […]
March 30, 2011 at 5:04 am
A gift that keeps giving! Thanks bro, this was very helpful!
May 14, 2011 at 6:30 pm
I never thought of it that way, well put!
June 2, 2011 at 12:11 pm
Всем Привет! Кто знает где находится село дебесы?.
September 22, 2011 at 9:19 pm
Hi
Thanks a lot for this example,which helps me alot..have a click on the spring-gwt integration..
September 30, 2011 at 6:23 pm
Thanks a lot guys…My head was running hot for last three days..It did work now…Let me know if any of you facing some issue at parry.ism@gmail.com
November 1, 2011 at 12:38 am
that was pretty cool?Did anyone use maven for build instead any lucks i am gonna try out maven and see if i meet the success.
November 16, 2011 at 5:18 pm
Thanks a lot for that. Apparently the source code link is broken, where can I get it?
November 21, 2011 at 7:52 am
Looks like you’re right Harvey, Mediafire seem to have ditched all my files. Shame, it’s so long ago now that I no longer have the code.
Things have come a long way with Spring and GWT since I first wrote this article. I’d suggest perhaps checking out Spring Roo’s GWT integration and some more modern approaches to doing this using Aspects and Annotations these days.
-Dave
December 8, 2011 at 2:23 am
thank you so much for a very nice articale
January 16, 2012 at 3:51 am
. .
- , - ,
, :
. , .
XXI .
, , ,
.
. , ,
- , ... , , . , , - . , : , , , , . , . .
, .
, ,
. ,
.
January 19, 2012 at 11:32 pm
Is possible to do the same with annotated (@Controller annotation) Controller that can have more mapped to it path (RESTful) ?
January 20, 2012 at 4:46 am
I don’t see why you couldn’t. It’s been a while since I’ve written anything with Spring though and I haven’t tried that approach.
Let me know what you discover!
January 23, 2012 at 5:42 pm
Thanks for that article. Very good approach.
Thank to Paul Martin for Your patch to GWTRpcController 🙂 Now i have working GWT (2.4) + Spring + Hibernate app.
You can clone my working skeleton app from: https://github.com/marioosh-net/GWT/tree/master/gwt-spring
May 29, 2012 at 2:32 pm
[…] are links to some resources – https://technophiliac.wordpress.com/2008/08/24/giving-gwt-a-spring-in-its-step/ and Experiences with integrating spring 3 mvc with GWT? . Tagged: GWTJavaquestionsspring […]
July 16, 2012 at 7:04 pm
dg
August 31, 2012 at 3:34 am
Sir ur tutorial really helped me alot. thank u so much for this wonderful n simple easy to understand tutorial.
though i have doubt in the flow of the application.;….well as we deploy it on server,i suppose web.xml gets called n then -servlet.xml one… i ‘m not understanding when is gwt.xml is getting called? is it called along with web.xml??
i would be thankful if u can explain me the control in the application
thank u.
February 9, 2013 at 9:06 pm
I love your blog.. very nice colors & theme.
Did you design this website yourself or did you hire someone to do it for you?
Plz reply as I’m looking to construct my own blog and would like to know where u got this from. thank you
February 19, 2013 at 7:46 am
Thanks, it’s just one of the standard wordpress themes.
May 25, 2013 at 3:30 pm
Thankyou very much sir. You saved my day
September 14, 2013 at 2:28 am
Thanks for the tutuorial. Very interesting reading.
One note. Why don’t you make RemoteServiceServlet as a field of the controller? You use RemoteServiceServlet(remoteService) . So you don’t need to override method because RemoteServiceServlet will use service that you passed to it in the constructor.
It would be then simple like that:
public class GwtRpcController implements
Controller, ServletContextAware {
private ServletContext servletContext;
RemoteServiceServlet delegateServlet;
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
delegateServlet.doPost(request, response);
return null;
}
@Override
public ServletContext getServletContext() {
return servletContext;
}
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
public void setRemoteService(RemoteService remoteService) {
this.remoteService = remoteService;
this.remoteServiceClass = this.remoteService.getClass();
}
}
September 14, 2013 at 2:31 am
Forgot about setRemoteService():
public void setRemoteService(RemoteService remoteService) {
this.delegateServlet = new RemoteServiceServlet(remoteService);
}
September 22, 2013 at 9:25 pm
Thanks Aleksey. Have you tested this code, does it work?
It’s been so long since I wrote this that I can hardly recall why I implemented it the way I did. Something tells me you’re still going to need to override RemoteServiceServlet.processCall in order to delegate to the injected service. Has something changed in recent versions of GWT that means this is no longer necessary?
September 23, 2013 at 5:03 pm
Hi Dave. Thanks for the reply.
No, I did not test this. That is my guess which I made by looking at GWT source code. It must be that the overloaded constructor appeared in the new version of the library.
March 17, 2015 at 11:03 am
[…] using GWT (2.4) with Spring integrated as in this article. I have problem with getting list of User from database (Hibernate) and populate DataGrid with it. […]
May 7, 2015 at 6:17 am
Excellent writeup! I’ve applied it, and am pleased with the results.
I may not be obvious to some that in order for GWT remote logging to work, you will have to create and use an implementation of RemoteLoggingService which does not extend RemoteServiceServlet.
December 10, 2017 at 12:35 am
[…] used by GWT and instead create your own Spring controller to handle incoming GWT-RPC requests. This blog post was the key to integrating the two […]
February 26, 2019 at 7:53 am
[…] usando GWT (2.4) con Molla integrata come in questo articolo. Ho un problema con ottenere l’elenco di Utente dal database (Hibernate) e popolare DataGrid. […]
January 10, 2021 at 5:55 pm
[…] 我想知道如何将Spring与GWT集成。是否需要像this post中那样实现GWT控制器?如果是这样,此控制器和我现有的控制器是否应该放在单独的模块中? […]