Using Spring MVC Controllers in Grails
Update 03/22/2010: As of version 1.2 Grails has support for Spring MVC controllers; check out the 1.2 release notes
Groovy is slower than Java and sometimes dramatically slower. Realistically, this has little impact on a web application since response time is affected more by the database and network latency, so as long as the slowdown isn't too dramatic, the benefits of Groovy and Grails far outweigh these concerns. And Grails is still way faster than Rails
But having said that, I was wondering how to use a regular Java Spring MVC controller
and JSP instead of a Grails controller and a GSP (both of which use Groovy). Turns out it's pretty easy:
-
Register the traditional Spring dispatcher servlet in
web.xml(you'll need to have rungrails install-templates). In this example the name (SpringMVC) isn't important, use whatever you want, and I've chosen to map *.action URLs to this controller and let Grails handle the rest:
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
- Generate web-app/WEB-INF/SpringMVC-servlet.xml:
<beans xmlns='http://www.springframework.org/schema/beans'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:p='http://www.springframework.org/schema/p'
xmlns:lang='http://www.springframework.org/schema/lang'
xsi:schemaLocation='
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang-2.5.xsd'>
<bean id='mvcHandlerMapping'
class='org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping'
p:order='1'>
<property name='interceptors'>
<list>
<ref bean='openSessionInViewInterceptor' />
<ref bean='localeChangeInterceptor' />
</list>
</property>
</bean>
<bean id='mvcViewResolver'
class='org.springframework.web.servlet.view.UrlBasedViewResolver'
p:viewClass='org.springframework.web.servlet.view.InternalResourceView'
p:order='1'
p:prefix='/WEB-INF/jsp/'
p:suffix='.jsp'
/>
<bean name='baseSimpleController' abstract='true' p:cacheSeconds='0'/>
<bean name='jspController'
class='com.foo.spring.controller.JspController'
parent='baseSimpleController'
abstract='true'
/>
<!-- actions -->
<bean name='/test.action'
class='com.foo.spring.controller.TestController'
parent='baseSimpleController'
p:successView='test'
/>
<bean name='/other.action' parent='jspController' p:successView='other' />
</beans>
And that's it. Some notes:
- the handler mapping uses the id
mvcHandlerMappingsince Grails will create one using the standard name ofhandlerMapping - since handler mappings are auto-discovered by default, you need to set the
orderattribute to something lower than the Grails mapping's (which uses the default value ofInteger.MAX_VALUE) so this mapping is accessed first - the
HandlerInterceptors that are configured for the Grails mapping (OpenSessionInView, LocaleChange) won't be automatically available to this mapping, but it's simple to borrow them since they're registered as beans; you can also add other custom interceptors to the list - I've created an optional abstract parent controller bean (
baseSimpleController) for simple controllers (single-page, i.e. not form or wizard controllers) - I've also created a simple controller that just shows a JSP – this is useful for pages that don't have any controller logic:
package com.foo.spring.controller;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;public class JspController extends AbstractController {
private String _successView;
@Override
protected ModelAndView handleRequestInternal(
final HttpServletRequest request,
final HttpServletResponse response) {return new ModelAndView(_successView);
}public void setSuccessView(final String view) {
_successView = view;
}
}
I've mapped two sample URLs – /test.action, which uses a controller, and /other.action, which uses JspController to just show other.jsp.
Note that it is possible to use JSPs with Grails; Grails looks for a GSP using the specified name, but if it doesn't find one it looks for a JSP (under /WEB-INF/grails-app/views/) and uses that if it exists. So another option is to use Grails controllers and JSP.
Big caveat: I haven't used this in production yet – I'm just prototyping so I'll have this available in the future just in case.







March 27th, 2008 21:50
Please — Keep me up to date!!
March 27th, 2008 22:47
Very interesting, was considering the same approach today as well. Nice to see some helpful examples. Keep updating your blog especially if you push this approach to production, would be interested to hear your experiences…
Josh
March 28th, 2008 08:07
Very cool – I’ve been thinking about a Spring MVC + Grails combo for a while, glad to see a write up on how it’s done.
Please post again as you move this into production (or anything else of interest happens)! I’m guessing there are a lot of people in the same boat as myself – an entire app developed in SpringMVC and Hibernate looking for a bit more productivity but not ready to throw everything thing out and start from scratch.
BTW, couldn’t you reuse Spring’s ParameterizableViewController instead of your JspController?
March 28th, 2008 08:16
Jon – thanks for the ParameterizableViewController pointer. It seemed unnecessary to create such a simple controller but I didn’t see that there was one already.
March 28th, 2008 09:45
Have you tried IWebMvc? It’s still Milestone 2 but it may be worth a look if you’re considering Grails + Spring MVC. You can download it from http://code.google.com/p/internna/downloads/list. Please log about your experiences if you try it
August 29th, 2008 01:30
[...] recorded first by o0AnimeMeisje0o on 2008-08-17→ Using Spring MVC Controllers in Grails [...]
April 1st, 2009 13:46
Is this code worked for anybody?
S
April 1st, 2009 13:52
I created a Grails plugin based on this work, see http://grails.org/plugin/springmvc
I haven’t tried it in 1.1, but it was working in 1.0.x
April 1st, 2009 13:57
I dont want to use JDK 1.5 or grails 1.1, I want to use grails 1.0.4 with jdk 1.4.2. In that case @override annnotation is complaining. How to go about that? My deployment environment is Tomcat 5.5
April 1st, 2009 14:53
You can delete the @Override annotations.
April 2nd, 2009 13:21
Burt
Is TestController code is same as JspController?
April 2nd, 2009 13:22
Burt
Is TestController code is similar as JspController?
April 2nd, 2009 13:29
Getting this error:
Caused by: org.springframework.beans.InvalidPropertyException: Invalid property
‘applicationContext’ of bean class [org.aarp.ones.JspController]: Getter for pro
perty ‘applicationContext’ threw exception; nested exception is java.lang.reflec
t.InvocationTargetException
any idea?
April 3rd, 2009 12:37
Do I need to do any changes to applicationContext.xml for SpringMVC configuration?
April 3rd, 2009 19:28
@ayrusna you wouldn’t edit applicationContext.xml, that creates Spring’s parent application context. Your beans go in resources.groovy/resources.xml. The original work was done with Grails 1.0.3 but I just created test apps in 1.0.4 and 1.1 and both worked fine. Could you email your org.aarp.ones.JspController to me (burt at burtbeckwith dot com) and I’ll take a look.